r109673 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r109672‎ | r109673 | r109674 >
Date:03:03, 21 January 2012
Author:gwicke
Status:deferred
Tags:
Comment:
Support empty template arguments and default values in arg expansion
Modified paths:
  • /trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/parse.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.TokenTransformManager.js
@@ -422,7 +422,7 @@
423423 this.tailAccumulator = res.async;
424424 this.tokenCB = res.async.getParentCB ( 'sibling' );
425425 }
426 - this.env.dp('AsyncTokenTransformManager onChunk ' + res.async);
 426+ this.env.dp('AsyncTokenTransformManager onChunk res.async=' + res.async);
427427 //this.phase2TailCB( tokens, true );
428428
429429 // The next processed chunk should call back as a sibling to last
@@ -529,6 +529,12 @@
530530 */
531531 AsyncTokenTransformManager.prototype._returnTokens = function ( tokens, notYetDone ) {
532532 //tokens = this._transformPhase2( this.frame, tokens, this.parentCB );
 533+
 534+ //if ( tokens.length && tokens[tokens.length - 1].type === 'END' ) {
 535+ // this.env.dp( 'AsyncTokenTransformManager, stripping end ' );
 536+ // tokens.pop();
 537+ //}
 538+
533539 this.env.dp('AsyncTokenTransformManager._returnTokens, emitting chunk: ' +
534540 JSON.stringify( tokens ) );
535541
@@ -539,6 +545,9 @@
540546 // JSON.stringify( tokens, null, 2 ) + ', listeners: ' +
541547 // JSON.stringify( this.listeners( 'chunk' ), null, 2 ) );
542548 // signal our done-ness to consumers.
 549+ //if ( this.atTopLevel ) {
 550+ // this.emit( 'chunk', [{type: 'END'}]);
 551+ //}
543552 this.emit( 'end' );
544553 // and reset internal state.
545554 this._reset();
@@ -553,11 +562,13 @@
554563 */
555564 AsyncTokenTransformManager.prototype.onEndEvent = function () {
556565 if ( this.tailAccumulator ) {
557 - this.env.dp( 'AsyncTokenTransformManager.onEndEvent: calling siblingDone' );
 566+ this.env.dp( 'AsyncTokenTransformManager.onEndEvent: calling siblingDone',
 567+ this.loopAndDepthCheck );
558568 this.tailAccumulator.siblingDone();
559569 } else {
560570 // nothing was asynchronous, so we'll have to emit end here.
561 - this.env.dp( 'AsyncTokenTransformManager.onEndEvent: synchronous done' );
 571+ this.env.dp( 'AsyncTokenTransformManager.onEndEvent: synchronous done',
 572+ this.loopAndDepthCheck );
562573 this.emit('end');
563574 this._reset();
564575 }
@@ -607,8 +618,8 @@
608619 * @param {Array} Token chunk.
609620 */
610621 SyncTokenTransformManager.prototype.onChunk = function ( tokens ) {
611 - //console.log('SyncTokenTransformManager.onChunk: ' +
612 - // JSON.stringify( tokens, null, 2 ) );
 622+ this.env.dp('SyncTokenTransformManager.onChunk, input: ' +
 623+ JSON.stringify( tokens, null, 2 ) );
613624 var res,
614625 localAccum = [],
615626 localAccumLength = 0,
@@ -859,36 +870,12 @@
860871 //console.log( 'TokenAccumulator._returnTokens' );
861872 if ( reference === 'child' ) {
862873 tokens = tokens.concat( this.accum );
863 - //console.log('TokenAccumulator._returnTokens child: ' +
864 - // JSON.stringify( tokens, null, 2 ) +
865 - // ' outstanding: ' + this.outstanding
866 - // );
 874+ console.log('TokenAccumulator._returnTokens child: ' +
 875+ JSON.stringify( tokens, null, 2 ) +
 876+ ' outstanding: ' + this.outstanding
 877+ );
867878 this.accum = [];
868 - // XXX: Use some marker to avoid re-transforming token chunks several
869 - // times?
870 - //res = this.transformTokens( tokens, this.parentCB );
871 -
872 - //if ( res.async ) {
873 - // // new asynchronous expansion started, chain of accumulators
874 - // // created
875 - // if ( this.outstanding === 0 ) {
876 - // // Last accum in chain should only wait for child
877 - // res.async.outstanding--;
878 - // cb = this.parentCB;
879 - // } else {
880 - // cb = this.parentCB;
881 - // // set own callback to new sibling, the end of accumulator chain
882 - // this.parentCB = res.async.getParentCB( 'sibling' );
883 - // }
884 - //}
885 - //if ( ! notYetDone ) {
886 - // // Child is done, return accumulator from sibling. Siblings
887 - // // process tokens themselves, so we concat those to the result of
888 - // // processing tokens from the child.
889 - // tokens = res.tokens.concat( this.accum );
890 - // this.accum = [];
891 - //}
892 - this.parentCB( tokens, this.outstanding !== 0 );
 879+ this.parentCB( tokens, this.outstanding );
893880 return null;
894881 } else {
895882 // sibling
@@ -896,13 +883,13 @@
897884 tokens = this.accum.concat( tokens );
898885 // A sibling will transform tokens, so we don't have to do this
899886 // again.
900 - //console.log( 'TokenAccumulator._returnTokens: sibling done and parentCB ' +
901 - // JSON.stringify( tokens ) );
 887+ console.log( 'TokenAccumulator._returnTokens: sibling done and parentCB ' +
 888+ JSON.stringify( tokens ) );
902889 this.parentCB( tokens, false );
903890 return null;
904891 } else if ( this.outstanding === 1 && notYetDone ) {
905 - //console.log( 'TokenAccumulator._returnTokens: sibling done and parentCB but notYetDone ' +
906 - // JSON.stringify( tokens ) );
 892+ console.log( 'TokenAccumulator._returnTokens: sibling done and parentCB but notYetDone ' +
 893+ JSON.stringify( tokens ) );
907894 // Sibling is not yet done, but child is. Return own parentCB to
908895 // allow the sibling to go direct, and call back parent with
909896 // tokens. The internal accumulator is empty at this stage, as its
@@ -910,8 +897,10 @@
911898 return this.parentCB( tokens, true);
912899 } else {
913900 this.accum = this.accum.concat( tokens );
914 - //console.log( 'TokenAccumulator._returnTokens: sibling done, but not overall ' +
915 - // JSON.stringify( tokens ) );
 901+ console.log( 'TokenAccumulator._returnTokens: sibling done, but not overall. notYetDone=' +
 902+ notYetDone + ', this.outstanding=' + this.outstanding +
 903+ ', this.accum=' +
 904+ JSON.stringify( this.accum, null, 2 ) );
916905 }
917906
918907
@@ -966,7 +955,7 @@
967956 */
968957 LoopAndDepthCheck.prototype.check = function ( title ) {
969958 // XXX: set limit really low for testing!
970 - if ( this.depth > 40 ) {
 959+ if ( this.depth > 5 ) {
971960 // too deep
972961 //console.log( 'Loopcheck: ' + JSON.stringify( this, null, 2 ) );
973962 return 'Expansion depth limit exceeded at ';
Index: trunk/extensions/VisualEditor/modules/parser/parse.js
@@ -20,7 +20,7 @@
2121 wgScriptExtension: ".php",
2222 fetchTemplates: true,
2323 // enable/disable debug output using this switch
24 - debug: false
 24+ debug: true
2525 } ),
2626 parser = new ParserPipeline( env );
2727
Index: trunk/extensions/VisualEditor/modules/parser/pegTokenizer.pegjs.txt
@@ -764,19 +764,25 @@
765765 // HACK, not final.
766766 obj.attribs.push(['data-defaultvalue', params[0][1]]);
767767 obj.attribs.push(['data-json-args', JSON.stringify(params)]);
768 - obj.defaultvalue = params[0][1];
 768+ obj.defaultvalue = params[0][1].length ? params[0][1] :
 769+ [{type: 'TEXT', value: ''}];
769770 }
770771 //console.log( 'tokenizer tplarg ' + JSON.stringify( obj ));
771772 return obj;
772773 }
773774
774775 template_param
775 - = name:template_param_name space* "=" space* c:template_param_text {
 776+ = name:template_param_name space* "=" space* c:template_param_text? {
776777 //console.log( 'named template_param matched' + pp([name, flatten( c )]) );
777 - return [name, flatten( c )];
 778+ if ( c !== '' ) {
 779+ return [name, flatten( c )];
 780+ } else {
 781+ return [name, []];
 782+ }
778783 } / c:template_param_text {
779 - return [[], flatten( c ) ];
 784+ return [[], flatten( c ) ];
780785 }
 786+ / & '|' { return [[], []]; }
781787
782788
783789 // FIXME: handle template args and templates in key! (or even parser functions?)
Index: trunk/extensions/VisualEditor/modules/parser/mediawiki.parser.js
@@ -67,6 +67,7 @@
6868 // Create an input pipeline for the given input type.
6969 this.inputPipeline = this.makeInputPipeline ( inputType, {}, true );
7070 this.inputPipeline.atTopLevel = true;
 71+ this.inputPipeline.last.atTopLevel = true;
7172
7273
7374 this.tokenPostProcessor = new TokenTransformManager.SyncTokenTransformManager ( env );
Index: trunk/extensions/VisualEditor/modules/parser/ext.core.TemplateHandler.js
@@ -75,8 +75,8 @@
7676 var attributes = [[[{ type: 'TEXT', value: '' }] , token.target ]]
7777 .concat( this._nameArgs( token.orderedArgs ) );
7878
79 - this.manager.env.dp( 'before AttributeTransformManager: ' +
80 - JSON.stringify( attributes, null, 2 ) );
 79+ //this.manager.env.dp( 'before AttributeTransformManager: ' +
 80+ // JSON.stringify( attributes, null, 2 ) );
8181 new AttributeTransformManager(
8282 this.manager,
8383 this._returnAttributes.bind( this, tplExpandData )
@@ -106,6 +106,7 @@
107107 var n = 1,
108108 out = [];
109109 for ( var i = 0, l = orderedArgs.length; i < l; i++ ) {
 110+ // FIXME: Also check for whitespace-only named args!
110111 if ( ! orderedArgs[i][0].length ) {
111112 out.push( [[{ type: 'TEXT', value: n }], orderedArgs[i][1]]);
112113 n++;
@@ -257,6 +258,7 @@
258259 var res = tplExpandData.resultTokens;
259260 // Remove 'end' token from end
260261 if ( res.length && res[res.length - 1].type === 'END' ) {
 262+ this.manager.env.dp( 'TemplateHandler, stripping end ' );
261263 res.pop();
262264 }
263265
@@ -365,7 +367,7 @@
366368 } else {
367369 console.log( 'templateArg not found: ' + argName +
368370 ' vs. ' + JSON.stringify( this.manager.args ) );
369 - if ( token.attribs.length > 1 ) {
 371+ if ( false && defaultValue.length ) {
370372 res = defaultValue;
371373 } else {
372374 res = [{ type: 'TEXT', value: '{{{' + argName + '}}}' }];

Status & tagging log