Skip to content

Commit d5fcac4

Browse files
committed
feat(compiler): pass compilation unit to the parser
1 parent d985045 commit d5fcac4

File tree

17 files changed

+109
-72
lines changed

17 files changed

+109
-72
lines changed

modules/benchmarks/src/change_detection/change_detection_benchmark.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,16 @@ function setUpChangeDetection() {
108108
var parentRange = parentProto.instantiate(dispatcher, MapWrapper.create());
109109

110110
var astWithSource = [
111-
parser.parseBinding('field0'),
112-
parser.parseBinding('field1'),
113-
parser.parseBinding('field2'),
114-
parser.parseBinding('field3'),
115-
parser.parseBinding('field4'),
116-
parser.parseBinding('field5'),
117-
parser.parseBinding('field6'),
118-
parser.parseBinding('field7'),
119-
parser.parseBinding('field8'),
120-
parser.parseBinding('field9')
111+
parser.parseBinding('field0', null),
112+
parser.parseBinding('field1', null),
113+
parser.parseBinding('field2', null),
114+
parser.parseBinding('field3', null),
115+
parser.parseBinding('field4', null),
116+
parser.parseBinding('field5', null),
117+
parser.parseBinding('field6', null),
118+
parser.parseBinding('field7', null),
119+
parser.parseBinding('field8', null),
120+
parser.parseBinding('field9', null)
121121
];
122122

123123
function proto(i) {

modules/change_detection/src/parser/ast.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,10 @@ export class FunctionCall extends AST {
385385
export class ASTWithSource extends AST {
386386
ast:AST;
387387
source:string;
388-
constructor(ast:AST, source:string) {
388+
location:string;
389+
constructor(ast:AST, source:string, location:string) {
389390
this.source = source;
391+
this.location = location;
390392
this.ast = ast;
391393
}
392394

@@ -407,7 +409,7 @@ export class ASTWithSource extends AST {
407409
}
408410

409411
toString():string {
410-
return this.source;
412+
return `${this.source} in ${this.location}`;
411413
}
412414
}
413415

modules/change_detection/src/parser/parser.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,32 +36,34 @@ export class Parser {
3636
this._reflector = isPresent(providedReflector) ? providedReflector : reflector;
3737
}
3838

39-
parseAction(input:string):ASTWithSource {
39+
parseAction(input:string, location:any):ASTWithSource {
4040
var tokens = this._lexer.tokenize(input);
41-
var ast = new _ParseAST(input, tokens, this._reflector, true).parseChain();
42-
return new ASTWithSource(ast, input);
41+
var ast = new _ParseAST(input, location, tokens, this._reflector, true).parseChain();
42+
return new ASTWithSource(ast, input, location);
4343
}
4444

45-
parseBinding(input:string):ASTWithSource {
45+
parseBinding(input:string, location:any):ASTWithSource {
4646
var tokens = this._lexer.tokenize(input);
47-
var ast = new _ParseAST(input, tokens, this._reflector, false).parseChain();
48-
return new ASTWithSource(ast, input);
47+
var ast = new _ParseAST(input, location, tokens, this._reflector, false).parseChain();
48+
return new ASTWithSource(ast, input, location);
4949
}
5050

51-
parseTemplateBindings(input:string):List<TemplateBinding> {
51+
parseTemplateBindings(input:string, location:any):List<TemplateBinding> {
5252
var tokens = this._lexer.tokenize(input);
53-
return new _ParseAST(input, tokens, this._reflector, false).parseTemplateBindings();
53+
return new _ParseAST(input, location, tokens, this._reflector, false).parseTemplateBindings();
5454
}
5555
}
5656

5757
class _ParseAST {
5858
input:string;
59+
location:any;
5960
tokens:List<Token>;
6061
reflector:Reflector;
6162
parseAction:boolean;
6263
index:int;
63-
constructor(input:string, tokens:List, reflector:Reflector, parseAction:boolean) {
64+
constructor(input:string, location:any, tokens:List, reflector:Reflector, parseAction:boolean) {
6465
this.input = input;
66+
this.location = location;
6567
this.tokens = tokens;
6668
this.index = 0;
6769
this.reflector = reflector;
@@ -451,7 +453,7 @@ class _ParseAST {
451453
var start = this.inputIndex;
452454
var ast = this.parseExpression();
453455
var source = this.input.substring(start, this.inputIndex);
454-
expression = new ASTWithSource(ast, source);
456+
expression = new ASTWithSource(ast, source, this.location);
455457
}
456458
}
457459
ListWrapper.push(bindings, new TemplateBinding(key, name, expression));
@@ -469,6 +471,6 @@ class _ParseAST {
469471
? `at column ${this.tokens[index].index + 1} in`
470472
: `at the end of the expression`;
471473

472-
throw new BaseException(`Parser Error: ${message} ${location} [${this.input}]`);
474+
throw new BaseException(`Parser Error: ${message} ${location} [${this.input}] in ${this.location}`);
473475
}
474476
}

modules/change_detection/test/change_detector_spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {Record} from 'change_detection/record';
2020
export function main() {
2121
function ast(exp:string) {
2222
var parser = new Parser(new Lexer());
23-
return parser.parseBinding(exp);
23+
return parser.parseBinding(exp, 'location');
2424
}
2525

2626
function createChangeDetector(memo:string, exp:string, context = null, formatters = null,
@@ -451,7 +451,7 @@ export function main() {
451451
expect(() => {
452452
var cd = new ChangeDetector(rr, true);
453453
cd.detectChanges();
454-
}).toThrowError(new RegExp("Expression 'a' has changed after it was checked"));
454+
}).toThrowError(new RegExp("Expression 'a in location' has changed after it was checked"));
455455
});
456456
});
457457
});

modules/change_detection/test/parser/parser_spec.js

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ export function main() {
3535
return new Parser(new Lexer(), reflector);
3636
}
3737

38-
function parseAction(text) {
39-
return createParser().parseAction(text).ast;
38+
function parseAction(text, location = null) {
39+
return createParser().parseAction(text, location);
4040
}
4141

42-
function parseBinding(text) {
43-
return createParser().parseBinding(text).ast;
42+
function parseBinding(text, location = null) {
43+
return createParser().parseBinding(text, location);
4444
}
4545

46-
function parseTemplateBindings(text) {
47-
return createParser().parseTemplateBindings(text);
46+
function parseTemplateBindings(text, location = null) {
47+
return createParser().parseTemplateBindings(text, location);
4848
}
4949

5050
function expectEval(text, passedInContext = null) {
@@ -340,7 +340,7 @@ export function main() {
340340

341341
it('should pass exceptions', () => {
342342
expect(() => {
343-
createParser().parseAction('a()').ast.eval(td(() => {throw new BaseException("boo to you")}));
343+
parseAction('a()').eval(td(() => {throw new BaseException("boo to you")}));
344344
}).toThrowError('boo to you');
345345
});
346346

@@ -352,20 +352,24 @@ export function main() {
352352
});
353353

354354
it('should store the source in the result', () => {
355-
expect(createParser().parseAction('someExpr').source).toBe('someExpr');
355+
expect(parseAction('someExpr').source).toBe('someExpr');
356+
});
357+
358+
it('should store the passed-in location', () => {
359+
expect(parseAction('someExpr', 'location').location).toBe('location');
356360
});
357361
});
358362

359363
describe("parseBinding", () => {
360364
describe("formatters", () => {
361365
it("should parse formatters", () => {
362-
var exp = parseBinding("'Foo'|uppercase");
366+
var exp = parseBinding("'Foo'|uppercase").ast;
363367
expect(exp).toBeAnInstanceOf(Formatter);
364368
expect(exp.name).toEqual("uppercase");
365369
});
366370

367371
it("should parse formatters with args", () => {
368-
var exp = parseBinding("1|increment:2");
372+
var exp = parseBinding("1|increment:2").ast;
369373
expect(exp).toBeAnInstanceOf(Formatter);
370374
expect(exp.name).toEqual("increment");
371375
expect(exp.args[0]).toBeAnInstanceOf(LiteralPrimitive);
@@ -380,7 +384,11 @@ export function main() {
380384
});
381385

382386
it('should store the source in the result', () => {
383-
expect(createParser().parseBinding('someExpr').source).toBe('someExpr');
387+
expect(parseBinding('someExpr').source).toBe('someExpr');
388+
});
389+
390+
it('should store the passed-in location', () => {
391+
expect(parseBinding('someExpr', 'location').location).toBe('location');
384392
});
385393

386394
it('should throw on chain expressions', () => {
@@ -409,7 +417,7 @@ export function main() {
409417

410418
function exprAsts(templateBindings) {
411419
return ListWrapper.map(templateBindings,
412-
(binding) => isPresent(binding.expression) ? binding.expression.ast : null );
420+
(binding) => isPresent(binding.expression) ? binding.expression : null );
413421
}
414422

415423
it('should parse an empty string', () => {
@@ -482,6 +490,11 @@ export function main() {
482490
expect(bindings[0].expression.source).toEqual('1');
483491
expect(bindings[1].expression.source).toEqual('2');
484492
});
493+
494+
it('should store the passed-in location', () => {
495+
var bindings = parseTemplateBindings("a 1,b 2", 'location');
496+
expect(bindings[0].expression.location).toEqual('location');
497+
});
485498
});
486499
});
487500
}

modules/core/src/compiler/compiler.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export class Compiler {
6262
for (var i=0; i<directives.length; i++) {
6363
ListWrapper.push(annotatedDirectives, this._reader.annotatedType(directives[i]));
6464
}
65-
return createDefaultSteps(this._parser, annotatedDirectives);
65+
return createDefaultSteps(this._parser, component, annotatedDirectives);
6666
}
6767

6868
compile(component:Type, templateRoot:Element = null):Promise<ProtoView> {

modules/core/src/compiler/pipeline/default_steps.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,22 @@ import {ElementBindingMarker} from './element_binding_marker';
99
import {ProtoViewBuilder} from './proto_view_builder';
1010
import {ProtoElementInjectorBuilder} from './proto_element_injector_builder';
1111
import {ElementBinderBuilder} from './element_binder_builder';
12+
import {AnnotatedType} from 'core/compiler/annotated_type';
13+
import {stringify} from 'facade/lang';
1214

1315
/**
1416
* Default steps used for compiling a template.
1517
* Takes in an HTMLElement and produces the ProtoViews,
1618
* ProtoElementInjectors and ElementBinders in the end.
1719
*/
18-
export function createDefaultSteps(parser:Parser, directives: List<AnnotatedType>) {
20+
export function createDefaultSteps(parser:Parser, compiledComponent: AnnotatedType,
21+
directives: List<AnnotatedType>) {
22+
var compilationUnit = stringify(compiledComponent.type);
23+
1924
return [
20-
new ViewSplitter(parser),
21-
new TextInterpolationParser(parser),
22-
new PropertyBindingParser(parser),
25+
new ViewSplitter(parser, compilationUnit),
26+
new TextInterpolationParser(parser, compilationUnit),
27+
new PropertyBindingParser(parser, compilationUnit),
2328
new DirectiveParser(directives),
2429
new ElementBindingMarker(),
2530
new ProtoViewBuilder(),

modules/core/src/compiler/pipeline/property_binding_parser.js

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {MapWrapper} from 'facade/collection';
33
import {TemplateElement} from 'facade/dom';
44

55
import {Parser} from 'change_detection/parser/parser';
6+
import {AST} from 'change_detection/parser/ast';
67
import {ExpressionWithSource} from 'change_detection/parser/ast';
78

89
import {CompileStep} from './compile_step';
@@ -24,8 +25,10 @@ var BIND_NAME_REGEXP = RegExpWrapper.create('^(?:(?:(bind)|(let)|(on))-(.+))|\\[
2425
*/
2526
export class PropertyBindingParser extends CompileStep {
2627
_parser:Parser;
27-
constructor(parser:Parser) {
28+
_compilationUnit:any;
29+
constructor(parser:Parser, compilationUnit:any) {
2830
this._parser = parser;
31+
this._compilationUnit = compilationUnit;
2932
}
3033

3134
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
@@ -35,7 +38,7 @@ export class PropertyBindingParser extends CompileStep {
3538
if (isPresent(bindParts)) {
3639
if (isPresent(bindParts[1])) {
3740
// match: bind-prop
38-
current.addPropertyBinding(bindParts[4], this._parser.parseBinding(attrValue));
41+
current.addPropertyBinding(bindParts[4], this._parseBinding(attrValue));
3942
} else if (isPresent(bindParts[2])) {
4043
// match: let-prop
4144
// Note: We assume that the ViewSplitter already did its work, i.e. template directive should
@@ -46,20 +49,28 @@ export class PropertyBindingParser extends CompileStep {
4649
current.addVariableBinding(bindParts[4], attrValue);
4750
} else if (isPresent(bindParts[3])) {
4851
// match: on-prop
49-
current.addEventBinding(bindParts[4], this._parser.parseAction(attrValue));
52+
current.addEventBinding(bindParts[4], this._parseAction(attrValue));
5053
} else if (isPresent(bindParts[5])) {
5154
// match: [prop]
52-
current.addPropertyBinding(bindParts[5], this._parser.parseBinding(attrValue));
55+
current.addPropertyBinding(bindParts[5], this._parseBinding(attrValue));
5356
} else if (isPresent(bindParts[6])) {
5457
// match: (prop)
55-
current.addEventBinding(bindParts[6], this._parser.parseBinding(attrValue));
58+
current.addEventBinding(bindParts[6], this._parseBinding(attrValue));
5659
}
5760
} else {
5861
var expression = interpolationToExpression(attrValue);
5962
if (isPresent(expression)) {
60-
current.addPropertyBinding(attrName, this._parser.parseBinding(expression));
63+
current.addPropertyBinding(attrName, this._parseBinding(expression));
6164
}
6265
}
6366
});
6467
}
68+
69+
_parseBinding(input:string):AST {
70+
return this._parser.parseBinding(input, this._compilationUnit);
71+
}
72+
73+
_parseAction(input:string):AST {
74+
return this._parser.parseAction(input, this._compilationUnit);
75+
}
6576
}

modules/core/src/compiler/pipeline/text_interpolation_parser.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ export function interpolationToExpression(value:string):string {
4747
*/
4848
export class TextInterpolationParser extends CompileStep {
4949
_parser:Parser;
50-
constructor(parser:Parser) {
50+
_compilationUnit:any;
51+
constructor(parser:Parser, compilationUnit:any) {
5152
this._parser = parser;
53+
this._compilationUnit = compilationUnit;
5254
}
5355

5456
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
@@ -66,7 +68,7 @@ export class TextInterpolationParser extends CompileStep {
6668
var expression = interpolationToExpression(node.nodeValue);
6769
if (isPresent(expression)) {
6870
DOM.setText(node, ' ');
69-
pipelineElement.addTextNodeBinding(nodeIndex, this._parser.parseBinding(expression));
71+
pipelineElement.addTextNodeBinding(nodeIndex, this._parser.parseBinding(expression, this._compilationUnit));
7072
}
7173
}
7274
}

modules/core/src/compiler/pipeline/view_splitter.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,10 @@ import {CompileControl} from './compile_control';
3131
*/
3232
export class ViewSplitter extends CompileStep {
3333
_parser:Parser;
34-
constructor(parser:Parser) {
34+
_compilationUnit:any;
35+
constructor(parser:Parser, compilationUnit:any) {
3536
this._parser = parser;
37+
this._compilationUnit = compilationUnit;
3638
}
3739

3840
process(parent:CompileElement, current:CompileElement, control:CompileControl) {
@@ -74,7 +76,7 @@ export class ViewSplitter extends CompileStep {
7476
}
7577

7678
_parseTemplateBindings(templateBindings:string, compileElement:CompileElement) {
77-
var bindings = this._parser.parseTemplateBindings(templateBindings);
79+
var bindings = this._parser.parseTemplateBindings(templateBindings, this._compilationUnit);
7880
for (var i=0; i<bindings.length; i++) {
7981
var binding = bindings[i];
8082
if (isPresent(binding.name)) {

0 commit comments

Comments
 (0)