Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(376)

Side by Side Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 137863002: Issue 8742. Preserve leading line comments during java2dart translation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Test for block-style comment translation. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « pkg/analyzer/lib/src/generated/parser.dart ('k') | pkg/analyzer/lib/src/generated/scanner.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 // This code was auto-generated, is not intended to be edited, and is subject to 5 // This code was auto-generated, is not intended to be edited, and is subject to
6 // significant change. Please see the README file for more information. 6 // significant change. Please see the README file for more information.
7 7
8 library engine.resolver; 8 library engine.resolver;
9 9
10 import 'dart:collection'; 10 import 'dart:collection';
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 63
64 static String _NG_CALLBACK = "NgCallback"; 64 static String _NG_CALLBACK = "NgCallback";
65 65
66 static String _NG_ONE_WAY = "NgOneWay"; 66 static String _NG_ONE_WAY = "NgOneWay";
67 67
68 static String _NG_ONE_WAY_ONE_TIME = "NgOneWayOneTime"; 68 static String _NG_ONE_WAY_ONE_TIME = "NgOneWayOneTime";
69 69
70 static String _NG_TWO_WAY = "NgTwoWay"; 70 static String _NG_TWO_WAY = "NgTwoWay";
71 71
72 static Element getElement(ASTNode node, int offset) { 72 static Element getElement(ASTNode node, int offset) {
73 // maybe no node
73 if (node == null) { 74 if (node == null) {
74 return null; 75 return null;
75 } 76 }
77 // prepare enclosing ClassDeclaration
76 ClassDeclaration classDeclaration = node.getAncestor(ClassDeclaration); 78 ClassDeclaration classDeclaration = node.getAncestor(ClassDeclaration);
77 if (classDeclaration == null) { 79 if (classDeclaration == null) {
78 return null; 80 return null;
79 } 81 }
82 // prepare ClassElement
80 ClassElement classElement = classDeclaration.element; 83 ClassElement classElement = classDeclaration.element;
81 if (classElement == null) { 84 if (classElement == null) {
82 return null; 85 return null;
83 } 86 }
87 // check toolkit objects
84 for (ToolkitObjectElement toolkitObject in classElement.toolkitObjects) { 88 for (ToolkitObjectElement toolkitObject in classElement.toolkitObjects) {
85 List<AngularPropertyElement> properties = AngularPropertyElement.EMPTY_ARR AY; 89 List<AngularPropertyElement> properties = AngularPropertyElement.EMPTY_ARR AY;
90 // try properties of AngularComponentElement
86 if (toolkitObject is AngularComponentElement) { 91 if (toolkitObject is AngularComponentElement) {
87 AngularComponentElement component = toolkitObject; 92 AngularComponentElement component = toolkitObject;
88 properties = component.properties; 93 properties = component.properties;
89 } 94 }
95 // try properties of AngularDirectiveElement
90 if (toolkitObject is AngularDirectiveElement) { 96 if (toolkitObject is AngularDirectiveElement) {
91 AngularDirectiveElement directive = toolkitObject; 97 AngularDirectiveElement directive = toolkitObject;
92 properties = directive.properties; 98 properties = directive.properties;
93 } 99 }
100 // check properties
94 for (AngularPropertyElement property in properties) { 101 for (AngularPropertyElement property in properties) {
102 // property name (use complete node range)
95 int propertyOffset = property.nameOffset; 103 int propertyOffset = property.nameOffset;
96 int propertyEnd = propertyOffset + property.name.length; 104 int propertyEnd = propertyOffset + property.name.length;
97 if (node.offset <= propertyOffset && propertyEnd < node.end) { 105 if (node.offset <= propertyOffset && propertyEnd < node.end) {
98 return property; 106 return property;
99 } 107 }
108 // field name (use complete node range, including @, => and <=>)
100 FieldElement field = property.field; 109 FieldElement field = property.field;
101 if (field != null) { 110 if (field != null) {
102 int fieldOffset = property.fieldNameOffset; 111 int fieldOffset = property.fieldNameOffset;
103 int fieldEnd = fieldOffset + field.name.length; 112 int fieldEnd = fieldOffset + field.name.length;
104 if (node.offset <= fieldOffset && fieldEnd < node.end) { 113 if (node.offset <= fieldOffset && fieldEnd < node.end) {
105 return field; 114 return field;
106 } 115 }
107 } 116 }
108 } 117 }
109 } 118 }
119 // no Element
110 return null; 120 return null;
111 } 121 }
112 122
113 /** 123 /**
114 * Checks if given [Type] is an Angular <code>Module</code> or its subclass. 124 * Checks if given [Type] is an Angular <code>Module</code> or its subclass.
115 */ 125 */
116 static bool isModule(Type2 type) { 126 static bool isModule(Type2 type) {
117 if (type is! InterfaceType) { 127 if (type is! InterfaceType) {
118 return false; 128 return false;
119 } 129 }
120 InterfaceType interfaceType = type as InterfaceType; 130 InterfaceType interfaceType = type as InterfaceType;
131 // check hierarchy
121 Set<Type2> seenTypes = new Set(); 132 Set<Type2> seenTypes = new Set();
122 while (interfaceType != null) { 133 while (interfaceType != null) {
134 // check for recursion
123 if (!seenTypes.add(interfaceType)) { 135 if (!seenTypes.add(interfaceType)) {
124 return false; 136 return false;
125 } 137 }
138 // check for "Module"
126 if (interfaceType.element.name == "Module") { 139 if (interfaceType.element.name == "Module") {
127 return true; 140 return true;
128 } 141 }
142 // try supertype
129 interfaceType = interfaceType.superclass; 143 interfaceType = interfaceType.superclass;
130 } 144 }
145 // no
131 return false; 146 return false;
132 } 147 }
133 148
134 /** 149 /**
135 * Parses given selector text and returns [AngularSelectorElement]. May be `nu ll` if 150 * Parses given selector text and returns [AngularSelectorElement]. May be `nu ll` if
136 * cannot parse. 151 * cannot parse.
137 */ 152 */
138 static AngularSelectorElement parseSelector(int offset, String text) { 153 static AngularSelectorElement parseSelector(int offset, String text) {
139 if (text.startsWith("[") && text.endsWith("]")) { 154 if (text.startsWith("[") && text.endsWith("]")) {
140 int nameOffset = offset + "[".length; 155 int nameOffset = offset + "[".length;
141 String attributeName = text.substring(1, text.length - 1); 156 String attributeName = text.substring(1, text.length - 1);
157 // TODO(scheglov) report warning if there are spaces between [ and identif ier
142 return new HasAttributeSelectorElementImpl(attributeName, nameOffset); 158 return new HasAttributeSelectorElementImpl(attributeName, nameOffset);
143 } 159 }
144 if (StringUtilities.isTagName(text)) { 160 if (StringUtilities.isTagName(text)) {
145 return new IsTagSelectorElementImpl(text, offset); 161 return new IsTagSelectorElementImpl(text, offset);
146 } 162 }
147 return null; 163 return null;
148 } 164 }
149 165
150 /** 166 /**
151 * Returns the [FieldElement] of the first field in the given [FieldDeclaratio n]. 167 * Returns the [FieldElement] of the first field in the given [FieldDeclaratio n].
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 this._errorListener = errorListener; 247 this._errorListener = errorListener;
232 this._source = source; 248 this._source = source;
233 } 249 }
234 250
235 /** 251 /**
236 * Builds Angular specific element models and adds them to the existing Dart e lements. 252 * Builds Angular specific element models and adds them to the existing Dart e lements.
237 * 253 *
238 * @param unit the compilation unit with built Dart element models 254 * @param unit the compilation unit with built Dart element models
239 */ 255 */
240 void build(CompilationUnit unit) { 256 void build(CompilationUnit unit) {
257 // process classes
241 for (CompilationUnitMember unitMember in unit.declarations) { 258 for (CompilationUnitMember unitMember in unit.declarations) {
242 if (unitMember is ClassDeclaration) { 259 if (unitMember is ClassDeclaration) {
243 this._classDeclaration = unitMember; 260 this._classDeclaration = unitMember;
244 this._classElement = _classDeclaration.element as ClassElementImpl; 261 this._classElement = _classDeclaration.element as ClassElementImpl;
245 this._classToolkitObjects.clear(); 262 this._classToolkitObjects.clear();
246 parseModuleClass(); 263 parseModuleClass();
264 // process annotations
247 NodeList<Annotation> annotations = _classDeclaration.metadata; 265 NodeList<Annotation> annotations = _classDeclaration.metadata;
248 for (Annotation annotation in annotations) { 266 for (Annotation annotation in annotations) {
249 this._annotation = annotation; 267 this._annotation = annotation;
268 // @NgFilter
250 if (isAngularAnnotation2(_NG_FILTER)) { 269 if (isAngularAnnotation2(_NG_FILTER)) {
251 parseNgFilter(); 270 parseNgFilter();
252 continue; 271 continue;
253 } 272 }
273 // @NgComponent
254 if (isAngularAnnotation2(_NG_COMPONENT)) { 274 if (isAngularAnnotation2(_NG_COMPONENT)) {
255 parseNgComponent(); 275 parseNgComponent();
256 continue; 276 continue;
257 } 277 }
278 // @NgController
258 if (isAngularAnnotation2(_NG_CONTROLLER)) { 279 if (isAngularAnnotation2(_NG_CONTROLLER)) {
259 parseNgController(); 280 parseNgController();
260 continue; 281 continue;
261 } 282 }
283 // @NgDirective
262 if (isAngularAnnotation2(_NG_DIRECTIVE)) { 284 if (isAngularAnnotation2(_NG_DIRECTIVE)) {
263 parseNgDirective(); 285 parseNgDirective();
264 continue; 286 continue;
265 } 287 }
266 } 288 }
289 // set toolkit objects
267 if (!_classToolkitObjects.isEmpty) { 290 if (!_classToolkitObjects.isEmpty) {
268 List<ToolkitObjectElement> objects = _classToolkitObjects; 291 List<ToolkitObjectElement> objects = _classToolkitObjects;
269 _classElement.toolkitObjects = new List.from(objects); 292 _classElement.toolkitObjects = new List.from(objects);
270 } 293 }
271 } 294 }
272 } 295 }
296 // process modules in variables
273 parseModuleVariables(unit); 297 parseModuleVariables(unit);
274 } 298 }
275 299
276 /** 300 /**
277 * Creates [AngularModuleElementImpl] for given information. 301 * Creates [AngularModuleElementImpl] for given information.
278 */ 302 */
279 AngularModuleElementImpl createModuleElement(List<AngularModuleElement> childM odules, List<ClassElement> keyTypes) { 303 AngularModuleElementImpl createModuleElement(List<AngularModuleElement> childM odules, List<ClassElement> keyTypes) {
280 AngularModuleElementImpl module = new AngularModuleElementImpl(); 304 AngularModuleElementImpl module = new AngularModuleElementImpl();
281 module.childModules = new List.from(childModules); 305 module.childModules = new List.from(childModules);
282 module.keyTypes = new List.from(keyTypes); 306 module.keyTypes = new List.from(keyTypes);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 } 380 }
357 381
358 /** 382 /**
359 * Analyzes [classDeclaration] and if it is a module, creates [AngularModuleEl ement] 383 * Analyzes [classDeclaration] and if it is a module, creates [AngularModuleEl ement]
360 * model for it. 384 * model for it.
361 */ 385 */
362 void parseModuleClass() { 386 void parseModuleClass() {
363 if (!isModule4) { 387 if (!isModule4) {
364 return; 388 return;
365 } 389 }
390 // check install(), type() and value() invocations
366 List<AngularModuleElement> childModules = []; 391 List<AngularModuleElement> childModules = [];
367 List<ClassElement> keyTypes = []; 392 List<ClassElement> keyTypes = [];
368 _classDeclaration.accept(new RecursiveASTVisitor_AngularCompilationUnitBuild er_parseModuleClass(this, childModules, keyTypes)); 393 _classDeclaration.accept(new RecursiveASTVisitor_AngularCompilationUnitBuild er_parseModuleClass(this, childModules, keyTypes));
394 // set module element
369 AngularModuleElementImpl module = createModuleElement(childModules, keyTypes ); 395 AngularModuleElementImpl module = createModuleElement(childModules, keyTypes );
370 _classToolkitObjects.add(module); 396 _classToolkitObjects.add(module);
371 } 397 }
372 398
373 /** 399 /**
374 * Checks if given [MethodInvocation] is an interesting <code>Module</code> me thod 400 * Checks if given [MethodInvocation] is an interesting <code>Module</code> me thod
375 * invocation and remembers corresponding elements into lists. 401 * invocation and remembers corresponding elements into lists.
376 */ 402 */
377 void parseModuleInvocation(MethodInvocation node, List<AngularModuleElement> c hildModules, List<ClassElement> keyTypes) { 403 void parseModuleInvocation(MethodInvocation node, List<AngularModuleElement> c hildModules, List<ClassElement> keyTypes) {
378 String methodName = node.methodName.name; 404 String methodName = node.methodName.name;
379 NodeList<Expression> arguments = node.argumentList.arguments; 405 NodeList<Expression> arguments = node.argumentList.arguments;
406 // install()
380 if (arguments.length == 1 && methodName == "install") { 407 if (arguments.length == 1 && methodName == "install") {
381 Type2 argType = arguments[0].bestType; 408 Type2 argType = arguments[0].bestType;
382 if (argType is InterfaceType) { 409 if (argType is InterfaceType) {
383 ClassElement argElement = argType.element; 410 ClassElement argElement = argType.element;
384 List<ToolkitObjectElement> toolkitObjects = argElement.toolkitObjects; 411 List<ToolkitObjectElement> toolkitObjects = argElement.toolkitObjects;
385 for (ToolkitObjectElement toolkitObject in toolkitObjects) { 412 for (ToolkitObjectElement toolkitObject in toolkitObjects) {
386 if (toolkitObject is AngularModuleElement) { 413 if (toolkitObject is AngularModuleElement) {
387 childModules.add(toolkitObject); 414 childModules.add(toolkitObject);
388 } 415 }
389 } 416 }
390 } 417 }
391 return; 418 return;
392 } 419 }
420 // type() and value()
393 if (arguments.length >= 1 && (methodName == "type" || methodName == "value") ) { 421 if (arguments.length >= 1 && (methodName == "type" || methodName == "value") ) {
394 Expression arg = arguments[0]; 422 Expression arg = arguments[0];
395 if (arg is Identifier) { 423 if (arg is Identifier) {
396 Element argElement = arg.staticElement; 424 Element argElement = arg.staticElement;
397 if (argElement is ClassElement) { 425 if (argElement is ClassElement) {
398 keyTypes.add(argElement); 426 keyTypes.add(argElement);
399 } 427 }
400 } 428 }
401 return; 429 return;
402 } 430 }
403 } 431 }
404 432
405 /** 433 /**
406 * Checks every local variable in the given unit to see if it is a <code>Modul e</code> and creates 434 * Checks every local variable in the given unit to see if it is a <code>Modul e</code> and creates
407 * [AngularModuleElement] for it. 435 * [AngularModuleElement] for it.
408 */ 436 */
409 void parseModuleVariables(CompilationUnit unit) { 437 void parseModuleVariables(CompilationUnit unit) {
410 unit.accept(new RecursiveASTVisitor_AngularCompilationUnitBuilder_parseModul eVariables(this)); 438 unit.accept(new RecursiveASTVisitor_AngularCompilationUnitBuilder_parseModul eVariables(this));
411 } 439 }
412 440
413 void parseNgComponent() { 441 void parseNgComponent() {
414 bool isValid = true; 442 bool isValid = true;
443 // publishAs
415 if (!hasStringArgument(_PUBLISH_AS)) { 444 if (!hasStringArgument(_PUBLISH_AS)) {
416 reportErrorForAnnotation(AngularCode.MISSING_PUBLISH_AS, []); 445 reportErrorForAnnotation(AngularCode.MISSING_PUBLISH_AS, []);
417 isValid = false; 446 isValid = false;
418 } 447 }
448 // selector
419 AngularSelectorElement selector = null; 449 AngularSelectorElement selector = null;
420 if (!hasStringArgument(_SELECTOR)) { 450 if (!hasStringArgument(_SELECTOR)) {
421 reportErrorForAnnotation(AngularCode.MISSING_SELECTOR, []); 451 reportErrorForAnnotation(AngularCode.MISSING_SELECTOR, []);
422 isValid = false; 452 isValid = false;
423 } else { 453 } else {
424 SimpleStringLiteral selectorLiteral = getStringLiteral(_SELECTOR); 454 SimpleStringLiteral selectorLiteral = getStringLiteral(_SELECTOR);
425 selector = parseSelector2(selectorLiteral); 455 selector = parseSelector2(selectorLiteral);
426 if (selector == null) { 456 if (selector == null) {
427 reportErrorForArgument(_SELECTOR, AngularCode.CANNOT_PARSE_SELECTOR, [se lectorLiteral]); 457 reportErrorForArgument(_SELECTOR, AngularCode.CANNOT_PARSE_SELECTOR, [se lectorLiteral]);
428 isValid = false; 458 isValid = false;
429 } 459 }
430 } 460 }
461 // templateUrl
431 if (!hasStringArgument(_TEMPLATE_URL)) { 462 if (!hasStringArgument(_TEMPLATE_URL)) {
432 reportErrorForAnnotation(AngularCode.MISSING_TEMPLATE_URL, []); 463 reportErrorForAnnotation(AngularCode.MISSING_TEMPLATE_URL, []);
433 isValid = false; 464 isValid = false;
434 } 465 }
466 // cssUrl
435 if (!hasStringArgument(_CSS_URL)) { 467 if (!hasStringArgument(_CSS_URL)) {
436 reportErrorForAnnotation(AngularCode.MISSING_CSS_URL, []); 468 reportErrorForAnnotation(AngularCode.MISSING_CSS_URL, []);
437 isValid = false; 469 isValid = false;
438 } 470 }
471 // create
439 if (isValid) { 472 if (isValid) {
440 String name = getStringArgument(_PUBLISH_AS); 473 String name = getStringArgument(_PUBLISH_AS);
441 int nameOffset = getStringArgumentOffset(_PUBLISH_AS); 474 int nameOffset = getStringArgumentOffset(_PUBLISH_AS);
442 String templateUri = getStringArgument(_TEMPLATE_URL); 475 String templateUri = getStringArgument(_TEMPLATE_URL);
443 int templateUriOffset = getStringArgumentOffset(_TEMPLATE_URL); 476 int templateUriOffset = getStringArgumentOffset(_TEMPLATE_URL);
444 String styleUri = getStringArgument(_CSS_URL); 477 String styleUri = getStringArgument(_CSS_URL);
445 int styleUriOffset = getStringArgumentOffset(_CSS_URL); 478 int styleUriOffset = getStringArgumentOffset(_CSS_URL);
446 AngularComponentElementImpl element = new AngularComponentElementImpl(name , nameOffset); 479 AngularComponentElementImpl element = new AngularComponentElementImpl(name , nameOffset);
447 element.selector = selector; 480 element.selector = selector;
448 element.templateUri = templateUri; 481 element.templateUri = templateUri;
(...skipping 19 matching lines...) Expand all
468 501
469 /** 502 /**
470 * Parses [AngularPropertyElement]s from [annotation]. 503 * Parses [AngularPropertyElement]s from [annotation].
471 */ 504 */
472 void parseNgComponentProperties_fromFields(List<AngularPropertyElement> proper ties) { 505 void parseNgComponentProperties_fromFields(List<AngularPropertyElement> proper ties) {
473 NodeList<ClassMember> members = _classDeclaration.members; 506 NodeList<ClassMember> members = _classDeclaration.members;
474 for (ClassMember member in members) { 507 for (ClassMember member in members) {
475 if (member is FieldDeclaration) { 508 if (member is FieldDeclaration) {
476 FieldDeclaration fieldDeclaration = member; 509 FieldDeclaration fieldDeclaration = member;
477 for (Annotation annotation in fieldDeclaration.metadata) { 510 for (Annotation annotation in fieldDeclaration.metadata) {
511 // prepare property kind (if property annotation at all)
478 AngularPropertyKind kind = null; 512 AngularPropertyKind kind = null;
479 if (isAngularAnnotation(annotation, _NG_ATTR)) { 513 if (isAngularAnnotation(annotation, _NG_ATTR)) {
480 kind = AngularPropertyKind.ATTR; 514 kind = AngularPropertyKind.ATTR;
481 } else if (isAngularAnnotation(annotation, _NG_CALLBACK)) { 515 } else if (isAngularAnnotation(annotation, _NG_CALLBACK)) {
482 kind = AngularPropertyKind.CALLBACK; 516 kind = AngularPropertyKind.CALLBACK;
483 } else if (isAngularAnnotation(annotation, _NG_ONE_WAY)) { 517 } else if (isAngularAnnotation(annotation, _NG_ONE_WAY)) {
484 kind = AngularPropertyKind.ONE_WAY; 518 kind = AngularPropertyKind.ONE_WAY;
485 } else if (isAngularAnnotation(annotation, _NG_ONE_WAY_ONE_TIME)) { 519 } else if (isAngularAnnotation(annotation, _NG_ONE_WAY_ONE_TIME)) {
486 kind = AngularPropertyKind.ONE_WAY_ONE_TIME; 520 kind = AngularPropertyKind.ONE_WAY_ONE_TIME;
487 } else if (isAngularAnnotation(annotation, _NG_TWO_WAY)) { 521 } else if (isAngularAnnotation(annotation, _NG_TWO_WAY)) {
488 kind = AngularPropertyKind.TWO_WAY; 522 kind = AngularPropertyKind.TWO_WAY;
489 } 523 }
524 // add property
490 if (kind != null) { 525 if (kind != null) {
491 SimpleStringLiteral nameLiteral = getOnlySimpleStringLiteralArgument (annotation); 526 SimpleStringLiteral nameLiteral = getOnlySimpleStringLiteralArgument (annotation);
492 FieldElement field = getOnlyFieldElement(fieldDeclaration); 527 FieldElement field = getOnlyFieldElement(fieldDeclaration);
493 if (nameLiteral != null && field != null) { 528 if (nameLiteral != null && field != null) {
494 AngularPropertyElementImpl property = new AngularPropertyElementIm pl(nameLiteral.value, nameLiteral.valueOffset); 529 AngularPropertyElementImpl property = new AngularPropertyElementIm pl(nameLiteral.value, nameLiteral.valueOffset);
495 property.field = field; 530 property.field = field;
496 property.propertyKind = kind; 531 property.propertyKind = kind;
497 properties.add(property); 532 properties.add(property);
498 } 533 }
499 } 534 }
500 } 535 }
501 } 536 }
502 } 537 }
503 } 538 }
504 539
505 /** 540 /**
506 * Parses [AngularPropertyElement]s from [annotation]. 541 * Parses [AngularPropertyElement]s from [annotation].
507 */ 542 */
508 void parseNgComponentProperties_fromMap(List<AngularPropertyElement> propertie s) { 543 void parseNgComponentProperties_fromMap(List<AngularPropertyElement> propertie s) {
509 Expression mapExpression = getArgument("map"); 544 Expression mapExpression = getArgument("map");
545 // may be not properties
510 if (mapExpression == null) { 546 if (mapExpression == null) {
511 return; 547 return;
512 } 548 }
549 // prepare map literal
513 if (mapExpression is! MapLiteral) { 550 if (mapExpression is! MapLiteral) {
514 reportError(mapExpression, AngularCode.INVALID_PROPERTY_MAP, []); 551 reportError(mapExpression, AngularCode.INVALID_PROPERTY_MAP, []);
515 return; 552 return;
516 } 553 }
517 MapLiteral mapLiteral = mapExpression as MapLiteral; 554 MapLiteral mapLiteral = mapExpression as MapLiteral;
555 // analyze map entries
518 for (MapLiteralEntry entry in mapLiteral.entries) { 556 for (MapLiteralEntry entry in mapLiteral.entries) {
557 // prepare property name
519 Expression nameExpression = entry.key; 558 Expression nameExpression = entry.key;
520 if (nameExpression is! SimpleStringLiteral) { 559 if (nameExpression is! SimpleStringLiteral) {
521 reportError(nameExpression, AngularCode.INVALID_PROPERTY_NAME, []); 560 reportError(nameExpression, AngularCode.INVALID_PROPERTY_NAME, []);
522 continue; 561 continue;
523 } 562 }
524 SimpleStringLiteral nameLiteral = nameExpression as SimpleStringLiteral; 563 SimpleStringLiteral nameLiteral = nameExpression as SimpleStringLiteral;
525 String name = nameLiteral.value; 564 String name = nameLiteral.value;
526 int nameOffset = nameLiteral.valueOffset; 565 int nameOffset = nameLiteral.valueOffset;
566 // prepare field specification
527 Expression specExpression = entry.value; 567 Expression specExpression = entry.value;
528 if (specExpression is! SimpleStringLiteral) { 568 if (specExpression is! SimpleStringLiteral) {
529 reportError(specExpression, AngularCode.INVALID_PROPERTY_SPEC, []); 569 reportError(specExpression, AngularCode.INVALID_PROPERTY_SPEC, []);
530 continue; 570 continue;
531 } 571 }
532 SimpleStringLiteral specLiteral = specExpression as SimpleStringLiteral; 572 SimpleStringLiteral specLiteral = specExpression as SimpleStringLiteral;
533 String spec = specLiteral.value; 573 String spec = specLiteral.value;
574 // parse binding kind and field name
534 AngularPropertyKind kind; 575 AngularPropertyKind kind;
535 int fieldNameOffset; 576 int fieldNameOffset;
536 if (spec.startsWith(_PREFIX_ATTR)) { 577 if (spec.startsWith(_PREFIX_ATTR)) {
537 kind = AngularPropertyKind.ATTR; 578 kind = AngularPropertyKind.ATTR;
538 fieldNameOffset = 1; 579 fieldNameOffset = 1;
539 } else if (spec.startsWith(_PREFIX_CALLBACK)) { 580 } else if (spec.startsWith(_PREFIX_CALLBACK)) {
540 kind = AngularPropertyKind.CALLBACK; 581 kind = AngularPropertyKind.CALLBACK;
541 fieldNameOffset = 1; 582 fieldNameOffset = 1;
542 } else if (spec.startsWith(_PREFIX_ONE_WAY_ONE_TIME)) { 583 } else if (spec.startsWith(_PREFIX_ONE_WAY_ONE_TIME)) {
543 kind = AngularPropertyKind.ONE_WAY_ONE_TIME; 584 kind = AngularPropertyKind.ONE_WAY_ONE_TIME;
544 fieldNameOffset = 3; 585 fieldNameOffset = 3;
545 } else if (spec.startsWith(_PREFIX_ONE_WAY)) { 586 } else if (spec.startsWith(_PREFIX_ONE_WAY)) {
546 kind = AngularPropertyKind.ONE_WAY; 587 kind = AngularPropertyKind.ONE_WAY;
547 fieldNameOffset = 2; 588 fieldNameOffset = 2;
548 } else if (spec.startsWith(_PREFIX_TWO_WAY)) { 589 } else if (spec.startsWith(_PREFIX_TWO_WAY)) {
549 kind = AngularPropertyKind.TWO_WAY; 590 kind = AngularPropertyKind.TWO_WAY;
550 fieldNameOffset = 3; 591 fieldNameOffset = 3;
551 } else { 592 } else {
552 reportError(specLiteral, AngularCode.INVALID_PROPERTY_KIND, [spec]); 593 reportError(specLiteral, AngularCode.INVALID_PROPERTY_KIND, [spec]);
553 continue; 594 continue;
554 } 595 }
555 String fieldName = spec.substring(fieldNameOffset); 596 String fieldName = spec.substring(fieldNameOffset);
556 fieldNameOffset += specLiteral.valueOffset; 597 fieldNameOffset += specLiteral.valueOffset;
598 // prepare field
557 FieldElement field = _classElement.getField(fieldName); 599 FieldElement field = _classElement.getField(fieldName);
558 if (field == null) { 600 if (field == null) {
559 reportError2(fieldNameOffset, fieldName.length, AngularCode.INVALID_PROP ERTY_FIELD, [fieldName]); 601 reportError2(fieldNameOffset, fieldName.length, AngularCode.INVALID_PROP ERTY_FIELD, [fieldName]);
560 continue; 602 continue;
561 } 603 }
604 // add property
562 AngularPropertyElementImpl property = new AngularPropertyElementImpl(name, nameOffset); 605 AngularPropertyElementImpl property = new AngularPropertyElementImpl(name, nameOffset);
563 property.field = field; 606 property.field = field;
564 property.propertyKind = kind; 607 property.propertyKind = kind;
565 property.fieldNameOffset = fieldNameOffset; 608 property.fieldNameOffset = fieldNameOffset;
566 properties.add(property); 609 properties.add(property);
567 } 610 }
568 } 611 }
569 612
570 void parseNgController() { 613 void parseNgController() {
571 bool isValid = true; 614 bool isValid = true;
615 // publishAs
572 if (!hasStringArgument(_PUBLISH_AS)) { 616 if (!hasStringArgument(_PUBLISH_AS)) {
573 reportErrorForAnnotation(AngularCode.MISSING_PUBLISH_AS, []); 617 reportErrorForAnnotation(AngularCode.MISSING_PUBLISH_AS, []);
574 isValid = false; 618 isValid = false;
575 } 619 }
620 // selector
576 AngularSelectorElement selector = null; 621 AngularSelectorElement selector = null;
577 if (!hasStringArgument(_SELECTOR)) { 622 if (!hasStringArgument(_SELECTOR)) {
578 reportErrorForAnnotation(AngularCode.MISSING_SELECTOR, []); 623 reportErrorForAnnotation(AngularCode.MISSING_SELECTOR, []);
579 isValid = false; 624 isValid = false;
580 } else { 625 } else {
581 SimpleStringLiteral selectorLiteral = getStringLiteral(_SELECTOR); 626 SimpleStringLiteral selectorLiteral = getStringLiteral(_SELECTOR);
582 selector = parseSelector2(selectorLiteral); 627 selector = parseSelector2(selectorLiteral);
583 if (selector == null) { 628 if (selector == null) {
584 reportErrorForArgument(_SELECTOR, AngularCode.CANNOT_PARSE_SELECTOR, [se lectorLiteral]); 629 reportErrorForArgument(_SELECTOR, AngularCode.CANNOT_PARSE_SELECTOR, [se lectorLiteral]);
585 isValid = false; 630 isValid = false;
586 } 631 }
587 } 632 }
633 // create
588 if (isValid) { 634 if (isValid) {
589 String name = getStringArgument(_PUBLISH_AS); 635 String name = getStringArgument(_PUBLISH_AS);
590 int nameOffset = getStringArgumentOffset(_PUBLISH_AS); 636 int nameOffset = getStringArgumentOffset(_PUBLISH_AS);
591 AngularControllerElementImpl element = new AngularControllerElementImpl(na me, nameOffset); 637 AngularControllerElementImpl element = new AngularControllerElementImpl(na me, nameOffset);
592 element.selector = selector; 638 element.selector = selector;
593 _classToolkitObjects.add(element); 639 _classToolkitObjects.add(element);
594 } 640 }
595 } 641 }
596 642
597 void parseNgDirective() { 643 void parseNgDirective() {
598 bool isValid = true; 644 bool isValid = true;
645 // selector
599 AngularSelectorElement selector = null; 646 AngularSelectorElement selector = null;
600 if (!hasStringArgument(_SELECTOR)) { 647 if (!hasStringArgument(_SELECTOR)) {
601 reportErrorForAnnotation(AngularCode.MISSING_SELECTOR, []); 648 reportErrorForAnnotation(AngularCode.MISSING_SELECTOR, []);
602 isValid = false; 649 isValid = false;
603 } else { 650 } else {
604 SimpleStringLiteral selectorLiteral = getStringLiteral(_SELECTOR); 651 SimpleStringLiteral selectorLiteral = getStringLiteral(_SELECTOR);
605 selector = parseSelector2(selectorLiteral); 652 selector = parseSelector2(selectorLiteral);
606 if (selector == null) { 653 if (selector == null) {
607 reportErrorForArgument(_SELECTOR, AngularCode.CANNOT_PARSE_SELECTOR, [se lectorLiteral]); 654 reportErrorForArgument(_SELECTOR, AngularCode.CANNOT_PARSE_SELECTOR, [se lectorLiteral]);
608 isValid = false; 655 isValid = false;
609 } 656 }
610 } 657 }
658 // create
611 if (isValid) { 659 if (isValid) {
612 int offset = _annotation.offset; 660 int offset = _annotation.offset;
613 AngularDirectiveElementImpl element = new AngularDirectiveElementImpl(offs et); 661 AngularDirectiveElementImpl element = new AngularDirectiveElementImpl(offs et);
614 element.selector = selector; 662 element.selector = selector;
615 element.properties = parseNgComponentProperties(false); 663 element.properties = parseNgComponentProperties(false);
616 _classToolkitObjects.add(element); 664 _classToolkitObjects.add(element);
617 } 665 }
618 } 666 }
619 667
620 void parseNgFilter() { 668 void parseNgFilter() {
621 bool isValid = true; 669 bool isValid = true;
670 // name
622 if (!hasStringArgument(_NAME)) { 671 if (!hasStringArgument(_NAME)) {
623 reportErrorForAnnotation(AngularCode.MISSING_NAME, []); 672 reportErrorForAnnotation(AngularCode.MISSING_NAME, []);
624 isValid = false; 673 isValid = false;
625 } 674 }
675 // create
626 if (isValid) { 676 if (isValid) {
627 String name = getStringArgument(_NAME); 677 String name = getStringArgument(_NAME);
628 int nameOffset = getStringArgumentOffset(_NAME); 678 int nameOffset = getStringArgumentOffset(_NAME);
629 _classToolkitObjects.add(new AngularFilterElementImpl(name, nameOffset)); 679 _classToolkitObjects.add(new AngularFilterElementImpl(name, nameOffset));
630 } 680 }
631 } 681 }
632 682
633 void reportError(ASTNode node, ErrorCode errorCode, List<Object> arguments) { 683 void reportError(ASTNode node, ErrorCode errorCode, List<Object> arguments) {
634 int offset = node.offset; 684 int offset = node.offset;
635 int length = node.length; 685 int length = node.length;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 RecursiveASTVisitor_AngularCompilationUnitBuilder_parseModuleVariables(this.An gularCompilationUnitBuilder_this) : super(); 723 RecursiveASTVisitor_AngularCompilationUnitBuilder_parseModuleVariables(this.An gularCompilationUnitBuilder_this) : super();
674 724
675 LocalVariableElementImpl _variable = null; 725 LocalVariableElementImpl _variable = null;
676 726
677 Expression _variableInit = null; 727 Expression _variableInit = null;
678 728
679 List<AngularModuleElement> _childModules = []; 729 List<AngularModuleElement> _childModules = [];
680 730
681 List<ClassElement> _keyTypes = []; 731 List<ClassElement> _keyTypes = [];
682 732
733 Object visitClassDeclaration(ClassDeclaration node) => null;
734
683 Object visitFunctionDeclaration(FunctionDeclaration node) { 735 Object visitFunctionDeclaration(FunctionDeclaration node) {
684 _childModules.clear(); 736 _childModules.clear();
685 _keyTypes.clear(); 737 _keyTypes.clear();
686 super.visitFunctionDeclaration(node); 738 super.visitFunctionDeclaration(node);
687 if (_variable != null) { 739 if (_variable != null) {
688 AngularModuleElementImpl module = AngularCompilationUnitBuilder_this.creat eModuleElement(_childModules, _keyTypes); 740 AngularModuleElementImpl module = AngularCompilationUnitBuilder_this.creat eModuleElement(_childModules, _keyTypes);
689 _variable.toolkitObjects = <ToolkitObjectElement> [module]; 741 _variable.toolkitObjects = <ToolkitObjectElement> [module];
690 } 742 }
691 return null; 743 return null;
692 } 744 }
(...skipping 11 matching lines...) Expand all
704 VariableElement element = node.element; 756 VariableElement element = node.element;
705 if (element is LocalVariableElementImpl && AngularCompilationUnitBuilder.isM odule2(node)) { 757 if (element is LocalVariableElementImpl && AngularCompilationUnitBuilder.isM odule2(node)) {
706 _variable = element; 758 _variable = element;
707 _variableInit = node.initializer; 759 _variableInit = node.initializer;
708 } 760 }
709 return super.visitVariableDeclaration(node); 761 return super.visitVariableDeclaration(node);
710 } 762 }
711 763
712 bool isVariableInvocation(MethodInvocation node) { 764 bool isVariableInvocation(MethodInvocation node) {
713 Expression target = node.realTarget; 765 Expression target = node.realTarget;
766 // var module = new Module()..type(t1)..type(t2);
714 if (_variableInit is CascadeExpression && target != null && identical(target .parent, _variableInit)) { 767 if (_variableInit is CascadeExpression && target != null && identical(target .parent, _variableInit)) {
715 return true; 768 return true;
716 } 769 }
770 // var module = new Module();
771 // module.type(t);
717 if (target is Identifier) { 772 if (target is Identifier) {
718 Element targetElement = target.staticElement; 773 Element targetElement = target.staticElement;
719 return identical(targetElement, _variable); 774 return identical(targetElement, _variable);
720 } 775 }
776 // no
721 return false; 777 return false;
722 } 778 }
723 } 779 }
724 780
725 /** 781 /**
726 * Instances of the class `CompilationUnitBuilder` build an element model for a single 782 * Instances of the class `CompilationUnitBuilder` build an element model for a single
727 * compilation unit. 783 * compilation unit.
728 * 784 *
729 * @coverage dart.engine.resolver 785 * @coverage dart.engine.resolver
730 */ 786 */
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 visitChildren(holder, node); 894 visitChildren(holder, node);
839 SimpleIdentifier className = node.name; 895 SimpleIdentifier className = node.name;
840 ClassElementImpl element = new ClassElementImpl(className); 896 ClassElementImpl element = new ClassElementImpl(className);
841 List<TypeParameterElement> typeParameters = holder.typeParameters; 897 List<TypeParameterElement> typeParameters = holder.typeParameters;
842 List<Type2> typeArguments = createTypeParameterTypes(typeParameters); 898 List<Type2> typeArguments = createTypeParameterTypes(typeParameters);
843 InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element); 899 InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
844 interfaceType.typeArguments = typeArguments; 900 interfaceType.typeArguments = typeArguments;
845 element.type = interfaceType; 901 element.type = interfaceType;
846 List<ConstructorElement> constructors = holder.constructors; 902 List<ConstructorElement> constructors = holder.constructors;
847 if (constructors.length == 0) { 903 if (constructors.length == 0) {
904 //
905 // Create the default constructor.
906 //
848 constructors = createDefaultConstructors(interfaceType); 907 constructors = createDefaultConstructors(interfaceType);
849 } 908 }
850 element.abstract = node.abstractKeyword != null; 909 element.abstract = node.abstractKeyword != null;
851 element.accessors = holder.accessors; 910 element.accessors = holder.accessors;
852 element.constructors = constructors; 911 element.constructors = constructors;
853 element.fields = holder.fields; 912 element.fields = holder.fields;
854 element.methods = holder.methods; 913 element.methods = holder.methods;
855 element.typeParameters = typeParameters; 914 element.typeParameters = typeParameters;
856 element.validMixin = _isValidMixin; 915 element.validMixin = _isValidMixin;
857 int functionTypeCount = _functionTypesToFix.length; 916 int functionTypeCount = _functionTypesToFix.length;
(...skipping 14 matching lines...) Expand all
872 SimpleIdentifier className = node.name; 931 SimpleIdentifier className = node.name;
873 ClassElementImpl element = new ClassElementImpl(className); 932 ClassElementImpl element = new ClassElementImpl(className);
874 element.abstract = node.abstractKeyword != null; 933 element.abstract = node.abstractKeyword != null;
875 element.typedef = true; 934 element.typedef = true;
876 List<TypeParameterElement> typeParameters = holder.typeParameters; 935 List<TypeParameterElement> typeParameters = holder.typeParameters;
877 element.typeParameters = typeParameters; 936 element.typeParameters = typeParameters;
878 List<Type2> typeArguments = createTypeParameterTypes(typeParameters); 937 List<Type2> typeArguments = createTypeParameterTypes(typeParameters);
879 InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element); 938 InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
880 interfaceType.typeArguments = typeArguments; 939 interfaceType.typeArguments = typeArguments;
881 element.type = interfaceType; 940 element.type = interfaceType;
941 // set default constructor
882 element.constructors = createDefaultConstructors(interfaceType); 942 element.constructors = createDefaultConstructors(interfaceType);
883 for (FunctionTypeImpl functionType in _functionTypesToFix) { 943 for (FunctionTypeImpl functionType in _functionTypesToFix) {
884 functionType.typeArguments = typeArguments; 944 functionType.typeArguments = typeArguments;
885 } 945 }
886 _functionTypesToFix = null; 946 _functionTypesToFix = null;
887 _currentHolder.addType(element); 947 _currentHolder.addType(element);
888 className.staticElement = element; 948 className.staticElement = element;
889 holder.validate(); 949 holder.validate();
890 return null; 950 return null;
891 } 951 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 SimpleIdentifier parameterName = node.parameter.identifier; 1004 SimpleIdentifier parameterName = node.parameter.identifier;
945 ParameterElementImpl parameter; 1005 ParameterElementImpl parameter;
946 if (node.parameter is FieldFormalParameter) { 1006 if (node.parameter is FieldFormalParameter) {
947 parameter = new DefaultFieldFormalParameterElementImpl(parameterName); 1007 parameter = new DefaultFieldFormalParameterElementImpl(parameterName);
948 } else { 1008 } else {
949 parameter = new DefaultParameterElementImpl(parameterName); 1009 parameter = new DefaultParameterElementImpl(parameterName);
950 } 1010 }
951 parameter.const3 = node.isConst; 1011 parameter.const3 = node.isConst;
952 parameter.final2 = node.isFinal; 1012 parameter.final2 = node.isFinal;
953 parameter.parameterKind = node.kind; 1013 parameter.parameterKind = node.kind;
1014 // set initializer, default value range
954 Expression defaultValue = node.defaultValue; 1015 Expression defaultValue = node.defaultValue;
955 if (defaultValue != null) { 1016 if (defaultValue != null) {
956 visit(holder, defaultValue); 1017 visit(holder, defaultValue);
957 FunctionElementImpl initializer = new FunctionElementImpl.con2(defaultValu e.beginToken.offset); 1018 FunctionElementImpl initializer = new FunctionElementImpl.con2(defaultValu e.beginToken.offset);
958 initializer.functions = holder.functions; 1019 initializer.functions = holder.functions;
959 initializer.labels = holder.labels; 1020 initializer.labels = holder.labels;
960 initializer.localVariables = holder.localVariables; 1021 initializer.localVariables = holder.localVariables;
961 initializer.parameters = holder.parameters; 1022 initializer.parameters = holder.parameters;
962 initializer.synthetic = true; 1023 initializer.synthetic = true;
963 parameter.initializer = initializer; 1024 parameter.initializer = initializer;
964 parameter.setDefaultValueRange(defaultValue.offset, defaultValue.length); 1025 parameter.setDefaultValueRange(defaultValue.offset, defaultValue.length);
965 } 1026 }
1027 // visible range
966 setParameterVisibleRange(node, parameter); 1028 setParameterVisibleRange(node, parameter);
967 _currentHolder.addParameter(parameter); 1029 _currentHolder.addParameter(parameter);
968 parameterName.staticElement = parameter; 1030 parameterName.staticElement = parameter;
969 node.parameter.accept(this); 1031 node.parameter.accept(this);
970 holder.validate(); 1032 holder.validate();
971 return null; 1033 return null;
972 } 1034 }
973 1035
974 Object visitFieldDeclaration(FieldDeclaration node) { 1036 Object visitFieldDeclaration(FieldDeclaration node) {
975 bool wasInField = _inFieldContext; 1037 bool wasInField = _inFieldContext;
976 _inFieldContext = true; 1038 _inFieldContext = true;
977 try { 1039 try {
978 node.visitChildren(this); 1040 node.visitChildren(this);
979 } finally { 1041 } finally {
980 _inFieldContext = wasInField; 1042 _inFieldContext = wasInField;
981 } 1043 }
982 return null; 1044 return null;
983 } 1045 }
984 1046
985 Object visitFieldFormalParameter(FieldFormalParameter node) { 1047 Object visitFieldFormalParameter(FieldFormalParameter node) {
986 if (node.parent is! DefaultFormalParameter) { 1048 if (node.parent is! DefaultFormalParameter) {
987 SimpleIdentifier parameterName = node.identifier; 1049 SimpleIdentifier parameterName = node.identifier;
988 FieldFormalParameterElementImpl parameter = new FieldFormalParameterElemen tImpl(parameterName); 1050 FieldFormalParameterElementImpl parameter = new FieldFormalParameterElemen tImpl(parameterName);
989 parameter.const3 = node.isConst; 1051 parameter.const3 = node.isConst;
990 parameter.final2 = node.isFinal; 1052 parameter.final2 = node.isFinal;
991 parameter.parameterKind = node.kind; 1053 parameter.parameterKind = node.kind;
992 _currentHolder.addParameter(parameter); 1054 _currentHolder.addParameter(parameter);
993 parameterName.staticElement = parameter; 1055 parameterName.staticElement = parameter;
994 } 1056 }
1057 //
1058 // The children of this parameter include any parameters defined on the type of this parameter.
1059 //
995 ElementHolder holder = new ElementHolder(); 1060 ElementHolder holder = new ElementHolder();
996 visitChildren(holder, node); 1061 visitChildren(holder, node);
997 (node.element as ParameterElementImpl).parameters = holder.parameters; 1062 (node.element as ParameterElementImpl).parameters = holder.parameters;
998 holder.validate(); 1063 holder.validate();
999 return null; 1064 return null;
1000 } 1065 }
1001 1066
1002 Object visitFunctionDeclaration(FunctionDeclaration node) { 1067 Object visitFunctionDeclaration(FunctionDeclaration node) {
1003 FunctionExpression expression = node.functionExpression; 1068 FunctionExpression expression = node.functionExpression;
1004 if (expression != null) { 1069 if (expression != null) {
(...skipping 20 matching lines...) Expand all
1025 int blockEnd = enclosingBlock.offset + enclosingBlock.length; 1090 int blockEnd = enclosingBlock.offset + enclosingBlock.length;
1026 element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1); 1091 element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
1027 } 1092 }
1028 } 1093 }
1029 _currentHolder.addFunction(element); 1094 _currentHolder.addFunction(element);
1030 expression.element = element; 1095 expression.element = element;
1031 functionName.staticElement = element; 1096 functionName.staticElement = element;
1032 } else { 1097 } else {
1033 SimpleIdentifier propertyNameNode = node.name; 1098 SimpleIdentifier propertyNameNode = node.name;
1034 if (propertyNameNode == null) { 1099 if (propertyNameNode == null) {
1100 // TODO(brianwilkerson) Report this internal error.
1035 return null; 1101 return null;
1036 } 1102 }
1037 String propertyName = propertyNameNode.name; 1103 String propertyName = propertyNameNode.name;
1038 TopLevelVariableElementImpl variable = _currentHolder.getTopLevelVariabl e(propertyName) as TopLevelVariableElementImpl; 1104 TopLevelVariableElementImpl variable = _currentHolder.getTopLevelVariabl e(propertyName) as TopLevelVariableElementImpl;
1039 if (variable == null) { 1105 if (variable == null) {
1040 variable = new TopLevelVariableElementImpl.con2(node.name.name); 1106 variable = new TopLevelVariableElementImpl.con2(node.name.name);
1041 variable.final2 = true; 1107 variable.final2 = true;
1042 variable.synthetic = true; 1108 variable.synthetic = true;
1043 _currentHolder.addTopLevelVariable(variable); 1109 _currentHolder.addTopLevelVariable(variable);
1044 } 1110 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1128 1194
1129 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { 1195 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
1130 if (node.parent is! DefaultFormalParameter) { 1196 if (node.parent is! DefaultFormalParameter) {
1131 SimpleIdentifier parameterName = node.identifier; 1197 SimpleIdentifier parameterName = node.identifier;
1132 ParameterElementImpl parameter = new ParameterElementImpl.con1(parameterNa me); 1198 ParameterElementImpl parameter = new ParameterElementImpl.con1(parameterNa me);
1133 parameter.parameterKind = node.kind; 1199 parameter.parameterKind = node.kind;
1134 setParameterVisibleRange(node, parameter); 1200 setParameterVisibleRange(node, parameter);
1135 _currentHolder.addParameter(parameter); 1201 _currentHolder.addParameter(parameter);
1136 parameterName.staticElement = parameter; 1202 parameterName.staticElement = parameter;
1137 } 1203 }
1204 //
1205 // The children of this parameter include any parameters defined on the type of this parameter.
1206 //
1138 ElementHolder holder = new ElementHolder(); 1207 ElementHolder holder = new ElementHolder();
1139 visitChildren(holder, node); 1208 visitChildren(holder, node);
1140 (node.element as ParameterElementImpl).parameters = holder.parameters; 1209 (node.element as ParameterElementImpl).parameters = holder.parameters;
1141 holder.validate(); 1210 holder.validate();
1142 return null; 1211 return null;
1143 } 1212 }
1144 1213
1145 Object visitLabeledStatement(LabeledStatement node) { 1214 Object visitLabeledStatement(LabeledStatement node) {
1146 bool onSwitchStatement = node.statement is SwitchStatement; 1215 bool onSwitchStatement = node.statement is SwitchStatement;
1147 for (Label label in node.labels) { 1216 for (Label label in node.labels) {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 LocalVariableElementImpl variable; 1362 LocalVariableElementImpl variable;
1294 if (isConst && hasInitializer) { 1363 if (isConst && hasInitializer) {
1295 variable = new ConstLocalVariableElementImpl(variableName); 1364 variable = new ConstLocalVariableElementImpl(variableName);
1296 } else { 1365 } else {
1297 variable = new LocalVariableElementImpl(variableName); 1366 variable = new LocalVariableElementImpl(variableName);
1298 } 1367 }
1299 element = variable; 1368 element = variable;
1300 Block enclosingBlock = node.getAncestor(Block); 1369 Block enclosingBlock = node.getAncestor(Block);
1301 int functionEnd = node.offset + node.length; 1370 int functionEnd = node.offset + node.length;
1302 int blockEnd = enclosingBlock.offset + enclosingBlock.length; 1371 int blockEnd = enclosingBlock.offset + enclosingBlock.length;
1372 // TODO(brianwilkerson) This isn't right for variables declared in a for l oop.
1303 variable.setVisibleRange(functionEnd, blockEnd - functionEnd - 1); 1373 variable.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
1304 _currentHolder.addLocalVariable(variable); 1374 _currentHolder.addLocalVariable(variable);
1305 variableName.staticElement = element; 1375 variableName.staticElement = element;
1306 } else { 1376 } else {
1307 SimpleIdentifier variableName = node.name; 1377 SimpleIdentifier variableName = node.name;
1308 TopLevelVariableElementImpl variable; 1378 TopLevelVariableElementImpl variable;
1309 if (isConst && hasInitializer) { 1379 if (isConst && hasInitializer) {
1310 variable = new ConstTopLevelVariableElementImpl(variableName); 1380 variable = new ConstTopLevelVariableElementImpl(variableName);
1311 } else { 1381 } else {
1312 variable = new TopLevelVariableElementImpl.con1(variableName); 1382 variable = new TopLevelVariableElementImpl.con1(variableName);
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
1920 String scriptSourcePath = scriptAttribute == null ? null : scriptAttribute .text; 1990 String scriptSourcePath = scriptAttribute == null ? null : scriptAttribute .text;
1921 if (identical(node.attributeEnd.type, ht.TokenType.GT) && scriptSourcePath == null) { 1991 if (identical(node.attributeEnd.type, ht.TokenType.GT) && scriptSourcePath == null) {
1922 EmbeddedHtmlScriptElementImpl script = new EmbeddedHtmlScriptElementImpl (node); 1992 EmbeddedHtmlScriptElementImpl script = new EmbeddedHtmlScriptElementImpl (node);
1923 try { 1993 try {
1924 LibraryResolver resolver = new LibraryResolver(_context); 1994 LibraryResolver resolver = new LibraryResolver(_context);
1925 LibraryElementImpl library = resolver.resolveEmbeddedLibrary(htmlSourc e, _modificationStamp, node.script, true) as LibraryElementImpl; 1995 LibraryElementImpl library = resolver.resolveEmbeddedLibrary(htmlSourc e, _modificationStamp, node.script, true) as LibraryElementImpl;
1926 script.scriptLibrary = library; 1996 script.scriptLibrary = library;
1927 _resolvedLibraries.addAll(resolver.resolvedLibraries); 1997 _resolvedLibraries.addAll(resolver.resolvedLibraries);
1928 _errorListener.addAll(resolver.errorListener); 1998 _errorListener.addAll(resolver.errorListener);
1929 } on AnalysisException catch (exception) { 1999 } on AnalysisException catch (exception) {
2000 //TODO (danrubel): Handle or forward the exception
1930 AnalysisEngine.instance.logger.logError3(exception); 2001 AnalysisEngine.instance.logger.logError3(exception);
1931 } 2002 }
1932 node.scriptElement = script; 2003 node.scriptElement = script;
1933 _scripts.add(script); 2004 _scripts.add(script);
1934 } else { 2005 } else {
1935 ExternalHtmlScriptElementImpl script = new ExternalHtmlScriptElementImpl (node); 2006 ExternalHtmlScriptElementImpl script = new ExternalHtmlScriptElementImpl (node);
1936 if (scriptSourcePath != null) { 2007 if (scriptSourcePath != null) {
1937 try { 2008 try {
1938 scriptSourcePath = Uri.encodeFull(scriptSourcePath); 2009 scriptSourcePath = Uri.encodeFull(scriptSourcePath);
2010 // Force an exception to be thrown if the URI is invalid so that we can report the
2011 // problem.
1939 parseUriWithException(scriptSourcePath); 2012 parseUriWithException(scriptSourcePath);
1940 Source scriptSource = _context.sourceFactory.resolveUri(htmlSource, scriptSourcePath); 2013 Source scriptSource = _context.sourceFactory.resolveUri(htmlSource, scriptSourcePath);
1941 script.scriptSource = scriptSource; 2014 script.scriptSource = scriptSource;
1942 if (scriptSource == null || !scriptSource.exists()) { 2015 if (scriptSource == null || !scriptSource.exists()) {
1943 reportValueError(HtmlWarningCode.URI_DOES_NOT_EXIST, scriptAttribu te, [scriptSourcePath]); 2016 reportValueError(HtmlWarningCode.URI_DOES_NOT_EXIST, scriptAttribu te, [scriptSourcePath]);
1944 } 2017 }
1945 } on URISyntaxException catch (exception) { 2018 } on URISyntaxException catch (exception) {
1946 reportValueError(HtmlWarningCode.INVALID_URI, scriptAttribute, [scri ptSourcePath]); 2019 reportValueError(HtmlWarningCode.INVALID_URI, scriptAttribute, [scri ptSourcePath]);
1947 } 2020 }
1948 } 2021 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2000 ht.XmlAttributeNode getScriptSourcePath(ht.XmlTagNode node) { 2073 ht.XmlAttributeNode getScriptSourcePath(ht.XmlTagNode node) {
2001 for (ht.XmlAttributeNode attribute in node.attributes) { 2074 for (ht.XmlAttributeNode attribute in node.attributes) {
2002 if (attribute.name == _SRC) { 2075 if (attribute.name == _SRC) {
2003 return attribute; 2076 return attribute;
2004 } 2077 }
2005 } 2078 }
2006 return null; 2079 return null;
2007 } 2080 }
2008 2081
2009 Object reportCircularity(ht.XmlTagNode node) { 2082 Object reportCircularity(ht.XmlTagNode node) {
2083 //
2084 // This should not be possible, but we have an error report that suggests th at it happened at
2085 // least once. This code will guard against infinite recursion and might hel p us identify the
2086 // cause of the issue.
2087 //
2010 JavaStringBuilder builder = new JavaStringBuilder(); 2088 JavaStringBuilder builder = new JavaStringBuilder();
2011 builder.append("Found circularity in XML nodes: "); 2089 builder.append("Found circularity in XML nodes: ");
2012 bool first = true; 2090 bool first = true;
2013 for (ht.XmlTagNode pathNode in _parentNodes) { 2091 for (ht.XmlTagNode pathNode in _parentNodes) {
2014 if (first) { 2092 if (first) {
2015 first = false; 2093 first = false;
2016 } else { 2094 } else {
2017 builder.append(", "); 2095 builder.append(", ");
2018 } 2096 }
2019 String tagName = pathNode.tag; 2097 String tagName = pathNode.tag;
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 Object visitBinaryExpression(BinaryExpression node) { 2212 Object visitBinaryExpression(BinaryExpression node) {
2135 checkForDivisionOptimizationHint(node); 2213 checkForDivisionOptimizationHint(node);
2136 checkForDeprecatedMemberUse(node.bestElement, node); 2214 checkForDeprecatedMemberUse(node.bestElement, node);
2137 return super.visitBinaryExpression(node); 2215 return super.visitBinaryExpression(node);
2138 } 2216 }
2139 2217
2140 Object visitClassDeclaration(ClassDeclaration node) { 2218 Object visitClassDeclaration(ClassDeclaration node) {
2141 ClassElement outerClass = _enclosingClass; 2219 ClassElement outerClass = _enclosingClass;
2142 try { 2220 try {
2143 _enclosingClass = node.element; 2221 _enclosingClass = node.element;
2222 // Commented out until we decide that we want this hint in the analyzer
2223 // checkForOverrideEqualsButNotHashCode(node);
2144 return super.visitClassDeclaration(node); 2224 return super.visitClassDeclaration(node);
2145 } finally { 2225 } finally {
2146 _enclosingClass = outerClass; 2226 _enclosingClass = outerClass;
2147 } 2227 }
2148 } 2228 }
2149 2229
2150 Object visitExportDirective(ExportDirective node) { 2230 Object visitExportDirective(ExportDirective node) {
2151 checkForDeprecatedMemberUse(node.uriElement, node); 2231 checkForDeprecatedMemberUse(node.uriElement, node);
2152 return super.visitExportDirective(node); 2232 return super.visitExportDirective(node);
2153 } 2233 }
(...skipping 17 matching lines...) Expand all
2171 checkForDeprecatedMemberUse(node.staticElement, node); 2251 checkForDeprecatedMemberUse(node.staticElement, node);
2172 return super.visitInstanceCreationExpression(node); 2252 return super.visitInstanceCreationExpression(node);
2173 } 2253 }
2174 2254
2175 Object visitIsExpression(IsExpression node) { 2255 Object visitIsExpression(IsExpression node) {
2176 checkAllTypeChecks(node); 2256 checkAllTypeChecks(node);
2177 return super.visitIsExpression(node); 2257 return super.visitIsExpression(node);
2178 } 2258 }
2179 2259
2180 Object visitMethodDeclaration(MethodDeclaration node) { 2260 Object visitMethodDeclaration(MethodDeclaration node) {
2181 checkForOverridingPrivateMember(node); 2261 // This was determined to not be a good hint, see: dartbug.com/16029
2262 //checkForOverridingPrivateMember(node);
2182 checkForMissingReturn(node.returnType, node.body); 2263 checkForMissingReturn(node.returnType, node.body);
2183 return super.visitMethodDeclaration(node); 2264 return super.visitMethodDeclaration(node);
2184 } 2265 }
2185 2266
2186 Object visitPostfixExpression(PostfixExpression node) { 2267 Object visitPostfixExpression(PostfixExpression node) {
2187 checkForDeprecatedMemberUse(node.bestElement, node); 2268 checkForDeprecatedMemberUse(node.bestElement, node);
2188 return super.visitPostfixExpression(node); 2269 return super.visitPostfixExpression(node);
2189 } 2270 }
2190 2271
2191 Object visitPrefixExpression(PrefixExpression node) { 2272 Object visitPrefixExpression(PrefixExpression node) {
(...skipping 29 matching lines...) Expand all
2221 */ 2302 */
2222 bool checkAllTypeChecks(IsExpression node) { 2303 bool checkAllTypeChecks(IsExpression node) {
2223 Expression expression = node.expression; 2304 Expression expression = node.expression;
2224 TypeName typeName = node.type; 2305 TypeName typeName = node.type;
2225 Type2 lhsType = expression.staticType; 2306 Type2 lhsType = expression.staticType;
2226 Type2 rhsType = typeName.type; 2307 Type2 rhsType = typeName.type;
2227 if (lhsType == null || rhsType == null) { 2308 if (lhsType == null || rhsType == null) {
2228 return false; 2309 return false;
2229 } 2310 }
2230 String rhsNameStr = typeName.name.name; 2311 String rhsNameStr = typeName.name.name;
2312 // if x is dynamic
2231 if (rhsType.isDynamic && rhsNameStr == sc.Keyword.DYNAMIC.syntax) { 2313 if (rhsType.isDynamic && rhsNameStr == sc.Keyword.DYNAMIC.syntax) {
2232 if (node.notOperator == null) { 2314 if (node.notOperator == null) {
2315 // the is case
2233 _errorReporter.reportError3(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node, []); 2316 _errorReporter.reportError3(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node, []);
2234 } else { 2317 } else {
2318 // the is not case
2235 _errorReporter.reportError3(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, node, []); 2319 _errorReporter.reportError3(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, node, []);
2236 } 2320 }
2237 return true; 2321 return true;
2238 } 2322 }
2239 Element rhsElement = rhsType.element; 2323 Element rhsElement = rhsType.element;
2240 LibraryElement libraryElement = rhsElement != null ? rhsElement.library : nu ll; 2324 LibraryElement libraryElement = rhsElement != null ? rhsElement.library : nu ll;
2241 if (libraryElement != null && libraryElement.isDartCore) { 2325 if (libraryElement != null && libraryElement.isDartCore) {
2326 // if x is Object or null is Null
2242 if (rhsType.isObject || (expression is NullLiteral && rhsNameStr == _NULL_ TYPE_NAME)) { 2327 if (rhsType.isObject || (expression is NullLiteral && rhsNameStr == _NULL_ TYPE_NAME)) {
2243 if (node.notOperator == null) { 2328 if (node.notOperator == null) {
2329 // the is case
2244 _errorReporter.reportError3(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node , []); 2330 _errorReporter.reportError3(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node , []);
2245 } else { 2331 } else {
2332 // the is not case
2246 _errorReporter.reportError3(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, nod e, []); 2333 _errorReporter.reportError3(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, nod e, []);
2247 } 2334 }
2248 return true; 2335 return true;
2249 } else if (rhsNameStr == _NULL_TYPE_NAME) { 2336 } else if (rhsNameStr == _NULL_TYPE_NAME) {
2250 if (node.notOperator == null) { 2337 if (node.notOperator == null) {
2338 // the is case
2251 _errorReporter.reportError3(HintCode.TYPE_CHECK_IS_NULL, node, []); 2339 _errorReporter.reportError3(HintCode.TYPE_CHECK_IS_NULL, node, []);
2252 } else { 2340 } else {
2341 // the is not case
2253 _errorReporter.reportError3(HintCode.TYPE_CHECK_IS_NOT_NULL, node, []) ; 2342 _errorReporter.reportError3(HintCode.TYPE_CHECK_IS_NOT_NULL, node, []) ;
2254 } 2343 }
2255 return true; 2344 return true;
2256 } 2345 }
2257 } 2346 }
2258 return false; 2347 return false;
2259 } 2348 }
2260 2349
2261 /** 2350 /**
2262 * Given some [Element], look at the associated metadata and report the use of the member if 2351 * Given some [Element], look at the associated metadata and report the use of the member if
2263 * it is declared as deprecated. 2352 * it is declared as deprecated.
2264 * 2353 *
2265 * @param element some element to check for deprecated use of 2354 * @param element some element to check for deprecated use of
2266 * @param node the node use for the location of the error 2355 * @param node the node use for the location of the error
2267 * @return `true` if and only if a hint code is generated on the passed node 2356 * @return `true` if and only if a hint code is generated on the passed node
2268 * @see HintCode#DEPRECATED_MEMBER_USE 2357 * @see HintCode#DEPRECATED_MEMBER_USE
2269 */ 2358 */
2270 bool checkForDeprecatedMemberUse(Element element, ASTNode node) { 2359 bool checkForDeprecatedMemberUse(Element element, ASTNode node) {
2271 if (element != null && element.isDeprecated) { 2360 if (element != null && element.isDeprecated) {
2272 String displayName = element.displayName; 2361 String displayName = element.displayName;
2273 if (element is ConstructorElement) { 2362 if (element is ConstructorElement) {
2363 // TODO(jwren) We should modify ConstructorElement.getDisplayName(), or have the logic
2364 // centralized elsewhere, instead of doing this logic here.
2274 ConstructorElement constructorElement = element; 2365 ConstructorElement constructorElement = element;
2275 displayName = constructorElement.enclosingElement.displayName; 2366 displayName = constructorElement.enclosingElement.displayName;
2276 if (!constructorElement.displayName.isEmpty) { 2367 if (!constructorElement.displayName.isEmpty) {
2277 displayName = "${displayName}.${constructorElement.displayName}"; 2368 displayName = "${displayName}.${constructorElement.displayName}";
2278 } 2369 }
2279 } 2370 }
2280 _errorReporter.reportError3(HintCode.DEPRECATED_MEMBER_USE, node, [display Name]); 2371 _errorReporter.reportError3(HintCode.DEPRECATED_MEMBER_USE, node, [display Name]);
2281 return true; 2372 return true;
2282 } 2373 }
2283 return false; 2374 return false;
(...skipping 25 matching lines...) Expand all
2309 } 2400 }
2310 2401
2311 /** 2402 /**
2312 * Check for the passed binary expression for the [HintCode#DIVISION_OPTIMIZAT ION]. 2403 * Check for the passed binary expression for the [HintCode#DIVISION_OPTIMIZAT ION].
2313 * 2404 *
2314 * @param node the binary expression to check 2405 * @param node the binary expression to check
2315 * @return `true` if and only if a hint code is generated on the passed node 2406 * @return `true` if and only if a hint code is generated on the passed node
2316 * @see HintCode#DIVISION_OPTIMIZATION 2407 * @see HintCode#DIVISION_OPTIMIZATION
2317 */ 2408 */
2318 bool checkForDivisionOptimizationHint(BinaryExpression node) { 2409 bool checkForDivisionOptimizationHint(BinaryExpression node) {
2410 // Return if the operator is not '/'
2319 if (node.operator.type != sc.TokenType.SLASH) { 2411 if (node.operator.type != sc.TokenType.SLASH) {
2320 return false; 2412 return false;
2321 } 2413 }
2414 // Return if the '/' operator is not defined in core, or if we don't know it s static or propagated type
2322 MethodElement methodElement = node.bestElement; 2415 MethodElement methodElement = node.bestElement;
2323 if (methodElement == null) { 2416 if (methodElement == null) {
2324 return false; 2417 return false;
2325 } 2418 }
2326 LibraryElement libraryElement = methodElement.library; 2419 LibraryElement libraryElement = methodElement.library;
2327 if (libraryElement != null && !libraryElement.isDartCore) { 2420 if (libraryElement != null && !libraryElement.isDartCore) {
2328 return false; 2421 return false;
2329 } 2422 }
2423 // Report error if the (x/y) has toInt() invoked on it
2330 if (node.parent is ParenthesizedExpression) { 2424 if (node.parent is ParenthesizedExpression) {
2331 ParenthesizedExpression parenthesizedExpression = wrapParenthesizedExpress ion(node.parent as ParenthesizedExpression); 2425 ParenthesizedExpression parenthesizedExpression = wrapParenthesizedExpress ion(node.parent as ParenthesizedExpression);
2332 if (parenthesizedExpression.parent is MethodInvocation) { 2426 if (parenthesizedExpression.parent is MethodInvocation) {
2333 MethodInvocation methodInvocation = parenthesizedExpression.parent as Me thodInvocation; 2427 MethodInvocation methodInvocation = parenthesizedExpression.parent as Me thodInvocation;
2334 if (_TO_INT_METHOD_NAME == methodInvocation.methodName.name && methodInv ocation.argumentList.arguments.isEmpty) { 2428 if (_TO_INT_METHOD_NAME == methodInvocation.methodName.name && methodInv ocation.argumentList.arguments.isEmpty) {
2335 _errorReporter.reportError3(HintCode.DIVISION_OPTIMIZATION, methodInvo cation, []); 2429 _errorReporter.reportError3(HintCode.DIVISION_OPTIMIZATION, methodInvo cation, []);
2336 return true; 2430 return true;
2337 } 2431 }
2338 } 2432 }
2339 } 2433 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2378 2472
2379 /** 2473 /**
2380 * Checks that if the passed method declaration is private, it does not overri de a private member 2474 * Checks that if the passed method declaration is private, it does not overri de a private member
2381 * in a superclass. 2475 * in a superclass.
2382 * 2476 *
2383 * @param node the method declaration to check 2477 * @param node the method declaration to check
2384 * @return `true` if and only if a hint code is generated on the passed node 2478 * @return `true` if and only if a hint code is generated on the passed node
2385 * @see HintCode#OVERRIDDING_PRIVATE_MEMBER 2479 * @see HintCode#OVERRIDDING_PRIVATE_MEMBER
2386 */ 2480 */
2387 bool checkForOverridingPrivateMember(MethodDeclaration node) { 2481 bool checkForOverridingPrivateMember(MethodDeclaration node) {
2482 // If not in an enclosing class, return false
2388 if (_enclosingClass == null) { 2483 if (_enclosingClass == null) {
2389 return false; 2484 return false;
2390 } 2485 }
2486 // If the member is not private, return false
2391 if (!Identifier.isPrivateName(node.name.name)) { 2487 if (!Identifier.isPrivateName(node.name.name)) {
2392 return false; 2488 return false;
2393 } 2489 }
2490 // Get the element of the member, if null, return false
2394 ExecutableElement executableElement = node.element; 2491 ExecutableElement executableElement = node.element;
2395 if (executableElement == null) { 2492 if (executableElement == null) {
2396 return false; 2493 return false;
2397 } 2494 }
2495 // Loop through all of the superclasses looking for a matching method or acc essor
2496 // TODO(jwren) If the HintGenerator needs or has easy access to the Inherita nceManager in the
2497 // future then this could be refactored down to be more readable, however, s ince we are only
2498 // looking through super classes (and not the entire interface graph) there is no pressing need
2398 String elementName = executableElement.name; 2499 String elementName = executableElement.name;
2399 bool isGetterOrSetter = executableElement is PropertyAccessorElement; 2500 bool isGetterOrSetter = executableElement is PropertyAccessorElement;
2400 InterfaceType superType = _enclosingClass.supertype; 2501 InterfaceType superType = _enclosingClass.supertype;
2401 if (superType == null) { 2502 if (superType == null) {
2402 return false; 2503 return false;
2403 } 2504 }
2404 ClassElement classElement = superType.element; 2505 ClassElement classElement = superType.element;
2405 while (classElement != null) { 2506 while (classElement != null) {
2406 if (_enclosingClass.library != classElement.library) { 2507 if (_enclosingClass.library != classElement.library) {
2407 if (isGetterOrSetter) { 2508 if (isGetterOrSetter) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2443 * 2544 *
2444 * @param node the as expression to check 2545 * @param node the as expression to check
2445 * @return `true` if and only if a hint code is generated on the passed node 2546 * @return `true` if and only if a hint code is generated on the passed node
2446 * @see HintCode#UNNECESSARY_CAST 2547 * @see HintCode#UNNECESSARY_CAST
2447 */ 2548 */
2448 bool checkForUnnecessaryCast(AsExpression node) { 2549 bool checkForUnnecessaryCast(AsExpression node) {
2449 Expression expression = node.expression; 2550 Expression expression = node.expression;
2450 TypeName typeName = node.type; 2551 TypeName typeName = node.type;
2451 Type2 lhsType = expression.staticType; 2552 Type2 lhsType = expression.staticType;
2452 Type2 rhsType = typeName.type; 2553 Type2 rhsType = typeName.type;
2554 // TODO(jwren) After dartbug.com/13732, revisit this, we should be able to r emove the
2555 // !(x instanceof TypeParameterType) checks.
2453 if (lhsType != null && rhsType != null && !lhsType.isDynamic && !rhsType.isD ynamic && lhsType is! TypeParameterType && rhsType is! TypeParameterType && lhsT ype.isSubtypeOf(rhsType)) { 2556 if (lhsType != null && rhsType != null && !lhsType.isDynamic && !rhsType.isD ynamic && lhsType is! TypeParameterType && rhsType is! TypeParameterType && lhsT ype.isSubtypeOf(rhsType)) {
2454 _errorReporter.reportError3(HintCode.UNNECESSARY_CAST, node, []); 2557 _errorReporter.reportError3(HintCode.UNNECESSARY_CAST, node, []);
2455 return true; 2558 return true;
2456 } 2559 }
2457 return false; 2560 return false;
2458 } 2561 }
2459 } 2562 }
2460 2563
2461 /** 2564 /**
2462 * Instances of the class `Dart2JSVerifier` traverse an AST structure looking fo r hints for 2565 * Instances of the class `Dart2JSVerifier` traverse an AST structure looking fo r hints for
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2500 * @see HintCode#IS_NOT_DOUBLE 2603 * @see HintCode#IS_NOT_DOUBLE
2501 * @see HintCode#IS_NOT_INT 2604 * @see HintCode#IS_NOT_INT
2502 */ 2605 */
2503 bool checkForIsDoubleHints(IsExpression node) { 2606 bool checkForIsDoubleHints(IsExpression node) {
2504 TypeName typeName = node.type; 2607 TypeName typeName = node.type;
2505 Type2 type = typeName.type; 2608 Type2 type = typeName.type;
2506 if (type != null && type.element != null) { 2609 if (type != null && type.element != null) {
2507 Element element = type.element; 2610 Element element = type.element;
2508 String typeNameStr = element.name; 2611 String typeNameStr = element.name;
2509 LibraryElement libraryElement = element.library; 2612 LibraryElement libraryElement = element.library;
2613 // if (typeNameStr.equals(INT_TYPE_NAME) && libraryElement != null
2614 // && libraryElement.isDartCore()) {
2615 // if (node.getNotOperator() == null) {
2616 // errorReporter.reportError(HintCode.IS_INT, node);
2617 // } else {
2618 // errorReporter.reportError(HintCode.IS_NOT_INT, node);
2619 // }
2620 // return true;
2621 // } else
2510 if (typeNameStr == _DOUBLE_TYPE_NAME && libraryElement != null && libraryE lement.isDartCore) { 2622 if (typeNameStr == _DOUBLE_TYPE_NAME && libraryElement != null && libraryE lement.isDartCore) {
2511 if (node.notOperator == null) { 2623 if (node.notOperator == null) {
2512 _errorReporter.reportError3(HintCode.IS_DOUBLE, node, []); 2624 _errorReporter.reportError3(HintCode.IS_DOUBLE, node, []);
2513 } else { 2625 } else {
2514 _errorReporter.reportError3(HintCode.IS_NOT_DOUBLE, node, []); 2626 _errorReporter.reportError3(HintCode.IS_NOT_DOUBLE, node, []);
2515 } 2627 }
2516 return true; 2628 return true;
2517 } 2629 }
2518 } 2630 }
2519 return false; 2631 return false;
(...skipping 24 matching lines...) Expand all
2544 Object visitBinaryExpression(BinaryExpression node) { 2656 Object visitBinaryExpression(BinaryExpression node) {
2545 sc.Token operator = node.operator; 2657 sc.Token operator = node.operator;
2546 bool isAmpAmp = identical(operator.type, sc.TokenType.AMPERSAND_AMPERSAND); 2658 bool isAmpAmp = identical(operator.type, sc.TokenType.AMPERSAND_AMPERSAND);
2547 bool isBarBar = identical(operator.type, sc.TokenType.BAR_BAR); 2659 bool isBarBar = identical(operator.type, sc.TokenType.BAR_BAR);
2548 if (isAmpAmp || isBarBar) { 2660 if (isAmpAmp || isBarBar) {
2549 Expression lhsCondition = node.leftOperand; 2661 Expression lhsCondition = node.leftOperand;
2550 if (!isDebugConstant(lhsCondition)) { 2662 if (!isDebugConstant(lhsCondition)) {
2551 ValidResult lhsResult = getConstantBooleanValue(lhsCondition); 2663 ValidResult lhsResult = getConstantBooleanValue(lhsCondition);
2552 if (lhsResult != null) { 2664 if (lhsResult != null) {
2553 if (lhsResult.isTrue && isBarBar) { 2665 if (lhsResult.isTrue && isBarBar) {
2666 // report error on else block: true || !e!
2554 _errorReporter.reportError3(HintCode.DEAD_CODE, node.rightOperand, [ ]); 2667 _errorReporter.reportError3(HintCode.DEAD_CODE, node.rightOperand, [ ]);
2668 // only visit the LHS:
2555 safelyVisit(lhsCondition); 2669 safelyVisit(lhsCondition);
2556 return null; 2670 return null;
2557 } else if (lhsResult.isFalse && isAmpAmp) { 2671 } else if (lhsResult.isFalse && isAmpAmp) {
2672 // report error on if block: false && !e!
2558 _errorReporter.reportError3(HintCode.DEAD_CODE, node.rightOperand, [ ]); 2673 _errorReporter.reportError3(HintCode.DEAD_CODE, node.rightOperand, [ ]);
2674 // only visit the LHS:
2559 safelyVisit(lhsCondition); 2675 safelyVisit(lhsCondition);
2560 return null; 2676 return null;
2561 } 2677 }
2562 } 2678 }
2563 } 2679 }
2564 } 2680 }
2565 return super.visitBinaryExpression(node); 2681 return super.visitBinaryExpression(node);
2566 } 2682 }
2567 2683
2568 /** 2684 /**
(...skipping 20 matching lines...) Expand all
2589 return null; 2705 return null;
2590 } 2706 }
2591 2707
2592 Object visitConditionalExpression(ConditionalExpression node) { 2708 Object visitConditionalExpression(ConditionalExpression node) {
2593 Expression conditionExpression = node.condition; 2709 Expression conditionExpression = node.condition;
2594 safelyVisit(conditionExpression); 2710 safelyVisit(conditionExpression);
2595 if (!isDebugConstant(conditionExpression)) { 2711 if (!isDebugConstant(conditionExpression)) {
2596 ValidResult result = getConstantBooleanValue(conditionExpression); 2712 ValidResult result = getConstantBooleanValue(conditionExpression);
2597 if (result != null) { 2713 if (result != null) {
2598 if (result.isTrue) { 2714 if (result.isTrue) {
2715 // report error on else block: true ? 1 : !2!
2599 _errorReporter.reportError3(HintCode.DEAD_CODE, node.elseExpression, [ ]); 2716 _errorReporter.reportError3(HintCode.DEAD_CODE, node.elseExpression, [ ]);
2600 safelyVisit(node.thenExpression); 2717 safelyVisit(node.thenExpression);
2601 return null; 2718 return null;
2602 } else { 2719 } else {
2720 // report error on if block: false ? !1! : 2
2603 _errorReporter.reportError3(HintCode.DEAD_CODE, node.thenExpression, [ ]); 2721 _errorReporter.reportError3(HintCode.DEAD_CODE, node.thenExpression, [ ]);
2604 safelyVisit(node.elseExpression); 2722 safelyVisit(node.elseExpression);
2605 return null; 2723 return null;
2606 } 2724 }
2607 } 2725 }
2608 } 2726 }
2609 return super.visitConditionalExpression(node); 2727 return super.visitConditionalExpression(node);
2610 } 2728 }
2611 2729
2612 Object visitIfStatement(IfStatement node) { 2730 Object visitIfStatement(IfStatement node) {
2613 Expression conditionExpression = node.condition; 2731 Expression conditionExpression = node.condition;
2614 safelyVisit(conditionExpression); 2732 safelyVisit(conditionExpression);
2615 if (!isDebugConstant(conditionExpression)) { 2733 if (!isDebugConstant(conditionExpression)) {
2616 ValidResult result = getConstantBooleanValue(conditionExpression); 2734 ValidResult result = getConstantBooleanValue(conditionExpression);
2617 if (result != null) { 2735 if (result != null) {
2618 if (result.isTrue) { 2736 if (result.isTrue) {
2737 // report error on else block: if(true) {} else {!}
2619 Statement elseStatement = node.elseStatement; 2738 Statement elseStatement = node.elseStatement;
2620 if (elseStatement != null) { 2739 if (elseStatement != null) {
2621 _errorReporter.reportError3(HintCode.DEAD_CODE, elseStatement, []); 2740 _errorReporter.reportError3(HintCode.DEAD_CODE, elseStatement, []);
2622 safelyVisit(node.thenStatement); 2741 safelyVisit(node.thenStatement);
2623 return null; 2742 return null;
2624 } 2743 }
2625 } else { 2744 } else {
2745 // report error on if block: if (false) {!} else {}
2626 _errorReporter.reportError3(HintCode.DEAD_CODE, node.thenStatement, [] ); 2746 _errorReporter.reportError3(HintCode.DEAD_CODE, node.thenStatement, [] );
2627 safelyVisit(node.elseStatement); 2747 safelyVisit(node.elseStatement);
2628 return null; 2748 return null;
2629 } 2749 }
2630 } 2750 }
2631 } 2751 }
2632 return super.visitIfStatement(node); 2752 return super.visitIfStatement(node);
2633 } 2753 }
2634 2754
2635 Object visitTryStatement(TryStatement node) { 2755 Object visitTryStatement(TryStatement node) {
2636 safelyVisit(node.body); 2756 safelyVisit(node.body);
2637 safelyVisit(node.finallyBlock); 2757 safelyVisit(node.finallyBlock);
2638 NodeList<CatchClause> catchClauses = node.catchClauses; 2758 NodeList<CatchClause> catchClauses = node.catchClauses;
2639 int numOfCatchClauses = catchClauses.length; 2759 int numOfCatchClauses = catchClauses.length;
2640 List<Type2> visitedTypes = new List<Type2>(); 2760 List<Type2> visitedTypes = new List<Type2>();
2641 for (int i = 0; i < numOfCatchClauses; i++) { 2761 for (int i = 0; i < numOfCatchClauses; i++) {
2642 CatchClause catchClause = catchClauses[i]; 2762 CatchClause catchClause = catchClauses[i];
2643 if (catchClause.onKeyword != null) { 2763 if (catchClause.onKeyword != null) {
2764 // on-catch clause found, verify that the exception type is not a subtyp e of a previous
2765 // on-catch exception type
2644 TypeName typeName = catchClause.exceptionType; 2766 TypeName typeName = catchClause.exceptionType;
2645 if (typeName != null && typeName.type != null) { 2767 if (typeName != null && typeName.type != null) {
2646 Type2 currentType = typeName.type; 2768 Type2 currentType = typeName.type;
2647 if (currentType.isObject) { 2769 if (currentType.isObject) {
2770 // Found catch clause clause that has Object as an exception type, t his is equivalent to
2771 // having a catch clause that doesn't have an exception type, visit the block, but
2772 // generate an error on any following catch clauses (and don't visit them).
2648 safelyVisit(catchClause); 2773 safelyVisit(catchClause);
2649 if (i + 1 != numOfCatchClauses) { 2774 if (i + 1 != numOfCatchClauses) {
2775 // this catch clause is not the last in the try statement
2650 CatchClause nextCatchClause = catchClauses[i + 1]; 2776 CatchClause nextCatchClause = catchClauses[i + 1];
2651 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; 2777 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
2652 int offset = nextCatchClause.offset; 2778 int offset = nextCatchClause.offset;
2653 int length = lastCatchClause.end - offset; 2779 int length = lastCatchClause.end - offset;
2654 _errorReporter.reportError5(HintCode.DEAD_CODE_CATCH_FOLLOWING_CAT CH, offset, length, []); 2780 _errorReporter.reportError5(HintCode.DEAD_CODE_CATCH_FOLLOWING_CAT CH, offset, length, []);
2655 return null; 2781 return null;
2656 } 2782 }
2657 } 2783 }
2658 for (Type2 type in visitedTypes) { 2784 for (Type2 type in visitedTypes) {
2659 if (currentType.isSubtypeOf(type)) { 2785 if (currentType.isSubtypeOf(type)) {
2660 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; 2786 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
2661 int offset = catchClause.offset; 2787 int offset = catchClause.offset;
2662 int length = lastCatchClause.end - offset; 2788 int length = lastCatchClause.end - offset;
2663 _errorReporter.reportError5(HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, o ffset, length, [currentType.displayName, type.displayName]); 2789 _errorReporter.reportError5(HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, o ffset, length, [currentType.displayName, type.displayName]);
2664 return null; 2790 return null;
2665 } 2791 }
2666 } 2792 }
2667 visitedTypes.add(currentType); 2793 visitedTypes.add(currentType);
2668 } 2794 }
2669 safelyVisit(catchClause); 2795 safelyVisit(catchClause);
2670 } else { 2796 } else {
2797 // Found catch clause clause that doesn't have an exception type, visit the block, but
2798 // generate an error on any following catch clauses (and don't visit the m).
2671 safelyVisit(catchClause); 2799 safelyVisit(catchClause);
2672 if (i + 1 != numOfCatchClauses) { 2800 if (i + 1 != numOfCatchClauses) {
2801 // this catch clause is not the last in the try statement
2673 CatchClause nextCatchClause = catchClauses[i + 1]; 2802 CatchClause nextCatchClause = catchClauses[i + 1];
2674 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; 2803 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
2675 int offset = nextCatchClause.offset; 2804 int offset = nextCatchClause.offset;
2676 int length = lastCatchClause.end - offset; 2805 int length = lastCatchClause.end - offset;
2677 _errorReporter.reportError5(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length, []); 2806 _errorReporter.reportError5(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length, []);
2678 return null; 2807 return null;
2679 } 2808 }
2680 } 2809 }
2681 } 2810 }
2682 return null; 2811 return null;
2683 } 2812 }
2684 2813
2685 Object visitWhileStatement(WhileStatement node) { 2814 Object visitWhileStatement(WhileStatement node) {
2686 Expression conditionExpression = node.condition; 2815 Expression conditionExpression = node.condition;
2687 safelyVisit(conditionExpression); 2816 safelyVisit(conditionExpression);
2688 if (!isDebugConstant(conditionExpression)) { 2817 if (!isDebugConstant(conditionExpression)) {
2689 ValidResult result = getConstantBooleanValue(conditionExpression); 2818 ValidResult result = getConstantBooleanValue(conditionExpression);
2690 if (result != null) { 2819 if (result != null) {
2691 if (result.isFalse) { 2820 if (result.isFalse) {
2821 // report error on if block: while (false) {!}
2692 _errorReporter.reportError3(HintCode.DEAD_CODE, node.body, []); 2822 _errorReporter.reportError3(HintCode.DEAD_CODE, node.body, []);
2693 return null; 2823 return null;
2694 } 2824 }
2695 } 2825 }
2696 } 2826 }
2697 safelyVisit(node.body); 2827 safelyVisit(node.body);
2698 return null; 2828 return null;
2699 } 2829 }
2700 2830
2701 /** 2831 /**
2702 * Given some [Expression], this method returns [ValidResult#RESULT_TRUE] if i t is 2832 * Given some [Expression], this method returns [ValidResult#RESULT_TRUE] if i t is
2703 * `true`, [ValidResult#RESULT_FALSE] if it is `false`, or `null` if the 2833 * `true`, [ValidResult#RESULT_FALSE] if it is `false`, or `null` if the
2704 * expression is not a constant boolean value. 2834 * expression is not a constant boolean value.
2705 * 2835 *
2706 * @param expression the expression to evaluate 2836 * @param expression the expression to evaluate
2707 * @return [ValidResult#RESULT_TRUE] if it is `true`, [ValidResult#RESULT_FALS E] 2837 * @return [ValidResult#RESULT_TRUE] if it is `true`, [ValidResult#RESULT_FALS E]
2708 * if it is `false`, or `null` if the expression is not a constant boo lean 2838 * if it is `false`, or `null` if the expression is not a constant boo lean
2709 * value 2839 * value
2710 */ 2840 */
2711 ValidResult getConstantBooleanValue(Expression expression) { 2841 ValidResult getConstantBooleanValue(Expression expression) {
2712 if (expression is BooleanLiteral) { 2842 if (expression is BooleanLiteral) {
2713 if (expression.value) { 2843 if (expression.value) {
2714 return new ValidResult(new DartObjectImpl(null, BoolState.from(true))); 2844 return new ValidResult(new DartObjectImpl(null, BoolState.from(true)));
2715 } else { 2845 } else {
2716 return new ValidResult(new DartObjectImpl(null, BoolState.from(false))); 2846 return new ValidResult(new DartObjectImpl(null, BoolState.from(false)));
2717 } 2847 }
2718 } 2848 }
2849 // Don't consider situations where we could evaluate to a constant boolean e xpression with the
2850 // ConstantVisitor
2851 // else {
2852 // EvaluationResultImpl result = expression.accept(new ConstantVisitor( ));
2853 // if (result == ValidResult.RESULT_TRUE) {
2854 // return ValidResult.RESULT_TRUE;
2855 // } else if (result == ValidResult.RESULT_FALSE) {
2856 // return ValidResult.RESULT_FALSE;
2857 // }
2858 // return null;
2859 // }
2719 return null; 2860 return null;
2720 } 2861 }
2721 2862
2722 /** 2863 /**
2723 * Return `true` if and only if the passed expression is resolved to a constan t variable. 2864 * Return `true` if and only if the passed expression is resolved to a constan t variable.
2724 * 2865 *
2725 * @param expression some conditional expression 2866 * @param expression some conditional expression
2726 * @return `true` if and only if the passed expression is resolved to a consta nt variable 2867 * @return `true` if and only if the passed expression is resolved to a consta nt variable
2727 */ 2868 */
2728 bool isDebugConstant(Expression expression) { 2869 bool isDebugConstant(Expression expression) {
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
2800 _importsVerifier.generateDuplicateImportHints(definingCompilationUnitError Reporter); 2941 _importsVerifier.generateDuplicateImportHints(definingCompilationUnitError Reporter);
2801 _importsVerifier.generateUnusedImportHints(definingCompilationUnitErrorRep orter); 2942 _importsVerifier.generateUnusedImportHints(definingCompilationUnitErrorRep orter);
2802 } finally { 2943 } finally {
2803 timeCounter.stop(); 2944 timeCounter.stop();
2804 } 2945 }
2805 } 2946 }
2806 2947
2807 void generateForCompilationUnit(CompilationUnit unit, Source source) { 2948 void generateForCompilationUnit(CompilationUnit unit, Source source) {
2808 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); 2949 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source);
2809 _importsVerifier.visitCompilationUnit(unit); 2950 _importsVerifier.visitCompilationUnit(unit);
2951 // dead code analysis
2810 new DeadCodeVerifier(errorReporter).visitCompilationUnit(unit); 2952 new DeadCodeVerifier(errorReporter).visitCompilationUnit(unit);
2953 // dart2js analysis
2811 if (_enableDart2JSHints) { 2954 if (_enableDart2JSHints) {
2812 new Dart2JSVerifier(errorReporter).visitCompilationUnit(unit); 2955 new Dart2JSVerifier(errorReporter).visitCompilationUnit(unit);
2813 } 2956 }
2957 // Dart best practices
2814 new BestPracticesVerifier(errorReporter).visitCompilationUnit(unit); 2958 new BestPracticesVerifier(errorReporter).visitCompilationUnit(unit);
2959 // Find to-do comments
2815 new ToDoFinder(errorReporter).findIn(unit); 2960 new ToDoFinder(errorReporter).findIn(unit);
2816 } 2961 }
2817 } 2962 }
2818 2963
2819 /** 2964 /**
2820 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the 2965 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the
2821 * source code verifying that all of the imports are used, otherwise a 2966 * source code verifying that all of the imports are used, otherwise a
2822 * [HintCode#UNUSED_IMPORT] is generated with 2967 * [HintCode#UNUSED_IMPORT] is generated with
2823 * [generateUnusedImportHints]. 2968 * [generateUnusedImportHints].
2824 * 2969 *
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2916 /** 3061 /**
2917 * After all of the compilation units have been visited by this visitor, this method can be called 3062 * After all of the compilation units have been visited by this visitor, this method can be called
2918 * to report an [HintCode#UNUSED_IMPORT] hint for each of the import directive s in the 3063 * to report an [HintCode#UNUSED_IMPORT] hint for each of the import directive s in the
2919 * [unusedImports] list. 3064 * [unusedImports] list.
2920 * 3065 *
2921 * @param errorReporter the error reporter to report the set of [HintCode#UNUS ED_IMPORT] 3066 * @param errorReporter the error reporter to report the set of [HintCode#UNUS ED_IMPORT]
2922 * hints to 3067 * hints to
2923 */ 3068 */
2924 void generateUnusedImportHints(ErrorReporter errorReporter) { 3069 void generateUnusedImportHints(ErrorReporter errorReporter) {
2925 for (ImportDirective unusedImport in _unusedImports) { 3070 for (ImportDirective unusedImport in _unusedImports) {
3071 // Check that the import isn't dart:core
2926 ImportElement importElement = unusedImport.element; 3072 ImportElement importElement = unusedImport.element;
2927 if (importElement != null) { 3073 if (importElement != null) {
2928 LibraryElement libraryElement = importElement.importedLibrary; 3074 LibraryElement libraryElement = importElement.importedLibrary;
2929 if (libraryElement != null && libraryElement.isDartCore) { 3075 if (libraryElement != null && libraryElement.isDartCore) {
2930 continue; 3076 continue;
2931 } 3077 }
2932 } 3078 }
2933 errorReporter.reportError3(HintCode.UNUSED_IMPORT, unusedImport.uri, []); 3079 errorReporter.reportError3(HintCode.UNUSED_IMPORT, unusedImport.uri, []);
2934 } 3080 }
2935 } 3081 }
2936 3082
2937 Object visitCompilationUnit(CompilationUnit node) { 3083 Object visitCompilationUnit(CompilationUnit node) {
2938 if (_inDefiningCompilationUnit) { 3084 if (_inDefiningCompilationUnit) {
2939 NodeList<Directive> directives = node.directives; 3085 NodeList<Directive> directives = node.directives;
2940 for (Directive directive in directives) { 3086 for (Directive directive in directives) {
2941 if (directive is ImportDirective) { 3087 if (directive is ImportDirective) {
2942 ImportDirective importDirective = directive; 3088 ImportDirective importDirective = directive;
2943 LibraryElement libraryElement = importDirective.uriElement; 3089 LibraryElement libraryElement = importDirective.uriElement;
2944 if (libraryElement != null) { 3090 if (libraryElement != null) {
2945 _unusedImports.add(importDirective); 3091 _unusedImports.add(importDirective);
3092 //
3093 // Initialize prefixElementMap
3094 //
2946 if (importDirective.asToken != null) { 3095 if (importDirective.asToken != null) {
2947 SimpleIdentifier prefixIdentifier = importDirective.prefix; 3096 SimpleIdentifier prefixIdentifier = importDirective.prefix;
2948 if (prefixIdentifier != null) { 3097 if (prefixIdentifier != null) {
2949 Element element = prefixIdentifier.staticElement; 3098 Element element = prefixIdentifier.staticElement;
2950 if (element is PrefixElement) { 3099 if (element is PrefixElement) {
2951 PrefixElement prefixElementKey = element; 3100 PrefixElement prefixElementKey = element;
2952 _prefixElementMap[prefixElementKey] = importDirective; 3101 _prefixElementMap[prefixElementKey] = importDirective;
2953 } 3102 }
2954 } 3103 }
2955 } 3104 }
3105 //
3106 // Initialize libraryMap: libraryElement -> importDirective
3107 //
2956 putIntoLibraryMap(libraryElement, importDirective); 3108 putIntoLibraryMap(libraryElement, importDirective);
3109 //
3110 // For this new addition to the libraryMap, also recursively add any exports from the
3111 // libraryElement
3112 //
2957 addAdditionalLibrariesForExports(libraryElement, importDirective, ne w List<LibraryElement>()); 3113 addAdditionalLibrariesForExports(libraryElement, importDirective, ne w List<LibraryElement>());
2958 } 3114 }
2959 } 3115 }
2960 } 3116 }
2961 } 3117 }
3118 // If there are no imports in this library, don't visit the identifiers in t he library- there
3119 // can be no unused imports.
2962 if (_unusedImports.isEmpty) { 3120 if (_unusedImports.isEmpty) {
2963 return null; 3121 return null;
2964 } 3122 }
2965 if (_unusedImports.length > 1) { 3123 if (_unusedImports.length > 1) {
3124 // order the list of unusedImports to find duplicates in faster than O(n^2 ) time
2966 List<ImportDirective> importDirectiveArray = new List.from(_unusedImports) ; 3125 List<ImportDirective> importDirectiveArray = new List.from(_unusedImports) ;
2967 importDirectiveArray.sort(ImportDirective.COMPARATOR); 3126 importDirectiveArray.sort(ImportDirective.COMPARATOR);
2968 ImportDirective currentDirective = importDirectiveArray[0]; 3127 ImportDirective currentDirective = importDirectiveArray[0];
2969 for (int i = 1; i < importDirectiveArray.length; i++) { 3128 for (int i = 1; i < importDirectiveArray.length; i++) {
2970 ImportDirective nextDirective = importDirectiveArray[i]; 3129 ImportDirective nextDirective = importDirectiveArray[i];
2971 if (ImportDirective.COMPARATOR(currentDirective, nextDirective) == 0) { 3130 if (ImportDirective.COMPARATOR(currentDirective, nextDirective) == 0) {
3131 // Add either the currentDirective or nextDirective depending on which comes second, this
3132 // guarantees that the first of the duplicates won't be highlighted.
2972 if (currentDirective.offset < nextDirective.offset) { 3133 if (currentDirective.offset < nextDirective.offset) {
2973 _duplicateImports.add(nextDirective); 3134 _duplicateImports.add(nextDirective);
2974 } else { 3135 } else {
2975 _duplicateImports.add(currentDirective); 3136 _duplicateImports.add(currentDirective);
2976 } 3137 }
2977 } 3138 }
2978 currentDirective = nextDirective; 3139 currentDirective = nextDirective;
2979 } 3140 }
2980 } 3141 }
2981 return super.visitCompilationUnit(node); 3142 return super.visitCompilationUnit(node);
2982 } 3143 }
2983 3144
2984 Object visitExportDirective(ExportDirective node) { 3145 Object visitExportDirective(ExportDirective node) {
2985 visitMetadata(node.metadata); 3146 visitMetadata(node.metadata);
2986 return null; 3147 return null;
2987 } 3148 }
2988 3149
2989 Object visitImportDirective(ImportDirective node) { 3150 Object visitImportDirective(ImportDirective node) {
2990 visitMetadata(node.metadata); 3151 visitMetadata(node.metadata);
2991 return null; 3152 return null;
2992 } 3153 }
2993 3154
2994 Object visitLibraryDirective(LibraryDirective node) { 3155 Object visitLibraryDirective(LibraryDirective node) {
2995 visitMetadata(node.metadata); 3156 visitMetadata(node.metadata);
2996 return null; 3157 return null;
2997 } 3158 }
2998 3159
2999 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 3160 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
3161 // If the prefixed identifier references some A.B, where A is a library pref ix, then we can
3162 // lookup the associated ImportDirective in prefixElementMap and remove it f rom the
3163 // unusedImports list.
3000 SimpleIdentifier prefixIdentifier = node.prefix; 3164 SimpleIdentifier prefixIdentifier = node.prefix;
3001 Element element = prefixIdentifier.staticElement; 3165 Element element = prefixIdentifier.staticElement;
3002 if (element is PrefixElement) { 3166 if (element is PrefixElement) {
3003 _unusedImports.remove(_prefixElementMap[element]); 3167 _unusedImports.remove(_prefixElementMap[element]);
3004 return null; 3168 return null;
3005 } 3169 }
3170 // Otherwise, pass the prefixed identifier element and name onto visitIdenti fier.
3006 return visitIdentifier(element, prefixIdentifier.name); 3171 return visitIdentifier(element, prefixIdentifier.name);
3007 } 3172 }
3008 3173
3009 Object visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node.st aticElement, node.name); 3174 Object visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node.st aticElement, node.name);
3010 3175
3011 void set inDefiningCompilationUnit(bool inDefiningCompilationUnit) { 3176 void set inDefiningCompilationUnit(bool inDefiningCompilationUnit) {
3012 this._inDefiningCompilationUnit = inDefiningCompilationUnit; 3177 this._inDefiningCompilationUnit = inDefiningCompilationUnit;
3013 } 3178 }
3014 3179
3015 /** 3180 /**
(...skipping 14 matching lines...) Expand all
3030 * Lookup and return the [Namespace] from the [namespaceMap], if the map does not 3195 * Lookup and return the [Namespace] from the [namespaceMap], if the map does not
3031 * have the computed namespace, compute it and cache it in the map. If the imp ort directive is not 3196 * have the computed namespace, compute it and cache it in the map. If the imp ort directive is not
3032 * resolved or is not resolvable, `null` is returned. 3197 * resolved or is not resolvable, `null` is returned.
3033 * 3198 *
3034 * @param importDirective the import directive used to compute the returned na mespace 3199 * @param importDirective the import directive used to compute the returned na mespace
3035 * @return the computed or looked up [Namespace] 3200 * @return the computed or looked up [Namespace]
3036 */ 3201 */
3037 Namespace computeNamespace(ImportDirective importDirective) { 3202 Namespace computeNamespace(ImportDirective importDirective) {
3038 Namespace namespace = _namespaceMap[importDirective]; 3203 Namespace namespace = _namespaceMap[importDirective];
3039 if (namespace == null) { 3204 if (namespace == null) {
3205 // If the namespace isn't in the namespaceMap, then compute and put it in the map
3040 ImportElement importElement = importDirective.element; 3206 ImportElement importElement = importDirective.element;
3041 if (importElement != null) { 3207 if (importElement != null) {
3042 NamespaceBuilder builder = new NamespaceBuilder(); 3208 NamespaceBuilder builder = new NamespaceBuilder();
3043 namespace = builder.createImportNamespace(importElement); 3209 namespace = builder.createImportNamespace(importElement);
3044 _namespaceMap[importDirective] = namespace; 3210 _namespaceMap[importDirective] = namespace;
3045 } 3211 }
3046 } 3212 }
3047 return namespace; 3213 return namespace;
3048 } 3214 }
3049 3215
3050 /** 3216 /**
3051 * The [libraryMap] is a mapping between a library elements and a list of impo rt 3217 * The [libraryMap] is a mapping between a library elements and a list of impo rt
3052 * directives, but when adding these mappings into the [libraryMap], this meth od can be 3218 * directives, but when adding these mappings into the [libraryMap], this meth od can be
3053 * used to simply add the mapping between the library element an an import dir ective without 3219 * used to simply add the mapping between the library element an an import dir ective without
3054 * needing to check to see if a list needs to be created. 3220 * needing to check to see if a list needs to be created.
3055 */ 3221 */
3056 void putIntoLibraryMap(LibraryElement libraryElement, ImportDirective importDi rective) { 3222 void putIntoLibraryMap(LibraryElement libraryElement, ImportDirective importDi rective) {
3057 List<ImportDirective> importList = _libraryMap[libraryElement]; 3223 List<ImportDirective> importList = _libraryMap[libraryElement];
3058 if (importList == null) { 3224 if (importList == null) {
3059 importList = new List<ImportDirective>(); 3225 importList = new List<ImportDirective>();
3060 _libraryMap[libraryElement] = importList; 3226 _libraryMap[libraryElement] = importList;
3061 } 3227 }
3062 importList.add(importDirective); 3228 importList.add(importDirective);
3063 } 3229 }
3064 3230
3065 Object visitIdentifier(Element element, String name) { 3231 Object visitIdentifier(Element element, String name) {
3066 if (element == null) { 3232 if (element == null) {
3067 return null; 3233 return null;
3068 } 3234 }
3235 // If the element is multiply defined then call this method recursively for each of the conflicting elements.
3069 if (element is MultiplyDefinedElement) { 3236 if (element is MultiplyDefinedElement) {
3070 MultiplyDefinedElement multiplyDefinedElement = element; 3237 MultiplyDefinedElement multiplyDefinedElement = element;
3071 for (Element elt in multiplyDefinedElement.conflictingElements) { 3238 for (Element elt in multiplyDefinedElement.conflictingElements) {
3072 visitIdentifier(elt, name); 3239 visitIdentifier(elt, name);
3073 } 3240 }
3074 return null; 3241 return null;
3075 } else if (element is PrefixElement) { 3242 } else if (element is PrefixElement) {
3076 _unusedImports.remove(_prefixElementMap[element]); 3243 _unusedImports.remove(_prefixElementMap[element]);
3077 return null; 3244 return null;
3078 } 3245 }
3079 LibraryElement containingLibrary = element.library; 3246 LibraryElement containingLibrary = element.library;
3080 if (containingLibrary == null) { 3247 if (containingLibrary == null) {
3081 return null; 3248 return null;
3082 } 3249 }
3250 // If the element is declared in the current library, return.
3083 if (_currentLibrary == containingLibrary) { 3251 if (_currentLibrary == containingLibrary) {
3084 return null; 3252 return null;
3085 } 3253 }
3086 List<ImportDirective> importsFromSameLibrary = _libraryMap[containingLibrary ]; 3254 List<ImportDirective> importsFromSameLibrary = _libraryMap[containingLibrary ];
3087 if (importsFromSameLibrary == null) { 3255 if (importsFromSameLibrary == null) {
3088 return null; 3256 return null;
3089 } 3257 }
3090 if (importsFromSameLibrary.length == 1) { 3258 if (importsFromSameLibrary.length == 1) {
3259 // If there is only one import directive for this library, then it must be the directive that
3260 // this element is imported with, remove it from the unusedImports list.
3091 ImportDirective usedImportDirective = importsFromSameLibrary[0]; 3261 ImportDirective usedImportDirective = importsFromSameLibrary[0];
3092 _unusedImports.remove(usedImportDirective); 3262 _unusedImports.remove(usedImportDirective);
3093 } else { 3263 } else {
3264 // Otherwise, for each of the imported directives, use the namespaceMap to
3094 for (ImportDirective importDirective in importsFromSameLibrary) { 3265 for (ImportDirective importDirective in importsFromSameLibrary) {
3266 // Get the namespace for this import
3095 Namespace namespace = computeNamespace(importDirective); 3267 Namespace namespace = computeNamespace(importDirective);
3096 if (namespace != null && namespace.get(name) != null) { 3268 if (namespace != null && namespace.get(name) != null) {
3097 _unusedImports.remove(importDirective); 3269 _unusedImports.remove(importDirective);
3098 } 3270 }
3099 } 3271 }
3100 } 3272 }
3101 return null; 3273 return null;
3102 } 3274 }
3103 3275
3104 /** 3276 /**
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3156 Source source = getSource(uriLiteral); 3328 Source source = getSource(uriLiteral);
3157 String fullName = getSourceFullName(source); 3329 String fullName = getSourceFullName(source);
3158 if (fullName != null) { 3330 if (fullName != null) {
3159 int pathIndex = 0; 3331 int pathIndex = 0;
3160 int fullNameIndex = fullName.length; 3332 int fullNameIndex = fullName.length;
3161 while (pathIndex < path.length && JavaString.startsWithBefore(path, "../", pathIndex)) { 3333 while (pathIndex < path.length && JavaString.startsWithBefore(path, "../", pathIndex)) {
3162 fullNameIndex = JavaString.lastIndexOf(fullName, '/', fullNameIndex); 3334 fullNameIndex = JavaString.lastIndexOf(fullName, '/', fullNameIndex);
3163 if (fullNameIndex < 4) { 3335 if (fullNameIndex < 4) {
3164 return false; 3336 return false;
3165 } 3337 }
3338 // Check for "/lib" at a specified place in the fullName
3166 if (JavaString.startsWithBefore(fullName, "/lib", fullNameIndex - 4)) { 3339 if (JavaString.startsWithBefore(fullName, "/lib", fullNameIndex - 4)) {
3167 String relativePubspecPath = path.substring(0, pathIndex + 3) + _PUBSP EC_YAML; 3340 String relativePubspecPath = path.substring(0, pathIndex + 3) + _PUBSP EC_YAML;
3168 Source pubspecSource = _context.sourceFactory.resolveUri(source, relat ivePubspecPath); 3341 Source pubspecSource = _context.sourceFactory.resolveUri(source, relat ivePubspecPath);
3169 if (pubspecSource != null && pubspecSource.exists()) { 3342 if (pubspecSource != null && pubspecSource.exists()) {
3343 // Files inside the lib directory hierarchy should not reference fil es outside
3170 _errorReporter.reportError3(PubSuggestionCode.FILE_IMPORT_INSIDE_LIB _REFERENCES_FILE_OUTSIDE, uriLiteral, []); 3344 _errorReporter.reportError3(PubSuggestionCode.FILE_IMPORT_INSIDE_LIB _REFERENCES_FILE_OUTSIDE, uriLiteral, []);
3171 } 3345 }
3172 return true; 3346 return true;
3173 } 3347 }
3174 pathIndex += 3; 3348 pathIndex += 3;
3175 } 3349 }
3176 } 3350 }
3177 return false; 3351 return false;
3178 } 3352 }
3179 3353
(...skipping 26 matching lines...) Expand all
3206 bool checkForFileImportOutsideLibReferencesFileInside2(StringLiteral uriLitera l, String path, int pathIndex) { 3380 bool checkForFileImportOutsideLibReferencesFileInside2(StringLiteral uriLitera l, String path, int pathIndex) {
3207 Source source = getSource(uriLiteral); 3381 Source source = getSource(uriLiteral);
3208 String relativePubspecPath = path.substring(0, pathIndex) + _PUBSPEC_YAML; 3382 String relativePubspecPath = path.substring(0, pathIndex) + _PUBSPEC_YAML;
3209 Source pubspecSource = _context.sourceFactory.resolveUri(source, relativePub specPath); 3383 Source pubspecSource = _context.sourceFactory.resolveUri(source, relativePub specPath);
3210 if (pubspecSource == null || !pubspecSource.exists()) { 3384 if (pubspecSource == null || !pubspecSource.exists()) {
3211 return false; 3385 return false;
3212 } 3386 }
3213 String fullName = getSourceFullName(source); 3387 String fullName = getSourceFullName(source);
3214 if (fullName != null) { 3388 if (fullName != null) {
3215 if (!fullName.contains("/lib/")) { 3389 if (!fullName.contains("/lib/")) {
3390 // Files outside the lib directory hierarchy should not reference files inside
3391 // ... use package: url instead
3216 _errorReporter.reportError3(PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_RE FERENCES_FILE_INSIDE, uriLiteral, []); 3392 _errorReporter.reportError3(PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_RE FERENCES_FILE_INSIDE, uriLiteral, []);
3217 return true; 3393 return true;
3218 } 3394 }
3219 } 3395 }
3220 return false; 3396 return false;
3221 } 3397 }
3222 3398
3223 /** 3399 /**
3224 * This verifies that the passed package import directive does not contain ".. " 3400 * This verifies that the passed package import directive does not contain ".. "
3225 * 3401 *
3226 * @param uriLiteral the import URL (not `null`) 3402 * @param uriLiteral the import URL (not `null`)
3227 * @param path the path to be validated (not `null`) 3403 * @param path the path to be validated (not `null`)
3228 * @return `true` if and only if an error code is generated on the passed node 3404 * @return `true` if and only if an error code is generated on the passed node
3229 * @see PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT 3405 * @see PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
3230 */ 3406 */
3231 bool checkForPackageImportContainsDotDot(StringLiteral uriLiteral, String path ) { 3407 bool checkForPackageImportContainsDotDot(StringLiteral uriLiteral, String path ) {
3232 if (path.startsWith("../") || path.contains("/../")) { 3408 if (path.startsWith("../") || path.contains("/../")) {
3409 // Package import should not to contain ".."
3233 _errorReporter.reportError3(PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_ DOT, uriLiteral, []); 3410 _errorReporter.reportError3(PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_ DOT, uriLiteral, []);
3234 return true; 3411 return true;
3235 } 3412 }
3236 return false; 3413 return false;
3237 } 3414 }
3238 3415
3239 /** 3416 /**
3240 * Answer the source associated with the compilation unit containing the given AST node. 3417 * Answer the source associated with the compilation unit containing the given AST node.
3241 * 3418 *
3242 * @param node the node (not `null`) 3419 * @param node the node (not `null`)
(...skipping 1461 matching lines...) Expand 10 before | Expand all | Expand 10 after
4704 if (leftHandSide != null) { 4881 if (leftHandSide != null) {
4705 String methodName = operatorType.lexeme; 4882 String methodName = operatorType.lexeme;
4706 Type2 staticType = getStaticType(leftHandSide); 4883 Type2 staticType = getStaticType(leftHandSide);
4707 MethodElement staticMethod = lookUpMethod(leftHandSide, staticType, meth odName); 4884 MethodElement staticMethod = lookUpMethod(leftHandSide, staticType, meth odName);
4708 node.staticElement = staticMethod; 4885 node.staticElement = staticMethod;
4709 Type2 propagatedType = getPropagatedType(leftHandSide); 4886 Type2 propagatedType = getPropagatedType(leftHandSide);
4710 MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedTy pe, methodName); 4887 MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedTy pe, methodName);
4711 node.propagatedElement = propagatedMethod; 4888 node.propagatedElement = propagatedMethod;
4712 bool shouldReportMissingMember_static = shouldReportMissingMember(static Type, staticMethod); 4889 bool shouldReportMissingMember_static = shouldReportMissingMember(static Type, staticMethod);
4713 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_s tatic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMeth od) : false; 4890 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_s tatic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMeth od) : false;
4891 //
4892 // If we are about to generate the hint (propagated version of this warn ing), then check
4893 // that the member is not in a subtype of the propagated type.
4894 //
4714 if (shouldReportMissingMember_propagated) { 4895 if (shouldReportMissingMember_propagated) {
4715 if (memberFoundInSubclass(propagatedType.element, methodName, true, fa lse)) { 4896 if (memberFoundInSubclass(propagatedType.element, methodName, true, fa lse)) {
4716 shouldReportMissingMember_propagated = false; 4897 shouldReportMissingMember_propagated = false;
4717 } 4898 }
4718 } 4899 }
4719 if (shouldReportMissingMember_static || shouldReportMissingMember_propag ated) { 4900 if (shouldReportMissingMember_static || shouldReportMissingMember_propag ated) {
4720 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_METHOD : HintCode.UNDEFINED_METHOD) as ErrorCode; 4901 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_METHOD : HintCode.UNDEFINED_METHOD) as ErrorCode;
4721 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissin gMember_static ? staticType.element : propagatedType.element, errorCode, operato r, [ 4902 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissin gMember_static ? staticType.element : propagatedType.element, errorCode, operato r, [
4722 methodName, 4903 methodName,
4723 shouldReportMissingMember_static ? staticType.displayName : propag atedType.displayName]); 4904 shouldReportMissingMember_static ? staticType.displayName : propag atedType.displayName]);
(...skipping 10 matching lines...) Expand all
4734 if (leftOperand != null) { 4915 if (leftOperand != null) {
4735 String methodName = operator.lexeme; 4916 String methodName = operator.lexeme;
4736 Type2 staticType = getStaticType(leftOperand); 4917 Type2 staticType = getStaticType(leftOperand);
4737 MethodElement staticMethod = lookUpMethod(leftOperand, staticType, metho dName); 4918 MethodElement staticMethod = lookUpMethod(leftOperand, staticType, metho dName);
4738 node.staticElement = staticMethod; 4919 node.staticElement = staticMethod;
4739 Type2 propagatedType = getPropagatedType(leftOperand); 4920 Type2 propagatedType = getPropagatedType(leftOperand);
4740 MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedTyp e, methodName); 4921 MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedTyp e, methodName);
4741 node.propagatedElement = propagatedMethod; 4922 node.propagatedElement = propagatedMethod;
4742 bool shouldReportMissingMember_static = shouldReportMissingMember(static Type, staticMethod); 4923 bool shouldReportMissingMember_static = shouldReportMissingMember(static Type, staticMethod);
4743 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_s tatic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMeth od) : false; 4924 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_s tatic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMeth od) : false;
4925 //
4926 // If we are about to generate the hint (propagated version of this warn ing), then check
4927 // that the member is not in a subtype of the propagated type.
4928 //
4744 if (shouldReportMissingMember_propagated) { 4929 if (shouldReportMissingMember_propagated) {
4745 if (memberFoundInSubclass(propagatedType.element, methodName, true, fa lse)) { 4930 if (memberFoundInSubclass(propagatedType.element, methodName, true, fa lse)) {
4746 shouldReportMissingMember_propagated = false; 4931 shouldReportMissingMember_propagated = false;
4747 } 4932 }
4748 } 4933 }
4749 if (shouldReportMissingMember_static || shouldReportMissingMember_propag ated) { 4934 if (shouldReportMissingMember_static || shouldReportMissingMember_propag ated) {
4750 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode; 4935 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
4751 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissin gMember_static ? staticType.element : propagatedType.element, errorCode, operato r, [ 4936 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissin gMember_static ? staticType.element : propagatedType.element, errorCode, operato r, [
4752 methodName, 4937 methodName,
4753 shouldReportMissingMember_static ? staticType.displayName : propag atedType.displayName]); 4938 shouldReportMissingMember_static ? staticType.displayName : propag atedType.displayName]);
(...skipping 21 matching lines...) Expand all
4775 setMetadata(node.element, node); 4960 setMetadata(node.element, node);
4776 return null; 4961 return null;
4777 } 4962 }
4778 4963
4779 Object visitCommentReference(CommentReference node) { 4964 Object visitCommentReference(CommentReference node) {
4780 Identifier identifier = node.identifier; 4965 Identifier identifier = node.identifier;
4781 if (identifier is SimpleIdentifier) { 4966 if (identifier is SimpleIdentifier) {
4782 SimpleIdentifier simpleIdentifier = identifier; 4967 SimpleIdentifier simpleIdentifier = identifier;
4783 Element element = resolveSimpleIdentifier(simpleIdentifier); 4968 Element element = resolveSimpleIdentifier(simpleIdentifier);
4784 if (element == null) { 4969 if (element == null) {
4970 //
4971 // This might be a reference to an imported name that is missing the pre fix.
4972 //
4785 element = findImportWithoutPrefix(simpleIdentifier); 4973 element = findImportWithoutPrefix(simpleIdentifier);
4786 if (element is MultiplyDefinedElement) { 4974 if (element is MultiplyDefinedElement) {
4975 // TODO(brianwilkerson) Report this error?
4787 element = null; 4976 element = null;
4788 } 4977 }
4789 } 4978 }
4790 if (element == null) { 4979 if (element == null) {
4791 } else { 4980 } else {
4792 if (element.library == null || element.library != _definingLibrary) { 4981 if (element.library == null || element.library != _definingLibrary) {
4793 } 4982 }
4794 simpleIdentifier.staticElement = element; 4983 simpleIdentifier.staticElement = element;
4795 if (node.newKeyword != null) { 4984 if (node.newKeyword != null) {
4796 if (element is ClassElement) { 4985 if (element is ClassElement) {
4797 ConstructorElement constructor = (element as ClassElement).unnamedCo nstructor; 4986 ConstructorElement constructor = (element as ClassElement).unnamedCo nstructor;
4798 if (constructor == null) { 4987 if (constructor == null) {
4799 } else { 4988 } else {
4800 simpleIdentifier.staticElement = constructor; 4989 simpleIdentifier.staticElement = constructor;
4801 } 4990 }
4802 } else { 4991 } else {
4803 } 4992 }
4804 } 4993 }
4805 } 4994 }
4806 } else if (identifier is PrefixedIdentifier) { 4995 } else if (identifier is PrefixedIdentifier) {
4807 PrefixedIdentifier prefixedIdentifier = identifier; 4996 PrefixedIdentifier prefixedIdentifier = identifier;
4808 SimpleIdentifier prefix = prefixedIdentifier.prefix; 4997 SimpleIdentifier prefix = prefixedIdentifier.prefix;
4809 SimpleIdentifier name = prefixedIdentifier.identifier; 4998 SimpleIdentifier name = prefixedIdentifier.identifier;
4810 Element element = resolveSimpleIdentifier(prefix); 4999 Element element = resolveSimpleIdentifier(prefix);
4811 if (element == null) { 5000 if (element == null) {
4812 } else { 5001 } else {
4813 if (element is PrefixElement) { 5002 if (element is PrefixElement) {
4814 prefix.staticElement = element; 5003 prefix.staticElement = element;
5004 // TODO(brianwilkerson) Report this error?
4815 element = _resolver.nameScope.lookup(identifier, _definingLibrary); 5005 element = _resolver.nameScope.lookup(identifier, _definingLibrary);
4816 name.staticElement = element; 5006 name.staticElement = element;
4817 return null; 5007 return null;
4818 } 5008 }
4819 LibraryElement library = element.library; 5009 LibraryElement library = element.library;
4820 if (library == null) { 5010 if (library == null) {
5011 // TODO(brianwilkerson) We need to understand how the library could ev er be null.
4821 AnalysisEngine.instance.logger.logError("Found element with null libra ry: ${element.name}"); 5012 AnalysisEngine.instance.logger.logError("Found element with null libra ry: ${element.name}");
4822 } else if (library != _definingLibrary) { 5013 } else if (library != _definingLibrary) {
4823 } 5014 }
4824 name.staticElement = element; 5015 name.staticElement = element;
4825 if (node.newKeyword == null) { 5016 if (node.newKeyword == null) {
4826 if (element is ClassElement) { 5017 if (element is ClassElement) {
4827 Element memberElement = lookupGetterOrMethod((element as ClassElemen t).type, name.name); 5018 Element memberElement = lookupGetterOrMethod((element as ClassElemen t).type, name.name);
4828 if (memberElement == null) { 5019 if (memberElement == null) {
4829 memberElement = (element as ClassElement).getNamedConstructor(name .name); 5020 memberElement = (element as ClassElement).getNamedConstructor(name .name);
4830 if (memberElement == null) { 5021 if (memberElement == null) {
(...skipping 19 matching lines...) Expand all
4850 } 5041 }
4851 } 5042 }
4852 return null; 5043 return null;
4853 } 5044 }
4854 5045
4855 Object visitConstructorDeclaration(ConstructorDeclaration node) { 5046 Object visitConstructorDeclaration(ConstructorDeclaration node) {
4856 super.visitConstructorDeclaration(node); 5047 super.visitConstructorDeclaration(node);
4857 ConstructorElement element = node.element; 5048 ConstructorElement element = node.element;
4858 if (element is ConstructorElementImpl) { 5049 if (element is ConstructorElementImpl) {
4859 ConstructorElementImpl constructorElement = element; 5050 ConstructorElementImpl constructorElement = element;
5051 // set redirected factory constructor
4860 ConstructorName redirectedNode = node.redirectedConstructor; 5052 ConstructorName redirectedNode = node.redirectedConstructor;
4861 if (redirectedNode != null) { 5053 if (redirectedNode != null) {
4862 ConstructorElement redirectedElement = redirectedNode.staticElement; 5054 ConstructorElement redirectedElement = redirectedNode.staticElement;
4863 constructorElement.redirectedConstructor = redirectedElement; 5055 constructorElement.redirectedConstructor = redirectedElement;
4864 } 5056 }
5057 // set redirected generate constructor
4865 for (ConstructorInitializer initializer in node.initializers) { 5058 for (ConstructorInitializer initializer in node.initializers) {
4866 if (initializer is RedirectingConstructorInvocation) { 5059 if (initializer is RedirectingConstructorInvocation) {
4867 ConstructorElement redirectedElement = initializer.staticElement; 5060 ConstructorElement redirectedElement = initializer.staticElement;
4868 constructorElement.redirectedConstructor = redirectedElement; 5061 constructorElement.redirectedConstructor = redirectedElement;
4869 } 5062 }
4870 } 5063 }
4871 setMetadata(constructorElement, node); 5064 setMetadata(constructorElement, node);
4872 } 5065 }
4873 return null; 5066 return null;
4874 } 5067 }
4875 5068
4876 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { 5069 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
4877 SimpleIdentifier fieldName = node.fieldName; 5070 SimpleIdentifier fieldName = node.fieldName;
4878 ClassElement enclosingClass = _resolver.enclosingClass; 5071 ClassElement enclosingClass = _resolver.enclosingClass;
4879 FieldElement fieldElement = enclosingClass.getField(fieldName.name); 5072 FieldElement fieldElement = enclosingClass.getField(fieldName.name);
4880 fieldName.staticElement = fieldElement; 5073 fieldName.staticElement = fieldElement;
4881 if (fieldElement == null || fieldElement.isSynthetic) { 5074 if (fieldElement == null || fieldElement.isSynthetic) {
4882 _resolver.reportError7(CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTANT_F IELD, node, [fieldName]); 5075 _resolver.reportError7(CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTANT_F IELD, node, [fieldName]);
4883 } else if (fieldElement.isStatic) { 5076 } else if (fieldElement.isStatic) {
4884 _resolver.reportError7(CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, node, [fieldName]); 5077 _resolver.reportError7(CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, node, [fieldName]);
4885 } 5078 }
4886 return null; 5079 return null;
4887 } 5080 }
4888 5081
4889 Object visitConstructorName(ConstructorName node) { 5082 Object visitConstructorName(ConstructorName node) {
4890 Type2 type = node.type.type; 5083 Type2 type = node.type.type;
4891 if (type != null && type.isDynamic) { 5084 if (type != null && type.isDynamic) {
4892 return null; 5085 return null;
4893 } else if (type is! InterfaceType) { 5086 } else if (type is! InterfaceType) {
5087 // TODO(brianwilkerson) Report these errors.
4894 ASTNode parent = node.parent; 5088 ASTNode parent = node.parent;
4895 if (parent is InstanceCreationExpression) { 5089 if (parent is InstanceCreationExpression) {
4896 if (parent.isConst) { 5090 if (parent.isConst) {
4897 } else { 5091 } else {
4898 } 5092 }
4899 } else { 5093 } else {
4900 } 5094 }
4901 return null; 5095 return null;
4902 } 5096 }
5097 // look up ConstructorElement
4903 ConstructorElement constructor; 5098 ConstructorElement constructor;
4904 SimpleIdentifier name = node.name; 5099 SimpleIdentifier name = node.name;
4905 InterfaceType interfaceType = type as InterfaceType; 5100 InterfaceType interfaceType = type as InterfaceType;
4906 if (name == null) { 5101 if (name == null) {
4907 constructor = interfaceType.lookUpConstructor(null, _definingLibrary); 5102 constructor = interfaceType.lookUpConstructor(null, _definingLibrary);
4908 } else { 5103 } else {
4909 constructor = interfaceType.lookUpConstructor(name.name, _definingLibrary) ; 5104 constructor = interfaceType.lookUpConstructor(name.name, _definingLibrary) ;
4910 name.staticElement = constructor; 5105 name.staticElement = constructor;
4911 } 5106 }
4912 node.staticElement = constructor; 5107 node.staticElement = constructor;
(...skipping 10 matching lines...) Expand all
4923 } 5118 }
4924 5119
4925 Object visitDeclaredIdentifier(DeclaredIdentifier node) { 5120 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
4926 setMetadata(node.element, node); 5121 setMetadata(node.element, node);
4927 return null; 5122 return null;
4928 } 5123 }
4929 5124
4930 Object visitExportDirective(ExportDirective node) { 5125 Object visitExportDirective(ExportDirective node) {
4931 Element element = node.element; 5126 Element element = node.element;
4932 if (element is ExportElement) { 5127 if (element is ExportElement) {
5128 // The element is null when the URI is invalid
5129 // TODO(brianwilkerson) Figure out whether the element can ever be somethi ng other than an
5130 // ExportElement
4933 resolveCombinators(element.exportedLibrary, node.combinators); 5131 resolveCombinators(element.exportedLibrary, node.combinators);
4934 setMetadata(element, node); 5132 setMetadata(element, node);
4935 } 5133 }
4936 return null; 5134 return null;
4937 } 5135 }
4938 5136
4939 Object visitFieldFormalParameter(FieldFormalParameter node) { 5137 Object visitFieldFormalParameter(FieldFormalParameter node) {
4940 String fieldName = node.identifier.name; 5138 String fieldName = node.identifier.name;
4941 ClassElement classElement = _resolver.enclosingClass; 5139 ClassElement classElement = _resolver.enclosingClass;
4942 if (classElement != null) { 5140 if (classElement != null) {
4943 FieldElement fieldElement = classElement.getField(fieldName); 5141 FieldElement fieldElement = classElement.getField(fieldName);
4944 if (fieldElement == null) { 5142 if (fieldElement == null) {
4945 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_ EXISTANT_FIELD, node, [fieldName]); 5143 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_ EXISTANT_FIELD, node, [fieldName]);
4946 } else { 5144 } else {
4947 ParameterElement parameterElement = node.element; 5145 ParameterElement parameterElement = node.element;
4948 if (parameterElement is FieldFormalParameterElementImpl) { 5146 if (parameterElement is FieldFormalParameterElementImpl) {
4949 FieldFormalParameterElementImpl fieldFormal = parameterElement; 5147 FieldFormalParameterElementImpl fieldFormal = parameterElement;
4950 fieldFormal.field = fieldElement; 5148 fieldFormal.field = fieldElement;
4951 Type2 declaredType = fieldFormal.type; 5149 Type2 declaredType = fieldFormal.type;
4952 Type2 fieldType = fieldElement.type; 5150 Type2 fieldType = fieldElement.type;
4953 if (node.type == null) { 5151 if (node.type == null) {
4954 fieldFormal.type = fieldType; 5152 fieldFormal.type = fieldType;
4955 } 5153 }
4956 if (fieldElement.isSynthetic) { 5154 if (fieldElement.isSynthetic) {
4957 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ NON_EXISTANT_FIELD, node, [fieldName]); 5155 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ NON_EXISTANT_FIELD, node, [fieldName]);
4958 } else if (fieldElement.isStatic) { 5156 } else if (fieldElement.isStatic) {
4959 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ STATIC_FIELD, node, [fieldName]); 5157 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ STATIC_FIELD, node, [fieldName]);
4960 } else if (declaredType != null && fieldType != null && !declaredType. isAssignableTo(fieldType)) { 5158 } else if (declaredType != null && fieldType != null && !declaredType. isAssignableTo(fieldType)) {
5159 // TODO(brianwilkerson) We should implement a displayName() method f or types that will
5160 // work nicely with function types and then use that below.
4961 _resolver.reportError7(StaticWarningCode.FIELD_INITIALIZING_FORMAL_N OT_ASSIGNABLE, node, [declaredType.displayName, fieldType.displayName]); 5161 _resolver.reportError7(StaticWarningCode.FIELD_INITIALIZING_FORMAL_N OT_ASSIGNABLE, node, [declaredType.displayName, fieldType.displayName]);
4962 } 5162 }
4963 } else { 5163 } else {
4964 if (fieldElement.isSynthetic) { 5164 if (fieldElement.isSynthetic) {
4965 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ NON_EXISTANT_FIELD, node, [fieldName]); 5165 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ NON_EXISTANT_FIELD, node, [fieldName]);
4966 } else if (fieldElement.isStatic) { 5166 } else if (fieldElement.isStatic) {
4967 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ STATIC_FIELD, node, [fieldName]); 5167 _resolver.reportError7(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ STATIC_FIELD, node, [fieldName]);
4968 } 5168 }
4969 } 5169 }
4970 } 5170 }
4971 } 5171 }
5172 // else {
5173 // // TODO(jwren) Report error, constructor initializer variable is a top level element
5174 // // (Either here or in ErrorVerifier#checkForAllFinalInitializedErrorCo des)
5175 // }
4972 return super.visitFieldFormalParameter(node); 5176 return super.visitFieldFormalParameter(node);
4973 } 5177 }
4974 5178
4975 Object visitFunctionDeclaration(FunctionDeclaration node) { 5179 Object visitFunctionDeclaration(FunctionDeclaration node) {
4976 setMetadata(node.element, node); 5180 setMetadata(node.element, node);
4977 return null; 5181 return null;
4978 } 5182 }
4979 5183
4980 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 5184 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
5185 // TODO(brianwilkerson) Can we ever resolve the function being invoked?
4981 Expression expression = node.function; 5186 Expression expression = node.function;
4982 if (expression is FunctionExpression) { 5187 if (expression is FunctionExpression) {
4983 FunctionExpression functionExpression = expression; 5188 FunctionExpression functionExpression = expression;
4984 ExecutableElement functionElement = functionExpression.element; 5189 ExecutableElement functionElement = functionExpression.element;
4985 ArgumentList argumentList = node.argumentList; 5190 ArgumentList argumentList = node.argumentList;
4986 List<ParameterElement> parameters = resolveArgumentsToParameters(false, ar gumentList, functionElement); 5191 List<ParameterElement> parameters = resolveArgumentsToParameters(false, ar gumentList, functionElement);
4987 if (parameters != null) { 5192 if (parameters != null) {
4988 argumentList.correspondingStaticParameters = parameters; 5193 argumentList.correspondingStaticParameters = parameters;
4989 } 5194 }
4990 } 5195 }
(...skipping 11 matching lines...) Expand all
5002 String prefixName = prefixNode.name; 5207 String prefixName = prefixNode.name;
5003 for (PrefixElement prefixElement in _definingLibrary.prefixes) { 5208 for (PrefixElement prefixElement in _definingLibrary.prefixes) {
5004 if (prefixElement.displayName == prefixName) { 5209 if (prefixElement.displayName == prefixName) {
5005 prefixNode.staticElement = prefixElement; 5210 prefixNode.staticElement = prefixElement;
5006 break; 5211 break;
5007 } 5212 }
5008 } 5213 }
5009 } 5214 }
5010 ImportElement importElement = node.element; 5215 ImportElement importElement = node.element;
5011 if (importElement != null) { 5216 if (importElement != null) {
5217 // The element is null when the URI is invalid
5012 LibraryElement library = importElement.importedLibrary; 5218 LibraryElement library = importElement.importedLibrary;
5013 if (library != null) { 5219 if (library != null) {
5014 resolveCombinators(library, node.combinators); 5220 resolveCombinators(library, node.combinators);
5015 } 5221 }
5016 setMetadata(importElement, node); 5222 setMetadata(importElement, node);
5017 } 5223 }
5018 return null; 5224 return null;
5019 } 5225 }
5020 5226
5021 Object visitIndexExpression(IndexExpression node) { 5227 Object visitIndexExpression(IndexExpression node) {
5022 Expression target = node.realTarget; 5228 Expression target = node.realTarget;
5023 Type2 staticType = getStaticType(target); 5229 Type2 staticType = getStaticType(target);
5024 Type2 propagatedType = getPropagatedType(target); 5230 Type2 propagatedType = getPropagatedType(target);
5025 String getterMethodName = sc.TokenType.INDEX.lexeme; 5231 String getterMethodName = sc.TokenType.INDEX.lexeme;
5026 String setterMethodName = sc.TokenType.INDEX_EQ.lexeme; 5232 String setterMethodName = sc.TokenType.INDEX_EQ.lexeme;
5027 bool isInGetterContext = node.inGetterContext(); 5233 bool isInGetterContext = node.inGetterContext();
5028 bool isInSetterContext = node.inSetterContext(); 5234 bool isInSetterContext = node.inSetterContext();
5029 if (isInGetterContext && isInSetterContext) { 5235 if (isInGetterContext && isInSetterContext) {
5236 // lookup setter
5030 MethodElement setterStaticMethod = lookUpMethod(target, staticType, setter MethodName); 5237 MethodElement setterStaticMethod = lookUpMethod(target, staticType, setter MethodName);
5031 MethodElement setterPropagatedMethod = lookUpMethod(target, propagatedType , setterMethodName); 5238 MethodElement setterPropagatedMethod = lookUpMethod(target, propagatedType , setterMethodName);
5239 // set setter element
5032 node.staticElement = setterStaticMethod; 5240 node.staticElement = setterStaticMethod;
5033 node.propagatedElement = setterPropagatedMethod; 5241 node.propagatedElement = setterPropagatedMethod;
5242 // generate undefined method warning
5034 checkForUndefinedIndexOperator(node, target, getterMethodName, setterStati cMethod, setterPropagatedMethod, staticType, propagatedType); 5243 checkForUndefinedIndexOperator(node, target, getterMethodName, setterStati cMethod, setterPropagatedMethod, staticType, propagatedType);
5244 // lookup getter method
5035 MethodElement getterStaticMethod = lookUpMethod(target, staticType, getter MethodName); 5245 MethodElement getterStaticMethod = lookUpMethod(target, staticType, getter MethodName);
5036 MethodElement getterPropagatedMethod = lookUpMethod(target, propagatedType , getterMethodName); 5246 MethodElement getterPropagatedMethod = lookUpMethod(target, propagatedType , getterMethodName);
5247 // set getter element
5037 AuxiliaryElements auxiliaryElements = new AuxiliaryElements(getterStaticMe thod, getterPropagatedMethod); 5248 AuxiliaryElements auxiliaryElements = new AuxiliaryElements(getterStaticMe thod, getterPropagatedMethod);
5038 node.auxiliaryElements = auxiliaryElements; 5249 node.auxiliaryElements = auxiliaryElements;
5250 // generate undefined method warning
5039 checkForUndefinedIndexOperator(node, target, getterMethodName, getterStati cMethod, getterPropagatedMethod, staticType, propagatedType); 5251 checkForUndefinedIndexOperator(node, target, getterMethodName, getterStati cMethod, getterPropagatedMethod, staticType, propagatedType);
5040 } else if (isInGetterContext) { 5252 } else if (isInGetterContext) {
5253 // lookup getter method
5041 MethodElement staticMethod = lookUpMethod(target, staticType, getterMethod Name); 5254 MethodElement staticMethod = lookUpMethod(target, staticType, getterMethod Name);
5042 MethodElement propagatedMethod = lookUpMethod(target, propagatedType, gett erMethodName); 5255 MethodElement propagatedMethod = lookUpMethod(target, propagatedType, gett erMethodName);
5256 // set getter element
5043 node.staticElement = staticMethod; 5257 node.staticElement = staticMethod;
5044 node.propagatedElement = propagatedMethod; 5258 node.propagatedElement = propagatedMethod;
5259 // generate undefined method warning
5045 checkForUndefinedIndexOperator(node, target, getterMethodName, staticMetho d, propagatedMethod, staticType, propagatedType); 5260 checkForUndefinedIndexOperator(node, target, getterMethodName, staticMetho d, propagatedMethod, staticType, propagatedType);
5046 } else if (isInSetterContext) { 5261 } else if (isInSetterContext) {
5262 // lookup setter method
5047 MethodElement staticMethod = lookUpMethod(target, staticType, setterMethod Name); 5263 MethodElement staticMethod = lookUpMethod(target, staticType, setterMethod Name);
5048 MethodElement propagatedMethod = lookUpMethod(target, propagatedType, sett erMethodName); 5264 MethodElement propagatedMethod = lookUpMethod(target, propagatedType, sett erMethodName);
5265 // set setter element
5049 node.staticElement = staticMethod; 5266 node.staticElement = staticMethod;
5050 node.propagatedElement = propagatedMethod; 5267 node.propagatedElement = propagatedMethod;
5268 // generate undefined method warning
5051 checkForUndefinedIndexOperator(node, target, setterMethodName, staticMetho d, propagatedMethod, staticType, propagatedType); 5269 checkForUndefinedIndexOperator(node, target, setterMethodName, staticMetho d, propagatedMethod, staticType, propagatedType);
5052 } 5270 }
5053 return null; 5271 return null;
5054 } 5272 }
5055 5273
5056 Object visitInstanceCreationExpression(InstanceCreationExpression node) { 5274 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
5057 ConstructorElement invokedConstructor = node.constructorName.staticElement; 5275 ConstructorElement invokedConstructor = node.constructorName.staticElement;
5058 node.staticElement = invokedConstructor; 5276 node.staticElement = invokedConstructor;
5059 ArgumentList argumentList = node.argumentList; 5277 ArgumentList argumentList = node.argumentList;
5060 List<ParameterElement> parameters = resolveArgumentsToParameters(node.isCons t, argumentList, invokedConstructor); 5278 List<ParameterElement> parameters = resolveArgumentsToParameters(node.isCons t, argumentList, invokedConstructor);
5061 if (parameters != null) { 5279 if (parameters != null) {
5062 argumentList.correspondingStaticParameters = parameters; 5280 argumentList.correspondingStaticParameters = parameters;
5063 } 5281 }
5064 return null; 5282 return null;
5065 } 5283 }
5066 5284
5067 Object visitLibraryDirective(LibraryDirective node) { 5285 Object visitLibraryDirective(LibraryDirective node) {
5068 setMetadata(node.element, node); 5286 setMetadata(node.element, node);
5069 return null; 5287 return null;
5070 } 5288 }
5071 5289
5072 Object visitMethodDeclaration(MethodDeclaration node) { 5290 Object visitMethodDeclaration(MethodDeclaration node) {
5073 setMetadata(node.element, node); 5291 setMetadata(node.element, node);
5074 return null; 5292 return null;
5075 } 5293 }
5076 5294
5077 Object visitMethodInvocation(MethodInvocation node) { 5295 Object visitMethodInvocation(MethodInvocation node) {
5078 SimpleIdentifier methodName = node.methodName; 5296 SimpleIdentifier methodName = node.methodName;
5297 //
5298 // Synthetic identifiers have been already reported during parsing.
5299 //
5079 if (methodName.isSynthetic) { 5300 if (methodName.isSynthetic) {
5080 return null; 5301 return null;
5081 } 5302 }
5303 //
5304 // We have a method invocation of one of two forms: 'e.m(a1, ..., an)' or 'm (a1, ..., an)'. The
5305 // first step is to figure out which executable is being invoked, using both the static and the
5306 // propagated type information.
5307 //
5082 Expression target = node.realTarget; 5308 Expression target = node.realTarget;
5083 if (target is SuperExpression && !isSuperInValidContext(target)) { 5309 if (target is SuperExpression && !isSuperInValidContext(target)) {
5084 return null; 5310 return null;
5085 } 5311 }
5086 Element staticElement; 5312 Element staticElement;
5087 Element propagatedElement; 5313 Element propagatedElement;
5088 if (target == null) { 5314 if (target == null) {
5089 staticElement = resolveInvokedElement2(methodName); 5315 staticElement = resolveInvokedElement2(methodName);
5090 propagatedElement = null; 5316 propagatedElement = null;
5091 } else { 5317 } else {
5092 Type2 staticType = getStaticType(target); 5318 Type2 staticType = getStaticType(target);
5319 //
5320 // If this method invocation is of the form 'C.m' where 'C' is a class, th en we don't call
5321 // resolveInvokedElement(..) which walks up the class hierarchy, instead w e just look for the
5322 // member in the type only.
5323 //
5093 ClassElementImpl typeReference = getTypeReference(target); 5324 ClassElementImpl typeReference = getTypeReference(target);
5094 if (typeReference != null) { 5325 if (typeReference != null) {
5095 staticElement = propagatedElement = resolveElement(typeReference, method Name); 5326 staticElement = propagatedElement = resolveElement(typeReference, method Name);
5096 } else { 5327 } else {
5097 staticElement = resolveInvokedElement(target, staticType, methodName); 5328 staticElement = resolveInvokedElement(target, staticType, methodName);
5098 propagatedElement = resolveInvokedElement(target, getPropagatedType(targ et), methodName); 5329 propagatedElement = resolveInvokedElement(target, getPropagatedType(targ et), methodName);
5099 } 5330 }
5100 } 5331 }
5101 staticElement = convertSetterToGetter(staticElement); 5332 staticElement = convertSetterToGetter(staticElement);
5102 propagatedElement = convertSetterToGetter(propagatedElement); 5333 propagatedElement = convertSetterToGetter(propagatedElement);
5334 //
5335 // Record the results.
5336 //
5103 methodName.staticElement = staticElement; 5337 methodName.staticElement = staticElement;
5104 methodName.propagatedElement = propagatedElement; 5338 methodName.propagatedElement = propagatedElement;
5105 ArgumentList argumentList = node.argumentList; 5339 ArgumentList argumentList = node.argumentList;
5106 if (staticElement != null) { 5340 if (staticElement != null) {
5107 List<ParameterElement> parameters = computeCorrespondingParameters(argumen tList, staticElement); 5341 List<ParameterElement> parameters = computeCorrespondingParameters(argumen tList, staticElement);
5108 if (parameters != null) { 5342 if (parameters != null) {
5109 argumentList.correspondingStaticParameters = parameters; 5343 argumentList.correspondingStaticParameters = parameters;
5110 } 5344 }
5111 } 5345 }
5112 if (propagatedElement != null) { 5346 if (propagatedElement != null) {
5113 List<ParameterElement> parameters = computeCorrespondingParameters(argumen tList, propagatedElement); 5347 List<ParameterElement> parameters = computeCorrespondingParameters(argumen tList, propagatedElement);
5114 if (parameters != null) { 5348 if (parameters != null) {
5115 argumentList.correspondingPropagatedParameters = parameters; 5349 argumentList.correspondingPropagatedParameters = parameters;
5116 } 5350 }
5117 } 5351 }
5352 //
5353 // Then check for error conditions.
5354 //
5118 ErrorCode errorCode = checkForInvocationError(target, true, staticElement); 5355 ErrorCode errorCode = checkForInvocationError(target, true, staticElement);
5119 bool generatedWithTypePropagation = false; 5356 bool generatedWithTypePropagation = false;
5120 if (_enableHints && errorCode == null && staticElement == null) { 5357 if (_enableHints && errorCode == null && staticElement == null) {
5121 errorCode = checkForInvocationError(target, false, propagatedElement); 5358 errorCode = checkForInvocationError(target, false, propagatedElement);
5122 if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { 5359 if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
5123 ClassElement classElementContext = null; 5360 ClassElement classElementContext = null;
5124 if (target == null) { 5361 if (target == null) {
5125 classElementContext = _resolver.enclosingClass; 5362 classElementContext = _resolver.enclosingClass;
5126 } else { 5363 } else {
5127 Type2 type = target.bestType; 5364 Type2 type = target.bestType;
(...skipping 23 matching lines...) Expand all
5151 } else if (identical(errorCode, CompileTimeErrorCode.UNDEFINED_FUNCTION)) { 5388 } else if (identical(errorCode, CompileTimeErrorCode.UNDEFINED_FUNCTION)) {
5152 _resolver.reportError7(CompileTimeErrorCode.UNDEFINED_FUNCTION, methodName , [methodName.name]); 5389 _resolver.reportError7(CompileTimeErrorCode.UNDEFINED_FUNCTION, methodName , [methodName.name]);
5153 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { 5390 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
5154 String targetTypeName; 5391 String targetTypeName;
5155 if (target == null) { 5392 if (target == null) {
5156 ClassElement enclosingClass = _resolver.enclosingClass; 5393 ClassElement enclosingClass = _resolver.enclosingClass;
5157 targetTypeName = enclosingClass.displayName; 5394 targetTypeName = enclosingClass.displayName;
5158 ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDE FINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode; 5395 ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDE FINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode;
5159 _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingCl ass, proxyErrorCode, methodName, [methodName.name, targetTypeName]); 5396 _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingCl ass, proxyErrorCode, methodName, [methodName.name, targetTypeName]);
5160 } else { 5397 } else {
5398 // ignore Function "call"
5399 // (if we are about to create a hint using type propagation, then we can use type
5400 // propagation here as well)
5161 Type2 targetType = null; 5401 Type2 targetType = null;
5162 if (!generatedWithTypePropagation) { 5402 if (!generatedWithTypePropagation) {
5163 targetType = getStaticType(target); 5403 targetType = getStaticType(target);
5164 } else { 5404 } else {
5405 // choose the best type
5165 targetType = getPropagatedType(target); 5406 targetType = getPropagatedType(target);
5166 if (targetType == null) { 5407 if (targetType == null) {
5167 targetType = getStaticType(target); 5408 targetType = getStaticType(target);
5168 } 5409 }
5169 } 5410 }
5170 if (targetType != null && targetType.isDartCoreFunction && methodName.na me == CALL_METHOD_NAME) { 5411 if (targetType != null && targetType.isDartCoreFunction && methodName.na me == CALL_METHOD_NAME) {
5412 // TODO(brianwilkerson) Can we ever resolve the function being invoked ?
5413 //resolveArgumentsToParameters(node.getArgumentList(), invokedFunction );
5171 return null; 5414 return null;
5172 } 5415 }
5173 targetTypeName = targetType == null ? null : targetType.displayName; 5416 targetTypeName = targetType == null ? null : targetType.displayName;
5174 ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDE FINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode; 5417 ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDE FINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode;
5175 _resolver.reportErrorProxyConditionalAnalysisError(targetType.element, p roxyErrorCode, methodName, [methodName.name, targetTypeName]); 5418 _resolver.reportErrorProxyConditionalAnalysisError(targetType.element, p roxyErrorCode, methodName, [methodName.name, targetTypeName]);
5176 } 5419 }
5177 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD )) { 5420 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD )) {
5421 // Generate the type name.
5422 // The error code will never be generated via type propagation
5178 Type2 targetType = getStaticType(target); 5423 Type2 targetType = getStaticType(target);
5179 String targetTypeName = targetType == null ? null : targetType.name; 5424 String targetTypeName = targetType == null ? null : targetType.name;
5180 _resolver.reportError7(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, metho dName, [methodName.name, targetTypeName]); 5425 _resolver.reportError7(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, metho dName, [methodName.name, targetTypeName]);
5181 } 5426 }
5182 return null; 5427 return null;
5183 } 5428 }
5184 5429
5185 Object visitPartDirective(PartDirective node) { 5430 Object visitPartDirective(PartDirective node) {
5186 setMetadata(node.element, node); 5431 setMetadata(node.element, node);
5187 return null; 5432 return null;
5188 } 5433 }
5189 5434
5190 Object visitPartOfDirective(PartOfDirective node) { 5435 Object visitPartOfDirective(PartOfDirective node) {
5191 setMetadata(node.element, node); 5436 setMetadata(node.element, node);
5192 return null; 5437 return null;
5193 } 5438 }
5194 5439
5195 Object visitPostfixExpression(PostfixExpression node) { 5440 Object visitPostfixExpression(PostfixExpression node) {
5196 Expression operand = node.operand; 5441 Expression operand = node.operand;
5197 String methodName = getPostfixOperator(node); 5442 String methodName = getPostfixOperator(node);
5198 Type2 staticType = getStaticType(operand); 5443 Type2 staticType = getStaticType(operand);
5199 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName); 5444 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName);
5200 node.staticElement = staticMethod; 5445 node.staticElement = staticMethod;
5201 Type2 propagatedType = getPropagatedType(operand); 5446 Type2 propagatedType = getPropagatedType(operand);
5202 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, metho dName); 5447 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, metho dName);
5203 node.propagatedElement = propagatedMethod; 5448 node.propagatedElement = propagatedMethod;
5204 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticMethod); 5449 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticMethod);
5205 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false; 5450 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
5451 //
5452 // If we are about to generate the hint (propagated version of this warning) , then check
5453 // that the member is not in a subtype of the propagated type.
5454 //
5206 if (shouldReportMissingMember_propagated) { 5455 if (shouldReportMissingMember_propagated) {
5207 if (memberFoundInSubclass(propagatedType.element, methodName, true, false) ) { 5456 if (memberFoundInSubclass(propagatedType.element, methodName, true, false) ) {
5208 shouldReportMissingMember_propagated = false; 5457 shouldReportMissingMember_propagated = false;
5209 } 5458 }
5210 } 5459 }
5211 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) { 5460 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) {
5212 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarnin gCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode; 5461 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarnin gCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
5213 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissingMem ber_static ? staticType.element : propagatedType.element, errorCode, node.operat or, [ 5462 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissingMem ber_static ? staticType.element : propagatedType.element, errorCode, node.operat or, [
5214 methodName, 5463 methodName,
5215 shouldReportMissingMember_static ? staticType.displayName : propagated Type.displayName]); 5464 shouldReportMissingMember_static ? staticType.displayName : propagated Type.displayName]);
5216 } 5465 }
5217 return null; 5466 return null;
5218 } 5467 }
5219 5468
5220 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 5469 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
5221 SimpleIdentifier prefix = node.prefix; 5470 SimpleIdentifier prefix = node.prefix;
5222 SimpleIdentifier identifier = node.identifier; 5471 SimpleIdentifier identifier = node.identifier;
5472 //
5473 // First, check to see whether the prefix is really a prefix.
5474 //
5223 Element prefixElement = prefix.staticElement; 5475 Element prefixElement = prefix.staticElement;
5224 if (prefixElement is PrefixElement) { 5476 if (prefixElement is PrefixElement) {
5225 Element element = _resolver.nameScope.lookup(node, _definingLibrary); 5477 Element element = _resolver.nameScope.lookup(node, _definingLibrary);
5226 if (element == null && identifier.inSetterContext()) { 5478 if (element == null && identifier.inSetterContext()) {
5227 element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdenti fier("${node.name}="), _definingLibrary); 5479 element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdenti fier("${node.name}="), _definingLibrary);
5228 } 5480 }
5229 if (element == null) { 5481 if (element == null) {
5230 if (identifier.inSetterContext()) { 5482 if (identifier.inSetterContext()) {
5231 _resolver.reportError7(StaticWarningCode.UNDEFINED_SETTER, identifier, [identifier.name, prefixElement.name]); 5483 _resolver.reportError7(StaticWarningCode.UNDEFINED_SETTER, identifier, [identifier.name, prefixElement.name]);
5232 } else if (node.parent is Annotation) { 5484 } else if (node.parent is Annotation) {
5233 Annotation annotation = node.parent as Annotation; 5485 Annotation annotation = node.parent as Annotation;
5234 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annota tion, []); 5486 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annota tion, []);
5235 return null; 5487 return null;
5236 } else { 5488 } else {
5237 _resolver.reportError7(StaticWarningCode.UNDEFINED_GETTER, identifier, [identifier.name, prefixElement.name]); 5489 _resolver.reportError7(StaticWarningCode.UNDEFINED_GETTER, identifier, [identifier.name, prefixElement.name]);
5238 } 5490 }
5239 return null; 5491 return null;
5240 } 5492 }
5241 if (element is PropertyAccessorElement && identifier.inSetterContext()) { 5493 if (element is PropertyAccessorElement && identifier.inSetterContext()) {
5242 PropertyInducingElement variable = (element as PropertyAccessorElement). variable; 5494 PropertyInducingElement variable = (element as PropertyAccessorElement). variable;
5243 if (variable != null) { 5495 if (variable != null) {
5244 PropertyAccessorElement setter = variable.setter; 5496 PropertyAccessorElement setter = variable.setter;
5245 if (setter != null) { 5497 if (setter != null) {
5246 element = setter; 5498 element = setter;
5247 } 5499 }
5248 } 5500 }
5249 } 5501 }
5502 // TODO(brianwilkerson) The prefix needs to be resolved to the element for the import that
5503 // defines the prefix, not the prefix's element.
5250 identifier.staticElement = element; 5504 identifier.staticElement = element;
5505 // Validate annotation element.
5251 if (node.parent is Annotation) { 5506 if (node.parent is Annotation) {
5252 Annotation annotation = node.parent as Annotation; 5507 Annotation annotation = node.parent as Annotation;
5253 resolveAnnotationElement(annotation); 5508 resolveAnnotationElement(annotation);
5254 return null; 5509 return null;
5255 } 5510 }
5256 return null; 5511 return null;
5257 } 5512 }
5513 // May be annotation, resolve invocation of "const" constructor.
5258 if (node.parent is Annotation) { 5514 if (node.parent is Annotation) {
5259 Annotation annotation = node.parent as Annotation; 5515 Annotation annotation = node.parent as Annotation;
5260 resolveAnnotationElement(annotation); 5516 resolveAnnotationElement(annotation);
5261 } 5517 }
5518 //
5519 // Otherwise, the prefix is really an expression that happens to be a simple identifier and this
5520 // is really equivalent to a property access node.
5521 //
5262 resolvePropertyAccess(prefix, identifier); 5522 resolvePropertyAccess(prefix, identifier);
5263 return null; 5523 return null;
5264 } 5524 }
5265 5525
5266 Object visitPrefixExpression(PrefixExpression node) { 5526 Object visitPrefixExpression(PrefixExpression node) {
5267 sc.Token operator = node.operator; 5527 sc.Token operator = node.operator;
5268 sc.TokenType operatorType = operator.type; 5528 sc.TokenType operatorType = operator.type;
5269 if (operatorType.isUserDefinableOperator || identical(operatorType, sc.Token Type.PLUS_PLUS) || identical(operatorType, sc.TokenType.MINUS_MINUS)) { 5529 if (operatorType.isUserDefinableOperator || identical(operatorType, sc.Token Type.PLUS_PLUS) || identical(operatorType, sc.TokenType.MINUS_MINUS)) {
5270 Expression operand = node.operand; 5530 Expression operand = node.operand;
5271 String methodName = getPrefixOperator(node); 5531 String methodName = getPrefixOperator(node);
5272 Type2 staticType = getStaticType(operand); 5532 Type2 staticType = getStaticType(operand);
5273 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName) ; 5533 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName) ;
5274 node.staticElement = staticMethod; 5534 node.staticElement = staticMethod;
5275 Type2 propagatedType = getPropagatedType(operand); 5535 Type2 propagatedType = getPropagatedType(operand);
5276 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, met hodName); 5536 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, met hodName);
5277 node.propagatedElement = propagatedMethod; 5537 node.propagatedElement = propagatedMethod;
5278 bool shouldReportMissingMember_static = shouldReportMissingMember(staticTy pe, staticMethod); 5538 bool shouldReportMissingMember_static = shouldReportMissingMember(staticTy pe, staticMethod);
5279 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_sta tic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod ) : false; 5539 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_sta tic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod ) : false;
5540 //
5541 // If we are about to generate the hint (propagated version of this warnin g), then check
5542 // that the member is not in a subtype of the propagated type.
5543 //
5280 if (shouldReportMissingMember_propagated) { 5544 if (shouldReportMissingMember_propagated) {
5281 if (memberFoundInSubclass(propagatedType.element, methodName, true, fals e)) { 5545 if (memberFoundInSubclass(propagatedType.element, methodName, true, fals e)) {
5282 shouldReportMissingMember_propagated = false; 5546 shouldReportMissingMember_propagated = false;
5283 } 5547 }
5284 } 5548 }
5285 if (shouldReportMissingMember_static || shouldReportMissingMember_propagat ed) { 5549 if (shouldReportMissingMember_static || shouldReportMissingMember_propagat ed) {
5286 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarn ingCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode; 5550 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarn ingCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
5287 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissingM ember_static ? staticType.element : propagatedType.element, errorCode, operator, [ 5551 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissingM ember_static ? staticType.element : propagatedType.element, errorCode, operator, [
5288 methodName, 5552 methodName,
5289 shouldReportMissingMember_static ? staticType.displayName : propagat edType.displayName]); 5553 shouldReportMissingMember_static ? staticType.displayName : propagat edType.displayName]);
5290 } 5554 }
5291 } 5555 }
5292 return null; 5556 return null;
5293 } 5557 }
5294 5558
5295 Object visitPropertyAccess(PropertyAccess node) { 5559 Object visitPropertyAccess(PropertyAccess node) {
5296 Expression target = node.realTarget; 5560 Expression target = node.realTarget;
5297 if (target is SuperExpression && !isSuperInValidContext(target)) { 5561 if (target is SuperExpression && !isSuperInValidContext(target)) {
5298 return null; 5562 return null;
5299 } 5563 }
5300 SimpleIdentifier propertyName = node.propertyName; 5564 SimpleIdentifier propertyName = node.propertyName;
5301 resolvePropertyAccess(target, propertyName); 5565 resolvePropertyAccess(target, propertyName);
5302 return null; 5566 return null;
5303 } 5567 }
5304 5568
5305 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) { 5569 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
5306 ClassElement enclosingClass = _resolver.enclosingClass; 5570 ClassElement enclosingClass = _resolver.enclosingClass;
5307 if (enclosingClass == null) { 5571 if (enclosingClass == null) {
5572 // TODO(brianwilkerson) Report this error.
5308 return null; 5573 return null;
5309 } 5574 }
5310 SimpleIdentifier name = node.constructorName; 5575 SimpleIdentifier name = node.constructorName;
5311 ConstructorElement element; 5576 ConstructorElement element;
5312 if (name == null) { 5577 if (name == null) {
5313 element = enclosingClass.unnamedConstructor; 5578 element = enclosingClass.unnamedConstructor;
5314 } else { 5579 } else {
5315 element = enclosingClass.getNamedConstructor(name.name); 5580 element = enclosingClass.getNamedConstructor(name.name);
5316 } 5581 }
5317 if (element == null) { 5582 if (element == null) {
5583 // TODO(brianwilkerson) Report this error and decide what element to assoc iate with the node.
5318 return null; 5584 return null;
5319 } 5585 }
5320 if (name != null) { 5586 if (name != null) {
5321 name.staticElement = element; 5587 name.staticElement = element;
5322 } 5588 }
5323 node.staticElement = element; 5589 node.staticElement = element;
5324 ArgumentList argumentList = node.argumentList; 5590 ArgumentList argumentList = node.argumentList;
5325 List<ParameterElement> parameters = resolveArgumentsToParameters(false, argu mentList, element); 5591 List<ParameterElement> parameters = resolveArgumentsToParameters(false, argu mentList, element);
5326 if (parameters != null) { 5592 if (parameters != null) {
5327 argumentList.correspondingStaticParameters = parameters; 5593 argumentList.correspondingStaticParameters = parameters;
5328 } 5594 }
5329 return null; 5595 return null;
5330 } 5596 }
5331 5597
5332 Object visitSimpleIdentifier(SimpleIdentifier node) { 5598 Object visitSimpleIdentifier(SimpleIdentifier node) {
5599 //
5600 // Synthetic identifiers have been already reported during parsing.
5601 //
5333 if (node.isSynthetic) { 5602 if (node.isSynthetic) {
5334 return null; 5603 return null;
5335 } 5604 }
5605 //
5606 // We ignore identifiers that have already been resolved, such as identifier s representing the
5607 // name in a declaration.
5608 //
5336 if (node.staticElement != null) { 5609 if (node.staticElement != null) {
5337 return null; 5610 return null;
5338 } 5611 }
5612 //
5613 // The name dynamic denotes a Type object even though dynamic is not a class .
5614 //
5339 if (node.name == _dynamicType.name) { 5615 if (node.name == _dynamicType.name) {
5340 node.staticElement = _dynamicType.element; 5616 node.staticElement = _dynamicType.element;
5341 node.staticType = _typeType; 5617 node.staticType = _typeType;
5342 return null; 5618 return null;
5343 } 5619 }
5620 //
5621 // Otherwise, the node should be resolved.
5622 //
5344 Element element = resolveSimpleIdentifier(node); 5623 Element element = resolveSimpleIdentifier(node);
5345 ClassElement enclosingClass = _resolver.enclosingClass; 5624 ClassElement enclosingClass = _resolver.enclosingClass;
5346 if (isFactoryConstructorReturnType(node) && element != enclosingClass) { 5625 if (isFactoryConstructorReturnType(node) && element != enclosingClass) {
5347 _resolver.reportError7(CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLA SS, node, []); 5626 _resolver.reportError7(CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLA SS, node, []);
5348 } else if (isConstructorReturnType(node) && element != enclosingClass) { 5627 } else if (isConstructorReturnType(node) && element != enclosingClass) {
5349 _resolver.reportError7(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node , []); 5628 _resolver.reportError7(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node , []);
5350 element = null; 5629 element = null;
5351 } else if (element == null || (element is PrefixElement && !isValidAsPrefix( node))) { 5630 } else if (element == null || (element is PrefixElement && !isValidAsPrefix( node))) {
5631 // TODO(brianwilkerson) Recover from this error.
5352 if (isConstructorReturnType(node)) { 5632 if (isConstructorReturnType(node)) {
5353 _resolver.reportError7(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, no de, []); 5633 _resolver.reportError7(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, no de, []);
5354 } else if (node.parent is Annotation) { 5634 } else if (node.parent is Annotation) {
5355 Annotation annotation = node.parent as Annotation; 5635 Annotation annotation = node.parent as Annotation;
5356 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annotati on, []); 5636 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annotati on, []);
5357 } else { 5637 } else {
5358 _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingCl ass, StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]); 5638 _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingCl ass, StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
5359 } 5639 }
5360 } 5640 }
5361 node.staticElement = element; 5641 node.staticElement = element;
5362 if (node.inSetterContext() && node.inGetterContext() && enclosingClass != nu ll) { 5642 if (node.inSetterContext() && node.inGetterContext() && enclosingClass != nu ll) {
5363 InterfaceType enclosingType = enclosingClass.type; 5643 InterfaceType enclosingType = enclosingClass.type;
5364 AuxiliaryElements auxiliaryElements = new AuxiliaryElements(lookUpGetter(n ull, enclosingType, node.name), null); 5644 AuxiliaryElements auxiliaryElements = new AuxiliaryElements(lookUpGetter(n ull, enclosingType, node.name), null);
5365 node.auxiliaryElements = auxiliaryElements; 5645 node.auxiliaryElements = auxiliaryElements;
5366 } 5646 }
5647 //
5648 // Validate annotation element.
5649 //
5367 if (node.parent is Annotation) { 5650 if (node.parent is Annotation) {
5368 Annotation annotation = node.parent as Annotation; 5651 Annotation annotation = node.parent as Annotation;
5369 resolveAnnotationElement(annotation); 5652 resolveAnnotationElement(annotation);
5370 } 5653 }
5371 return null; 5654 return null;
5372 } 5655 }
5373 5656
5374 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { 5657 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
5375 ClassElement enclosingClass = _resolver.enclosingClass; 5658 ClassElement enclosingClass = _resolver.enclosingClass;
5376 if (enclosingClass == null) { 5659 if (enclosingClass == null) {
5660 // TODO(brianwilkerson) Report this error.
5377 return null; 5661 return null;
5378 } 5662 }
5379 InterfaceType superType = enclosingClass.supertype; 5663 InterfaceType superType = enclosingClass.supertype;
5380 if (superType == null) { 5664 if (superType == null) {
5665 // TODO(brianwilkerson) Report this error.
5381 return null; 5666 return null;
5382 } 5667 }
5383 SimpleIdentifier name = node.constructorName; 5668 SimpleIdentifier name = node.constructorName;
5384 String superName = name != null ? name.name : null; 5669 String superName = name != null ? name.name : null;
5385 ConstructorElement element = superType.lookUpConstructor(superName, _definin gLibrary); 5670 ConstructorElement element = superType.lookUpConstructor(superName, _definin gLibrary);
5386 if (element == null) { 5671 if (element == null) {
5387 if (name != null) { 5672 if (name != null) {
5388 _resolver.reportError7(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INI TIALIZER, node, [superType.displayName, name]); 5673 _resolver.reportError7(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INI TIALIZER, node, [superType.displayName, name]);
5389 } else { 5674 } else {
5390 _resolver.reportError7(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INI TIALIZER_DEFAULT, node, [superType.displayName]); 5675 _resolver.reportError7(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INI TIALIZER_DEFAULT, node, [superType.displayName]);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
5451 /** 5736 /**
5452 * Given that we have found code to invoke the given element, return the error code that should be 5737 * Given that we have found code to invoke the given element, return the error code that should be
5453 * reported, or `null` if no error should be reported. 5738 * reported, or `null` if no error should be reported.
5454 * 5739 *
5455 * @param target the target of the invocation, or `null` if there was no targe t 5740 * @param target the target of the invocation, or `null` if there was no targe t
5456 * @param useStaticContext 5741 * @param useStaticContext
5457 * @param element the element to be invoked 5742 * @param element the element to be invoked
5458 * @return the error code that should be reported 5743 * @return the error code that should be reported
5459 */ 5744 */
5460 ErrorCode checkForInvocationError(Expression target, bool useStaticContext, El ement element) { 5745 ErrorCode checkForInvocationError(Expression target, bool useStaticContext, El ement element) {
5746 // Prefix is not declared, instead "prefix.id" are declared.
5461 if (element is PrefixElement) { 5747 if (element is PrefixElement) {
5462 element = null; 5748 element = null;
5463 } 5749 }
5464 if (element is PropertyAccessorElement) { 5750 if (element is PropertyAccessorElement) {
5751 //
5752 // This is really a function expression invocation.
5753 //
5754 // TODO(brianwilkerson) Consider the possibility of re-writing the AST.
5465 FunctionType getterType = element.type; 5755 FunctionType getterType = element.type;
5466 if (getterType != null) { 5756 if (getterType != null) {
5467 Type2 returnType = getterType.returnType; 5757 Type2 returnType = getterType.returnType;
5468 if (!isExecutableType(returnType)) { 5758 if (!isExecutableType(returnType)) {
5469 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; 5759 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
5470 } 5760 }
5471 } 5761 }
5472 } else if (element is ExecutableElement) { 5762 } else if (element is ExecutableElement) {
5473 return null; 5763 return null;
5474 } else if (element == null && target is SuperExpression) { 5764 } else if (element == null && target is SuperExpression) {
5765 // TODO(jwren) We should split the UNDEFINED_METHOD into two error codes, this one, and
5766 // a code that describes the situation where the method was found, but it was not
5767 // accessible from the current library.
5475 return StaticTypeWarningCode.UNDEFINED_SUPER_METHOD; 5768 return StaticTypeWarningCode.UNDEFINED_SUPER_METHOD;
5476 } else { 5769 } else {
5770 //
5771 // This is really a function expression invocation.
5772 //
5773 // TODO(brianwilkerson) Consider the possibility of re-writing the AST.
5477 if (element is PropertyInducingElement) { 5774 if (element is PropertyInducingElement) {
5478 PropertyAccessorElement getter = element.getter; 5775 PropertyAccessorElement getter = element.getter;
5479 FunctionType getterType = getter.type; 5776 FunctionType getterType = getter.type;
5480 if (getterType != null) { 5777 if (getterType != null) {
5481 Type2 returnType = getterType.returnType; 5778 Type2 returnType = getterType.returnType;
5482 if (!isExecutableType(returnType)) { 5779 if (!isExecutableType(returnType)) {
5483 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; 5780 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
5484 } 5781 }
5485 } 5782 }
5486 } else if (element is VariableElement) { 5783 } else if (element is VariableElement) {
5487 Type2 variableType = element.type; 5784 Type2 variableType = element.type;
5488 if (!isExecutableType(variableType)) { 5785 if (!isExecutableType(variableType)) {
5489 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; 5786 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
5490 } 5787 }
5491 } else { 5788 } else {
5492 if (target == null) { 5789 if (target == null) {
5493 ClassElement enclosingClass = _resolver.enclosingClass; 5790 ClassElement enclosingClass = _resolver.enclosingClass;
5494 if (enclosingClass == null) { 5791 if (enclosingClass == null) {
5495 return CompileTimeErrorCode.UNDEFINED_FUNCTION; 5792 return CompileTimeErrorCode.UNDEFINED_FUNCTION;
5496 } else if (element == null) { 5793 } else if (element == null) {
5794 // Proxy-conditional warning, based on state of resolver.getEnclosin gClass()
5497 return StaticTypeWarningCode.UNDEFINED_METHOD; 5795 return StaticTypeWarningCode.UNDEFINED_METHOD;
5498 } else { 5796 } else {
5499 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; 5797 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
5500 } 5798 }
5501 } else { 5799 } else {
5502 Type2 targetType; 5800 Type2 targetType;
5503 if (useStaticContext) { 5801 if (useStaticContext) {
5504 targetType = getStaticType(target); 5802 targetType = getStaticType(target);
5505 } else { 5803 } else {
5804 // Compute and use the propagated type, if it is null, then it may b e the case that
5805 // static type is some type, in which the static type should be used .
5506 targetType = target.bestType; 5806 targetType = target.bestType;
5507 } 5807 }
5508 if (targetType == null) { 5808 if (targetType == null) {
5509 return CompileTimeErrorCode.UNDEFINED_FUNCTION; 5809 return CompileTimeErrorCode.UNDEFINED_FUNCTION;
5510 } else if (!targetType.isDynamic && !targetType.isBottom) { 5810 } else if (!targetType.isDynamic && !targetType.isBottom) {
5811 // Proxy-conditional warning, based on state of targetType.getElemen t()
5511 return StaticTypeWarningCode.UNDEFINED_METHOD; 5812 return StaticTypeWarningCode.UNDEFINED_METHOD;
5512 } 5813 }
5513 } 5814 }
5514 } 5815 }
5515 } 5816 }
5516 return null; 5817 return null;
5517 } 5818 }
5518 5819
5519 /** 5820 /**
5520 * Check that the for some index expression that the method element was resolv ed, otherwise a 5821 * Check that the for some index expression that the method element was resolv ed, otherwise a
5521 * [StaticWarningCode#UNDEFINED_OPERATOR] is generated. 5822 * [StaticWarningCode#UNDEFINED_OPERATOR] is generated.
5522 * 5823 *
5523 * @param node the index expression to resolve 5824 * @param node the index expression to resolve
5524 * @param target the target of the expression 5825 * @param target the target of the expression
5525 * @param methodName the name of the operator associated with the context of u sing of the given 5826 * @param methodName the name of the operator associated with the context of u sing of the given
5526 * index expression 5827 * index expression
5527 * @return `true` if and only if an error code is generated on the passed node 5828 * @return `true` if and only if an error code is generated on the passed node
5528 */ 5829 */
5529 bool checkForUndefinedIndexOperator(IndexExpression node, Expression target, S tring methodName, MethodElement staticMethod, MethodElement propagatedMethod, Ty pe2 staticType, Type2 propagatedType) { 5830 bool checkForUndefinedIndexOperator(IndexExpression node, Expression target, S tring methodName, MethodElement staticMethod, MethodElement propagatedMethod, Ty pe2 staticType, Type2 propagatedType) {
5530 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticMethod); 5831 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticMethod);
5531 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false; 5832 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
5833 //
5834 // If we are about to generate the hint (propagated version of this warning) , then check
5835 // that the member is not in a subtype of the propagated type.
5836 //
5532 if (shouldReportMissingMember_propagated) { 5837 if (shouldReportMissingMember_propagated) {
5533 if (memberFoundInSubclass(propagatedType.element, methodName, true, false) ) { 5838 if (memberFoundInSubclass(propagatedType.element, methodName, true, false) ) {
5534 shouldReportMissingMember_propagated = false; 5839 shouldReportMissingMember_propagated = false;
5535 } 5840 }
5536 } 5841 }
5537 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) { 5842 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) {
5538 sc.Token leftBracket = node.leftBracket; 5843 sc.Token leftBracket = node.leftBracket;
5539 sc.Token rightBracket = node.rightBracket; 5844 sc.Token rightBracket = node.rightBracket;
5540 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarnin gCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode; 5845 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarnin gCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
5541 if (leftBracket == null || rightBracket == null) { 5846 if (leftBracket == null || rightBracket == null) {
(...skipping 16 matching lines...) Expand all
5558 * Given a list of arguments and the element that will be invoked using those argument, compute 5863 * Given a list of arguments and the element that will be invoked using those argument, compute
5559 * the list of parameters that correspond to the list of arguments. Return the parameters that 5864 * the list of parameters that correspond to the list of arguments. Return the parameters that
5560 * correspond to the arguments, or `null` if no correspondence could be comput ed. 5865 * correspond to the arguments, or `null` if no correspondence could be comput ed.
5561 * 5866 *
5562 * @param argumentList the list of arguments being passed to the element 5867 * @param argumentList the list of arguments being passed to the element
5563 * @param executableElement the element that will be invoked with the argument s 5868 * @param executableElement the element that will be invoked with the argument s
5564 * @return the parameters that correspond to the arguments 5869 * @return the parameters that correspond to the arguments
5565 */ 5870 */
5566 List<ParameterElement> computeCorrespondingParameters(ArgumentList argumentLis t, Element element) { 5871 List<ParameterElement> computeCorrespondingParameters(ArgumentList argumentLis t, Element element) {
5567 if (element is PropertyAccessorElement) { 5872 if (element is PropertyAccessorElement) {
5873 //
5874 // This is an invocation of the call method defined on the value returned by the getter.
5875 //
5568 FunctionType getterType = element.type; 5876 FunctionType getterType = element.type;
5569 if (getterType != null) { 5877 if (getterType != null) {
5570 Type2 getterReturnType = getterType.returnType; 5878 Type2 getterReturnType = getterType.returnType;
5571 if (getterReturnType is InterfaceType) { 5879 if (getterReturnType is InterfaceType) {
5572 MethodElement callMethod = getterReturnType.lookUpMethod(CALL_METHOD_N AME, _definingLibrary); 5880 MethodElement callMethod = getterReturnType.lookUpMethod(CALL_METHOD_N AME, _definingLibrary);
5573 if (callMethod != null) { 5881 if (callMethod != null) {
5574 return resolveArgumentsToParameters(false, argumentList, callMethod) ; 5882 return resolveArgumentsToParameters(false, argumentList, callMethod) ;
5575 } 5883 }
5576 } else if (getterReturnType is FunctionType) { 5884 } else if (getterReturnType is FunctionType) {
5577 Element functionElement = getterReturnType.element; 5885 Element functionElement = getterReturnType.element;
5578 if (functionElement is ExecutableElement) { 5886 if (functionElement is ExecutableElement) {
5579 return resolveArgumentsToParameters(false, argumentList, functionEle ment); 5887 return resolveArgumentsToParameters(false, argumentList, functionEle ment);
5580 } 5888 }
5581 } 5889 }
5582 } 5890 }
5583 } else if (element is ExecutableElement) { 5891 } else if (element is ExecutableElement) {
5584 return resolveArgumentsToParameters(false, argumentList, element); 5892 return resolveArgumentsToParameters(false, argumentList, element);
5585 } else if (element is VariableElement) { 5893 } else if (element is VariableElement) {
5586 VariableElement variable = element; 5894 VariableElement variable = element;
5587 Type2 type = _promoteManager.getStaticType(variable); 5895 Type2 type = _promoteManager.getStaticType(variable);
5588 if (type is FunctionType) { 5896 if (type is FunctionType) {
5589 FunctionType functionType = type; 5897 FunctionType functionType = type;
5590 List<ParameterElement> parameters = functionType.parameters; 5898 List<ParameterElement> parameters = functionType.parameters;
5591 return resolveArgumentsToParameters2(false, argumentList, parameters); 5899 return resolveArgumentsToParameters2(false, argumentList, parameters);
5592 } else if (type is InterfaceType) { 5900 } else if (type is InterfaceType) {
5901 // "call" invocation
5593 MethodElement callMethod = type.lookUpMethod(CALL_METHOD_NAME, _defining Library); 5902 MethodElement callMethod = type.lookUpMethod(CALL_METHOD_NAME, _defining Library);
5594 if (callMethod != null) { 5903 if (callMethod != null) {
5595 List<ParameterElement> parameters = callMethod.parameters; 5904 List<ParameterElement> parameters = callMethod.parameters;
5596 return resolveArgumentsToParameters2(false, argumentList, parameters); 5905 return resolveArgumentsToParameters2(false, argumentList, parameters);
5597 } 5906 }
5598 } 5907 }
5599 } 5908 }
5600 return null; 5909 return null;
5601 } 5910 }
5602 5911
5603 /** 5912 /**
5604 * If the given element is a setter, return the getter associated with it. Oth erwise, return the 5913 * If the given element is a setter, return the getter associated with it. Oth erwise, return the
5605 * element unchanged. 5914 * element unchanged.
5606 * 5915 *
5607 * @param element the element to be normalized 5916 * @param element the element to be normalized
5608 * @return a non-setter element derived from the given element 5917 * @return a non-setter element derived from the given element
5609 */ 5918 */
5610 Element convertSetterToGetter(Element element) { 5919 Element convertSetterToGetter(Element element) {
5920 // TODO(brianwilkerson) Determine whether and why the element could ever be a setter.
5611 if (element is PropertyAccessorElement) { 5921 if (element is PropertyAccessorElement) {
5612 return element.variable.getter; 5922 return element.variable.getter;
5613 } 5923 }
5614 return element; 5924 return element;
5615 } 5925 }
5616 5926
5617 /** 5927 /**
5618 * Look for any declarations of the given identifier that are imported using a prefix. Return the 5928 * Look for any declarations of the given identifier that are imported using a prefix. Return the
5619 * element that was found, or `null` if the name is not imported using a prefi x. 5929 * element that was found, or `null` if the name is not imported using a prefi x.
5620 * 5930 *
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
5671 5981
5672 /** 5982 /**
5673 * Return the propagated type of the given expression that is to be used for t ype analysis. 5983 * Return the propagated type of the given expression that is to be used for t ype analysis.
5674 * 5984 *
5675 * @param expression the expression whose type is to be returned 5985 * @param expression the expression whose type is to be returned
5676 * @return the type of the given expression 5986 * @return the type of the given expression
5677 */ 5987 */
5678 Type2 getPropagatedType(Expression expression) { 5988 Type2 getPropagatedType(Expression expression) {
5679 Type2 propagatedType = resolveTypeParameter(expression.propagatedType); 5989 Type2 propagatedType = resolveTypeParameter(expression.propagatedType);
5680 if (propagatedType is FunctionType) { 5990 if (propagatedType is FunctionType) {
5991 //
5992 // All function types are subtypes of 'Function', which is itself a subcla ss of 'Object'.
5993 //
5681 propagatedType = _resolver.typeProvider.functionType; 5994 propagatedType = _resolver.typeProvider.functionType;
5682 } 5995 }
5683 return propagatedType; 5996 return propagatedType;
5684 } 5997 }
5685 5998
5686 /** 5999 /**
5687 * Return the static type of the given expression that is to be used for type analysis. 6000 * Return the static type of the given expression that is to be used for type analysis.
5688 * 6001 *
5689 * @param expression the expression whose type is to be returned 6002 * @param expression the expression whose type is to be returned
5690 * @return the type of the given expression 6003 * @return the type of the given expression
5691 */ 6004 */
5692 Type2 getStaticType(Expression expression) { 6005 Type2 getStaticType(Expression expression) {
5693 if (expression is NullLiteral) { 6006 if (expression is NullLiteral) {
5694 return _resolver.typeProvider.bottomType; 6007 return _resolver.typeProvider.bottomType;
5695 } 6008 }
5696 Type2 staticType = resolveTypeParameter(expression.staticType); 6009 Type2 staticType = resolveTypeParameter(expression.staticType);
5697 if (staticType is FunctionType) { 6010 if (staticType is FunctionType) {
6011 //
6012 // All function types are subtypes of 'Function', which is itself a subcla ss of 'Object'.
6013 //
5698 staticType = _resolver.typeProvider.functionType; 6014 staticType = _resolver.typeProvider.functionType;
5699 } 6015 }
5700 return staticType; 6016 return staticType;
5701 } 6017 }
5702 6018
5703 /** 6019 /**
5704 * Return `true` if the given type represents an object that could be invoked using the call 6020 * Return `true` if the given type represents an object that could be invoked using the call
5705 * operator '()'. 6021 * operator '()'.
5706 * 6022 *
5707 * @param type the type being tested 6023 * @param type the type being tested
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
5799 * `null` if there is no getter with the given name. 6115 * `null` if there is no getter with the given name.
5800 * 6116 *
5801 * @param targetType the type in which the getter might be defined 6117 * @param targetType the type in which the getter might be defined
5802 * @param includeTargetType `true` if the search should include the target typ e 6118 * @param includeTargetType `true` if the search should include the target typ e
5803 * @param getterName the name of the getter being looked up 6119 * @param getterName the name of the getter being looked up
5804 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used 6120 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used
5805 * to prevent infinite recursion and to optimize the search 6121 * to prevent infinite recursion and to optimize the search
5806 * @return the element representing the getter that was found 6122 * @return the element representing the getter that was found
5807 */ 6123 */
5808 PropertyAccessorElement lookUpGetterInInterfaces(InterfaceType targetType, boo l includeTargetType, String getterName, Set<ClassElement> visitedInterfaces) { 6124 PropertyAccessorElement lookUpGetterInInterfaces(InterfaceType targetType, boo l includeTargetType, String getterName, Set<ClassElement> visitedInterfaces) {
6125 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the specificati on (titled
6126 // "Inheritance and Overriding" under "Interfaces") describes a much more co mplex scheme for
6127 // finding the inherited member. We need to follow that scheme. The code bel ow should cover the
6128 // 80% case.
5809 ClassElement targetClass = targetType.element; 6129 ClassElement targetClass = targetType.element;
5810 if (visitedInterfaces.contains(targetClass)) { 6130 if (visitedInterfaces.contains(targetClass)) {
5811 return null; 6131 return null;
5812 } 6132 }
5813 visitedInterfaces.add(targetClass); 6133 visitedInterfaces.add(targetClass);
5814 if (includeTargetType) { 6134 if (includeTargetType) {
5815 PropertyAccessorElement getter = targetType.getGetter(getterName); 6135 PropertyAccessorElement getter = targetType.getGetter(getterName);
5816 if (getter != null && getter.isAccessibleIn(_definingLibrary)) { 6136 if (getter != null && getter.isAccessibleIn(_definingLibrary)) {
5817 return getter; 6137 return getter;
5818 } 6138 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
5868 * was found, or `null` if there is no method or getter with the given name. 6188 * was found, or `null` if there is no method or getter with the given name.
5869 * 6189 *
5870 * @param targetType the type in which the method or getter might be defined 6190 * @param targetType the type in which the method or getter might be defined
5871 * @param includeTargetType `true` if the search should include the target typ e 6191 * @param includeTargetType `true` if the search should include the target typ e
5872 * @param memberName the name of the method or getter being looked up 6192 * @param memberName the name of the method or getter being looked up
5873 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used 6193 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used
5874 * to prevent infinite recursion and to optimize the search 6194 * to prevent infinite recursion and to optimize the search
5875 * @return the element representing the method or getter that was found 6195 * @return the element representing the method or getter that was found
5876 */ 6196 */
5877 ExecutableElement lookUpGetterOrMethodInInterfaces(InterfaceType targetType, b ool includeTargetType, String memberName, Set<ClassElement> visitedInterfaces) { 6197 ExecutableElement lookUpGetterOrMethodInInterfaces(InterfaceType targetType, b ool includeTargetType, String memberName, Set<ClassElement> visitedInterfaces) {
6198 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the specificati on (titled
6199 // "Inheritance and Overriding" under "Interfaces") describes a much more co mplex scheme for
6200 // finding the inherited member. We need to follow that scheme. The code bel ow should cover the
6201 // 80% case.
5878 ClassElement targetClass = targetType.element; 6202 ClassElement targetClass = targetType.element;
5879 if (visitedInterfaces.contains(targetClass)) { 6203 if (visitedInterfaces.contains(targetClass)) {
5880 return null; 6204 return null;
5881 } 6205 }
5882 visitedInterfaces.add(targetClass); 6206 visitedInterfaces.add(targetClass);
5883 if (includeTargetType) { 6207 if (includeTargetType) {
5884 ExecutableElement member = targetType.getMethod(memberName); 6208 ExecutableElement member = targetType.getMethod(memberName);
5885 if (member != null) { 6209 if (member != null) {
5886 return member; 6210 return member;
5887 } 6211 }
(...skipping 30 matching lines...) Expand all
5918 */ 6242 */
5919 LabelElementImpl lookupLabel(ASTNode parentNode, SimpleIdentifier labelNode) { 6243 LabelElementImpl lookupLabel(ASTNode parentNode, SimpleIdentifier labelNode) {
5920 LabelScope labelScope = _resolver.labelScope; 6244 LabelScope labelScope = _resolver.labelScope;
5921 LabelElementImpl labelElement = null; 6245 LabelElementImpl labelElement = null;
5922 if (labelNode == null) { 6246 if (labelNode == null) {
5923 if (labelScope == null) { 6247 if (labelScope == null) {
5924 } else { 6248 } else {
5925 labelElement = labelScope.lookup2(LabelScope.EMPTY_LABEL) as LabelElemen tImpl; 6249 labelElement = labelScope.lookup2(LabelScope.EMPTY_LABEL) as LabelElemen tImpl;
5926 if (labelElement == null) { 6250 if (labelElement == null) {
5927 } 6251 }
6252 //
6253 // The label element that was returned was a marker for look-up and isn' t stored in the
6254 // element model.
6255 //
5928 labelElement = null; 6256 labelElement = null;
5929 } 6257 }
5930 } else { 6258 } else {
5931 if (labelScope == null) { 6259 if (labelScope == null) {
5932 _resolver.reportError7(CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]); 6260 _resolver.reportError7(CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]);
5933 } else { 6261 } else {
5934 labelElement = labelScope.lookup(labelNode) as LabelElementImpl; 6262 labelElement = labelScope.lookup(labelNode) as LabelElementImpl;
5935 if (labelElement == null) { 6263 if (labelElement == null) {
5936 _resolver.reportError7(CompileTimeErrorCode.LABEL_UNDEFINED, labelNode , [labelNode.name]); 6264 _resolver.reportError7(CompileTimeErrorCode.LABEL_UNDEFINED, labelNode , [labelNode.name]);
5937 } else { 6265 } else {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
5982 * `null` if there is no method with the given name. 6310 * `null` if there is no method with the given name.
5983 * 6311 *
5984 * @param targetType the type in which the member might be defined 6312 * @param targetType the type in which the member might be defined
5985 * @param includeTargetType `true` if the search should include the target typ e 6313 * @param includeTargetType `true` if the search should include the target typ e
5986 * @param methodName the name of the method being looked up 6314 * @param methodName the name of the method being looked up
5987 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used 6315 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used
5988 * to prevent infinite recursion and to optimize the search 6316 * to prevent infinite recursion and to optimize the search
5989 * @return the element representing the method that was found 6317 * @return the element representing the method that was found
5990 */ 6318 */
5991 MethodElement lookUpMethodInInterfaces(InterfaceType targetType, bool includeT argetType, String methodName, Set<ClassElement> visitedInterfaces) { 6319 MethodElement lookUpMethodInInterfaces(InterfaceType targetType, bool includeT argetType, String methodName, Set<ClassElement> visitedInterfaces) {
6320 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the specificati on (titled
6321 // "Inheritance and Overriding" under "Interfaces") describes a much more co mplex scheme for
6322 // finding the inherited member. We need to follow that scheme. The code bel ow should cover the
6323 // 80% case.
5992 ClassElement targetClass = targetType.element; 6324 ClassElement targetClass = targetType.element;
5993 if (visitedInterfaces.contains(targetClass)) { 6325 if (visitedInterfaces.contains(targetClass)) {
5994 return null; 6326 return null;
5995 } 6327 }
5996 visitedInterfaces.add(targetClass); 6328 visitedInterfaces.add(targetClass);
5997 if (includeTargetType) { 6329 if (includeTargetType) {
5998 MethodElement method = targetType.getMethod(methodName); 6330 MethodElement method = targetType.getMethod(methodName);
5999 if (method != null && method.isAccessibleIn(_definingLibrary)) { 6331 if (method != null && method.isAccessibleIn(_definingLibrary)) {
6000 return method; 6332 return method;
6001 } 6333 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
6052 * `null` if there is no setter with the given name. 6384 * `null` if there is no setter with the given name.
6053 * 6385 *
6054 * @param targetType the type in which the setter might be defined 6386 * @param targetType the type in which the setter might be defined
6055 * @param includeTargetType `true` if the search should include the target typ e 6387 * @param includeTargetType `true` if the search should include the target typ e
6056 * @param setterName the name of the setter being looked up 6388 * @param setterName the name of the setter being looked up
6057 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used 6389 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used
6058 * to prevent infinite recursion and to optimize the search 6390 * to prevent infinite recursion and to optimize the search
6059 * @return the element representing the setter that was found 6391 * @return the element representing the setter that was found
6060 */ 6392 */
6061 PropertyAccessorElement lookUpSetterInInterfaces(InterfaceType targetType, boo l includeTargetType, String setterName, Set<ClassElement> visitedInterfaces) { 6393 PropertyAccessorElement lookUpSetterInInterfaces(InterfaceType targetType, boo l includeTargetType, String setterName, Set<ClassElement> visitedInterfaces) {
6394 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the specificati on (titled
6395 // "Inheritance and Overriding" under "Interfaces") describes a much more co mplex scheme for
6396 // finding the inherited member. We need to follow that scheme. The code bel ow should cover the
6397 // 80% case.
6062 ClassElement targetClass = targetType.element; 6398 ClassElement targetClass = targetType.element;
6063 if (visitedInterfaces.contains(targetClass)) { 6399 if (visitedInterfaces.contains(targetClass)) {
6064 return null; 6400 return null;
6065 } 6401 }
6066 visitedInterfaces.add(targetClass); 6402 visitedInterfaces.add(targetClass);
6067 if (includeTargetType) { 6403 if (includeTargetType) {
6068 PropertyAccessorElement setter = targetType.getSetter(setterName); 6404 PropertyAccessorElement setter = targetType.getSetter(setterName);
6069 if (setter != null && setter.isAccessibleIn(_definingLibrary)) { 6405 if (setter != null && setter.isAccessibleIn(_definingLibrary)) {
6070 return setter; 6406 return setter;
6071 } 6407 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
6143 return sc.TokenType.PLUS; 6479 return sc.TokenType.PLUS;
6144 } else if (operator == sc.TokenType.SLASH_EQ) { 6480 } else if (operator == sc.TokenType.SLASH_EQ) {
6145 return sc.TokenType.SLASH; 6481 return sc.TokenType.SLASH;
6146 } else if (operator == sc.TokenType.STAR_EQ) { 6482 } else if (operator == sc.TokenType.STAR_EQ) {
6147 return sc.TokenType.STAR; 6483 return sc.TokenType.STAR;
6148 } else if (operator == sc.TokenType.TILDE_SLASH_EQ) { 6484 } else if (operator == sc.TokenType.TILDE_SLASH_EQ) {
6149 return sc.TokenType.TILDE_SLASH; 6485 return sc.TokenType.TILDE_SLASH;
6150 } 6486 }
6151 break; 6487 break;
6152 } 6488 }
6489 // Internal error: Unmapped assignment operator.
6153 AnalysisEngine.instance.logger.logError("Failed to map ${operator.lexeme} to it's corresponding operator"); 6490 AnalysisEngine.instance.logger.logError("Failed to map ${operator.lexeme} to it's corresponding operator");
6154 return operator; 6491 return operator;
6155 } 6492 }
6156 6493
6157 void resolveAnnotationConstructorInvocationArguments(Annotation annotation, Co nstructorElement constructor) { 6494 void resolveAnnotationConstructorInvocationArguments(Annotation annotation, Co nstructorElement constructor) {
6158 ArgumentList argumentList = annotation.arguments; 6495 ArgumentList argumentList = annotation.arguments;
6496 // error will be reported in ConstantVerifier
6159 if (argumentList == null) { 6497 if (argumentList == null) {
6160 return; 6498 return;
6161 } 6499 }
6500 // resolve arguments to parameters
6162 List<ParameterElement> parameters = resolveArgumentsToParameters(true, argum entList, constructor); 6501 List<ParameterElement> parameters = resolveArgumentsToParameters(true, argum entList, constructor);
6163 if (parameters != null) { 6502 if (parameters != null) {
6164 argumentList.correspondingStaticParameters = parameters; 6503 argumentList.correspondingStaticParameters = parameters;
6165 } 6504 }
6166 } 6505 }
6167 6506
6168 /** 6507 /**
6169 * Continues resolution of the given [Annotation]. 6508 * Continues resolution of the given [Annotation].
6170 * 6509 *
6171 * @param annotation the [Annotation] to resolve 6510 * @param annotation the [Annotation] to resolve
6172 */ 6511 */
6173 void resolveAnnotationElement(Annotation annotation) { 6512 void resolveAnnotationElement(Annotation annotation) {
6174 SimpleIdentifier nameNode1; 6513 SimpleIdentifier nameNode1;
6175 SimpleIdentifier nameNode2; 6514 SimpleIdentifier nameNode2;
6176 { 6515 {
6177 Identifier annName = annotation.name; 6516 Identifier annName = annotation.name;
6178 if (annName is PrefixedIdentifier) { 6517 if (annName is PrefixedIdentifier) {
6179 PrefixedIdentifier prefixed = annName; 6518 PrefixedIdentifier prefixed = annName;
6180 nameNode1 = prefixed.prefix; 6519 nameNode1 = prefixed.prefix;
6181 nameNode2 = prefixed.identifier; 6520 nameNode2 = prefixed.identifier;
6182 } else { 6521 } else {
6183 nameNode1 = annName as SimpleIdentifier; 6522 nameNode1 = annName as SimpleIdentifier;
6184 nameNode2 = null; 6523 nameNode2 = null;
6185 } 6524 }
6186 } 6525 }
6187 SimpleIdentifier nameNode3 = annotation.constructorName; 6526 SimpleIdentifier nameNode3 = annotation.constructorName;
6188 ConstructorElement constructor = null; 6527 ConstructorElement constructor = null;
6528 //
6529 // CONST or Class(args)
6530 //
6189 if (nameNode1 != null && nameNode2 == null && nameNode3 == null) { 6531 if (nameNode1 != null && nameNode2 == null && nameNode3 == null) {
6190 Element element1 = nameNode1.staticElement; 6532 Element element1 = nameNode1.staticElement;
6533 // CONST
6191 if (element1 is PropertyAccessorElement) { 6534 if (element1 is PropertyAccessorElement) {
6192 resolveAnnotationElementGetter(annotation, element1); 6535 resolveAnnotationElementGetter(annotation, element1);
6193 return; 6536 return;
6194 } 6537 }
6538 // Class(args)
6195 if (element1 is ClassElement) { 6539 if (element1 is ClassElement) {
6196 ClassElement classElement = element1; 6540 ClassElement classElement = element1;
6197 constructor = new InterfaceTypeImpl.con1(classElement).lookUpConstructor (null, _definingLibrary); 6541 constructor = new InterfaceTypeImpl.con1(classElement).lookUpConstructor (null, _definingLibrary);
6198 } 6542 }
6199 } 6543 }
6544 //
6545 // prefix.CONST or prefix.Class() or Class.CONST or Class.constructor(args)
6546 //
6200 if (nameNode1 != null && nameNode2 != null && nameNode3 == null) { 6547 if (nameNode1 != null && nameNode2 != null && nameNode3 == null) {
6201 Element element1 = nameNode1.staticElement; 6548 Element element1 = nameNode1.staticElement;
6202 Element element2 = nameNode2.staticElement; 6549 Element element2 = nameNode2.staticElement;
6550 // Class.CONST - not resolved yet
6203 if (element1 is ClassElement) { 6551 if (element1 is ClassElement) {
6204 ClassElement classElement = element1; 6552 ClassElement classElement = element1;
6205 element2 = classElement.lookUpGetter(nameNode2.name, _definingLibrary); 6553 element2 = classElement.lookUpGetter(nameNode2.name, _definingLibrary);
6206 } 6554 }
6555 // prefix.CONST or Class.CONST
6207 if (element2 is PropertyAccessorElement) { 6556 if (element2 is PropertyAccessorElement) {
6208 nameNode2.staticElement = element2; 6557 nameNode2.staticElement = element2;
6209 annotation.element = element2; 6558 annotation.element = element2;
6210 resolveAnnotationElementGetter(annotation, element2 as PropertyAccessorE lement); 6559 resolveAnnotationElementGetter(annotation, element2 as PropertyAccessorE lement);
6211 return; 6560 return;
6212 } 6561 }
6562 // prefix.Class()
6213 if (element2 is ClassElement) { 6563 if (element2 is ClassElement) {
6214 ClassElement classElement = element2 as ClassElement; 6564 ClassElement classElement = element2 as ClassElement;
6215 constructor = classElement.unnamedConstructor; 6565 constructor = classElement.unnamedConstructor;
6216 } 6566 }
6567 // Class.constructor(args)
6217 if (element1 is ClassElement) { 6568 if (element1 is ClassElement) {
6218 ClassElement classElement = element1; 6569 ClassElement classElement = element1;
6219 constructor = new InterfaceTypeImpl.con1(classElement).lookUpConstructor (nameNode2.name, _definingLibrary); 6570 constructor = new InterfaceTypeImpl.con1(classElement).lookUpConstructor (nameNode2.name, _definingLibrary);
6220 nameNode2.staticElement = constructor; 6571 nameNode2.staticElement = constructor;
6221 } 6572 }
6222 } 6573 }
6574 //
6575 // prefix.Class.CONST or prefix.Class.constructor(args)
6576 //
6223 if (nameNode1 != null && nameNode2 != null && nameNode3 != null) { 6577 if (nameNode1 != null && nameNode2 != null && nameNode3 != null) {
6224 Element element2 = nameNode2.staticElement; 6578 Element element2 = nameNode2.staticElement;
6579 // element2 should be ClassElement
6225 if (element2 is ClassElement) { 6580 if (element2 is ClassElement) {
6226 ClassElement classElement = element2; 6581 ClassElement classElement = element2;
6227 String name3 = nameNode3.name; 6582 String name3 = nameNode3.name;
6583 // prefix.Class.CONST
6228 PropertyAccessorElement getter = classElement.lookUpGetter(name3, _defin ingLibrary); 6584 PropertyAccessorElement getter = classElement.lookUpGetter(name3, _defin ingLibrary);
6229 if (getter != null) { 6585 if (getter != null) {
6230 nameNode3.staticElement = getter; 6586 nameNode3.staticElement = getter;
6231 annotation.element = element2; 6587 annotation.element = element2;
6232 resolveAnnotationElementGetter(annotation, getter); 6588 resolveAnnotationElementGetter(annotation, getter);
6233 return; 6589 return;
6234 } 6590 }
6591 // prefix.Class.constructor(args)
6235 constructor = new InterfaceTypeImpl.con1(classElement).lookUpConstructor (name3, _definingLibrary); 6592 constructor = new InterfaceTypeImpl.con1(classElement).lookUpConstructor (name3, _definingLibrary);
6236 nameNode3.staticElement = constructor; 6593 nameNode3.staticElement = constructor;
6237 } 6594 }
6238 } 6595 }
6596 // we need constructor
6239 if (constructor == null) { 6597 if (constructor == null) {
6240 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annotation , []); 6598 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annotation , []);
6241 return; 6599 return;
6242 } 6600 }
6601 // record element
6243 annotation.element = constructor; 6602 annotation.element = constructor;
6603 // resolve arguments
6244 resolveAnnotationConstructorInvocationArguments(annotation, constructor); 6604 resolveAnnotationConstructorInvocationArguments(annotation, constructor);
6245 } 6605 }
6246 6606
6247 void resolveAnnotationElementGetter(Annotation annotation, PropertyAccessorEle ment accessorElement) { 6607 void resolveAnnotationElementGetter(Annotation annotation, PropertyAccessorEle ment accessorElement) {
6608 // accessor should be synthetic
6248 if (!accessorElement.isSynthetic) { 6609 if (!accessorElement.isSynthetic) {
6249 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annotation , []); 6610 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annotation , []);
6250 return; 6611 return;
6251 } 6612 }
6613 // variable should be constant
6252 VariableElement variableElement = accessorElement.variable; 6614 VariableElement variableElement = accessorElement.variable;
6253 if (!variableElement.isConst) { 6615 if (!variableElement.isConst) {
6254 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annotation , []); 6616 _resolver.reportError7(CompileTimeErrorCode.INVALID_ANNOTATION, annotation , []);
6255 } 6617 }
6618 // OK
6256 return; 6619 return;
6257 } 6620 }
6258 6621
6259 /** 6622 /**
6260 * Given a list of arguments and the element that will be invoked using those argument, compute 6623 * Given a list of arguments and the element that will be invoked using those argument, compute
6261 * the list of parameters that correspond to the list of arguments. Return the parameters that 6624 * the list of parameters that correspond to the list of arguments. Return the parameters that
6262 * correspond to the arguments, or `null` if no correspondence could be comput ed. 6625 * correspond to the arguments, or `null` if no correspondence could be comput ed.
6263 * 6626 *
6264 * @param reportError if `true` then compile-time error should be reported; if `false` 6627 * @param reportError if `true` then compile-time error should be reported; if `false`
6265 * then compile-time warning 6628 * then compile-time warning
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
6343 } 6706 }
6344 6707
6345 /** 6708 /**
6346 * Resolve the names in the given combinators in the scope of the given librar y. 6709 * Resolve the names in the given combinators in the scope of the given librar y.
6347 * 6710 *
6348 * @param library the library that defines the names 6711 * @param library the library that defines the names
6349 * @param combinators the combinators containing the names to be resolved 6712 * @param combinators the combinators containing the names to be resolved
6350 */ 6713 */
6351 void resolveCombinators(LibraryElement library, NodeList<Combinator> combinato rs) { 6714 void resolveCombinators(LibraryElement library, NodeList<Combinator> combinato rs) {
6352 if (library == null) { 6715 if (library == null) {
6716 //
6717 // The library will be null if the directive containing the combinators ha s a URI that is not
6718 // valid.
6719 //
6353 return; 6720 return;
6354 } 6721 }
6355 Namespace namespace = new NamespaceBuilder().createExportNamespace2(library) ; 6722 Namespace namespace = new NamespaceBuilder().createExportNamespace2(library) ;
6356 for (Combinator combinator in combinators) { 6723 for (Combinator combinator in combinators) {
6357 NodeList<SimpleIdentifier> names; 6724 NodeList<SimpleIdentifier> names;
6358 if (combinator is HideCombinator) { 6725 if (combinator is HideCombinator) {
6359 names = combinator.hiddenNames; 6726 names = combinator.hiddenNames;
6360 } else { 6727 } else {
6361 names = (combinator as ShowCombinator).shownNames; 6728 names = (combinator as ShowCombinator).shownNames;
6362 } 6729 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
6401 * @param target the target of the invocation ('e') 6768 * @param target the target of the invocation ('e')
6402 * @param targetType the type of the target 6769 * @param targetType the type of the target
6403 * @param methodName the name of the method being invoked ('m') 6770 * @param methodName the name of the method being invoked ('m')
6404 * @return the element being invoked 6771 * @return the element being invoked
6405 */ 6772 */
6406 Element resolveInvokedElement(Expression target, Type2 targetType, SimpleIdent ifier methodName) { 6773 Element resolveInvokedElement(Expression target, Type2 targetType, SimpleIdent ifier methodName) {
6407 if (targetType is InterfaceType) { 6774 if (targetType is InterfaceType) {
6408 InterfaceType classType = targetType; 6775 InterfaceType classType = targetType;
6409 Element element = lookUpMethod(target, classType, methodName.name); 6776 Element element = lookUpMethod(target, classType, methodName.name);
6410 if (element == null) { 6777 if (element == null) {
6778 //
6779 // If there's no method, then it's possible that 'm' is a getter that re turns a function.
6780 //
6411 element = lookUpGetter(target, classType, methodName.name); 6781 element = lookUpGetter(target, classType, methodName.name);
6412 } 6782 }
6413 return element; 6783 return element;
6414 } else if (target is SimpleIdentifier) { 6784 } else if (target is SimpleIdentifier) {
6415 Element targetElement = target.staticElement; 6785 Element targetElement = target.staticElement;
6416 if (targetElement is PrefixElement) { 6786 if (targetElement is PrefixElement) {
6787 //
6788 // Look to see whether the name of the method is really part of a prefix ed identifier for an
6789 // imported top-level function or top-level getter that returns a functi on.
6790 //
6417 String name = "${target.name}.${methodName}"; 6791 String name = "${target.name}.${methodName}";
6418 Identifier functionName = new ElementResolver_SyntheticIdentifier(name); 6792 Identifier functionName = new ElementResolver_SyntheticIdentifier(name);
6419 Element element = _resolver.nameScope.lookup(functionName, _definingLibr ary); 6793 Element element = _resolver.nameScope.lookup(functionName, _definingLibr ary);
6420 if (element != null) { 6794 if (element != null) {
6795 // TODO(brianwilkerson) This isn't a method invocation, it's a functio n invocation where
6796 // the function name is a prefixed identifier. Consider re-writing the AST.
6421 return element; 6797 return element;
6422 } 6798 }
6423 } 6799 }
6424 } 6800 }
6801 // TODO(brianwilkerson) Report this error.
6425 return null; 6802 return null;
6426 } 6803 }
6427 6804
6428 /** 6805 /**
6429 * Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the elemen t being invoked. If 6806 * Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the elemen t being invoked. If
6430 * the returned element is a method, then the method will be invoked. If the r eturned element is a 6807 * the returned element is a method, then the method will be invoked. If the r eturned element is a
6431 * getter, the getter will be invoked without arguments and the result of that invocation will 6808 * getter, the getter will be invoked without arguments and the result of that invocation will
6432 * then be invoked with the arguments. 6809 * then be invoked with the arguments.
6433 * 6810 *
6434 * @param methodName the name of the method being invoked ('m') 6811 * @param methodName the name of the method being invoked ('m')
6435 * @return the element being invoked 6812 * @return the element being invoked
6436 */ 6813 */
6437 Element resolveInvokedElement2(SimpleIdentifier methodName) { 6814 Element resolveInvokedElement2(SimpleIdentifier methodName) {
6815 //
6816 // Look first in the lexical scope.
6817 //
6438 Element element = _resolver.nameScope.lookup(methodName, _definingLibrary); 6818 Element element = _resolver.nameScope.lookup(methodName, _definingLibrary);
6439 if (element == null) { 6819 if (element == null) {
6820 //
6821 // If it isn't defined in the lexical scope, and the invocation is within a class, then look
6822 // in the inheritance scope.
6823 //
6440 ClassElement enclosingClass = _resolver.enclosingClass; 6824 ClassElement enclosingClass = _resolver.enclosingClass;
6441 if (enclosingClass != null) { 6825 if (enclosingClass != null) {
6442 InterfaceType enclosingType = enclosingClass.type; 6826 InterfaceType enclosingType = enclosingClass.type;
6443 element = lookUpMethod(null, enclosingType, methodName.name); 6827 element = lookUpMethod(null, enclosingType, methodName.name);
6444 if (element == null) { 6828 if (element == null) {
6829 //
6830 // If there's no method, then it's possible that 'm' is a getter that returns a function.
6831 //
6445 element = lookUpGetter(null, enclosingType, methodName.name); 6832 element = lookUpGetter(null, enclosingType, methodName.name);
6446 } 6833 }
6447 } 6834 }
6448 } 6835 }
6836 // TODO(brianwilkerson) Report this error.
6449 return element; 6837 return element;
6450 } 6838 }
6451 6839
6452 /** 6840 /**
6453 * Given that we are accessing a property of the given type with the given nam e, return the 6841 * Given that we are accessing a property of the given type with the given nam e, return the
6454 * element that represents the property. 6842 * element that represents the property.
6455 * 6843 *
6456 * @param target the target of the invocation ('e') 6844 * @param target the target of the invocation ('e')
6457 * @param targetType the type in which the search for the property should begi n 6845 * @param targetType the type in which the search for the property should begi n
6458 * @param propertyName the name of the property being accessed 6846 * @param propertyName the name of the property being accessed
(...skipping 11 matching lines...) Expand all
6470 memberElement = lookUpMethod(target, targetType, propertyName.name); 6858 memberElement = lookUpMethod(target, targetType, propertyName.name);
6471 } 6859 }
6472 return memberElement; 6860 return memberElement;
6473 } 6861 }
6474 6862
6475 void resolvePropertyAccess(Expression target, SimpleIdentifier propertyName) { 6863 void resolvePropertyAccess(Expression target, SimpleIdentifier propertyName) {
6476 Type2 staticType = getStaticType(target); 6864 Type2 staticType = getStaticType(target);
6477 Type2 propagatedType = getPropagatedType(target); 6865 Type2 propagatedType = getPropagatedType(target);
6478 Element staticElement = null; 6866 Element staticElement = null;
6479 Element propagatedElement = null; 6867 Element propagatedElement = null;
6868 //
6869 // If this property access is of the form 'C.m' where 'C' is a class, then w e don't call
6870 // resolveProperty(..) which walks up the class hierarchy, instead we just l ook for the
6871 // member in the type only.
6872 //
6480 ClassElementImpl typeReference = getTypeReference(target); 6873 ClassElementImpl typeReference = getTypeReference(target);
6481 if (typeReference != null) { 6874 if (typeReference != null) {
6482 staticElement = propagatedElement = resolveElement(typeReference, property Name); 6875 staticElement = propagatedElement = resolveElement(typeReference, property Name);
6483 } else { 6876 } else {
6484 staticElement = resolveProperty(target, staticType, propertyName); 6877 staticElement = resolveProperty(target, staticType, propertyName);
6485 propagatedElement = resolveProperty(target, propagatedType, propertyName); 6878 propagatedElement = resolveProperty(target, propagatedType, propertyName);
6486 } 6879 }
6880 // May be part of annotation, record property element only if exists.
6881 // Error was already reported in validateAnnotationElement().
6487 if (target.parent.parent is Annotation) { 6882 if (target.parent.parent is Annotation) {
6488 if (staticElement != null) { 6883 if (staticElement != null) {
6489 propertyName.staticElement = staticElement; 6884 propertyName.staticElement = staticElement;
6490 } 6885 }
6491 return; 6886 return;
6492 } 6887 }
6493 propertyName.staticElement = staticElement; 6888 propertyName.staticElement = staticElement;
6494 propertyName.propagatedElement = propagatedElement; 6889 propertyName.propagatedElement = propagatedElement;
6495 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticElement); 6890 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticElement);
6496 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedElement) : false; 6891 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedElement) : false;
6892 // If we are about to generate the hint (propagated version of this warning) , then check
6893 // that the member is not in a subtype of the propagated type.
6497 if (shouldReportMissingMember_propagated) { 6894 if (shouldReportMissingMember_propagated) {
6498 if (memberFoundInSubclass(propagatedType.element, propertyName.name, false , true)) { 6895 if (memberFoundInSubclass(propagatedType.element, propertyName.name, false , true)) {
6499 shouldReportMissingMember_propagated = false; 6896 shouldReportMissingMember_propagated = false;
6500 } 6897 }
6501 } 6898 }
6502 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) { 6899 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) {
6503 Element staticOrPropagatedEnclosingElt = shouldReportMissingMember_static ? staticType.element : propagatedType.element; 6900 Element staticOrPropagatedEnclosingElt = shouldReportMissingMember_static ? staticType.element : propagatedType.element;
6504 bool isStaticProperty = isStatic(staticOrPropagatedEnclosingElt); 6901 if (staticOrPropagatedEnclosingElt != null) {
6505 if (propertyName.inSetterContext()) { 6902 bool isStaticProperty = isStatic(staticOrPropagatedEnclosingElt);
6506 if (isStaticProperty) { 6903 if (propertyName.inSetterContext()) {
6507 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarnin gCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode; 6904 if (isStaticProperty) {
6508 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, errorCode, propertyName, [ 6905 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarn ingCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode;
6509 propertyName.name, 6906 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagate dEnclosingElt, errorCode, propertyName, [
6510 staticOrPropagatedEnclosingElt.displayName]); 6907 propertyName.name,
6908 staticOrPropagatedEnclosingElt.displayName]);
6909 } else {
6910 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticType WarningCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode;
6911 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagate dEnclosingElt, errorCode, propertyName, [
6912 propertyName.name,
6913 staticOrPropagatedEnclosingElt.displayName]);
6914 }
6915 } else if (propertyName.inGetterContext()) {
6916 if (isStaticProperty) {
6917 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarn ingCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode;
6918 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagate dEnclosingElt, errorCode, propertyName, [
6919 propertyName.name,
6920 staticOrPropagatedEnclosingElt.displayName]);
6921 } else {
6922 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticType WarningCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode;
6923 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagate dEnclosingElt, errorCode, propertyName, [
6924 propertyName.name,
6925 staticOrPropagatedEnclosingElt.displayName]);
6926 }
6511 } else { 6927 } else {
6512 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode; 6928 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName, [propertyName .name]);
6513 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, errorCode, propertyName, [
6514 propertyName.name,
6515 staticOrPropagatedEnclosingElt.displayName]);
6516 } 6929 }
6517 } else if (propertyName.inGetterContext()) {
6518 if (isStaticProperty) {
6519 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarnin gCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode;
6520 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, errorCode, propertyName, [
6521 propertyName.name,
6522 staticOrPropagatedEnclosingElt.displayName]);
6523 } else {
6524 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode;
6525 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, errorCode, propertyName, [
6526 propertyName.name,
6527 staticOrPropagatedEnclosingElt.displayName]);
6528 }
6529 } else {
6530 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedEnc losingElt, StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName, [propertyName.n ame]);
6531 } 6930 }
6532 } 6931 }
6533 } 6932 }
6534 6933
6535 /** 6934 /**
6536 * Resolve the given simple identifier if possible. Return the element to whic h it could be 6935 * Resolve the given simple identifier if possible. Return the element to whic h it could be
6537 * resolved, or `null` if it could not be resolved. This does not record the r esults of the 6936 * resolved, or `null` if it could not be resolved. This does not record the r esults of the
6538 * resolution. 6937 * resolution.
6539 * 6938 *
6540 * @param node the identifier to be resolved 6939 * @param node the identifier to be resolved
6541 * @return the element to which the identifier could be resolved 6940 * @return the element to which the identifier could be resolved
6542 */ 6941 */
6543 Element resolveSimpleIdentifier(SimpleIdentifier node) { 6942 Element resolveSimpleIdentifier(SimpleIdentifier node) {
6544 Element element = _resolver.nameScope.lookup(node, _definingLibrary); 6943 Element element = _resolver.nameScope.lookup(node, _definingLibrary);
6545 if (element is PropertyAccessorElement && node.inSetterContext()) { 6944 if (element is PropertyAccessorElement && node.inSetterContext()) {
6546 PropertyInducingElement variable = (element as PropertyAccessorElement).va riable; 6945 PropertyInducingElement variable = (element as PropertyAccessorElement).va riable;
6547 if (variable != null) { 6946 if (variable != null) {
6548 PropertyAccessorElement setter = variable.setter; 6947 PropertyAccessorElement setter = variable.setter;
6549 if (setter == null) { 6948 if (setter == null) {
6949 //
6950 // Check to see whether there might be a locally defined getter and an inherited setter.
6951 //
6550 ClassElement enclosingClass = _resolver.enclosingClass; 6952 ClassElement enclosingClass = _resolver.enclosingClass;
6551 if (enclosingClass != null) { 6953 if (enclosingClass != null) {
6552 setter = lookUpSetter(null, enclosingClass.type, node.name); 6954 setter = lookUpSetter(null, enclosingClass.type, node.name);
6553 } 6955 }
6554 } 6956 }
6555 if (setter != null) { 6957 if (setter != null) {
6556 element = setter; 6958 element = setter;
6557 } 6959 }
6558 } 6960 }
6559 } else if (element == null && node.inSetterContext()) { 6961 } else if (element == null && node.inSetterContext()) {
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after
6967 * @param baseFunctionType the function type that is being overridden 7369 * @param baseFunctionType the function type that is being overridden
6968 * @param memberName the name of the member, this is used to lookup the inheri tance path of the 7370 * @param memberName the name of the member, this is used to lookup the inheri tance path of the
6969 * override 7371 * override
6970 * @param definingType the type that is overriding the member 7372 * @param definingType the type that is overriding the member
6971 * @return the passed function type with any parameterized types substituted 7373 * @return the passed function type with any parameterized types substituted
6972 */ 7374 */
6973 FunctionType substituteTypeArgumentsInMemberFromInheritance(FunctionType baseF unctionType, String memberName, InterfaceType definingType) { 7375 FunctionType substituteTypeArgumentsInMemberFromInheritance(FunctionType baseF unctionType, String memberName, InterfaceType definingType) {
6974 if (baseFunctionType == null) { 7376 if (baseFunctionType == null) {
6975 return baseFunctionType; 7377 return baseFunctionType;
6976 } 7378 }
7379 // First, generate the path from the defining type to the overridden member
6977 Queue<InterfaceType> inheritancePath = new Queue<InterfaceType>(); 7380 Queue<InterfaceType> inheritancePath = new Queue<InterfaceType>();
6978 computeInheritancePath(inheritancePath, definingType, memberName); 7381 computeInheritancePath(inheritancePath, definingType, memberName);
6979 if (inheritancePath == null || inheritancePath.isEmpty) { 7382 if (inheritancePath == null || inheritancePath.isEmpty) {
7383 // TODO(jwren) log analysis engine error
6980 return baseFunctionType; 7384 return baseFunctionType;
6981 } 7385 }
6982 FunctionType functionTypeToReturn = baseFunctionType; 7386 FunctionType functionTypeToReturn = baseFunctionType;
7387 // loop backward through the list substituting as we go:
6983 while (!inheritancePath.isEmpty) { 7388 while (!inheritancePath.isEmpty) {
6984 InterfaceType lastType = inheritancePath.removeLast(); 7389 InterfaceType lastType = inheritancePath.removeLast();
6985 List<Type2> parameterTypes = lastType.element.type.typeArguments; 7390 List<Type2> parameterTypes = lastType.element.type.typeArguments;
6986 List<Type2> argumentTypes = lastType.typeArguments; 7391 List<Type2> argumentTypes = lastType.typeArguments;
6987 functionTypeToReturn = functionTypeToReturn.substitute2(argumentTypes, par ameterTypes); 7392 functionTypeToReturn = functionTypeToReturn.substitute2(argumentTypes, par ameterTypes);
6988 } 7393 }
6989 return functionTypeToReturn; 7394 return functionTypeToReturn;
6990 } 7395 }
6991 7396
6992 /** 7397 /**
(...skipping 12 matching lines...) Expand all
7005 if (resultMap != null) { 7410 if (resultMap != null) {
7006 return resultMap; 7411 return resultMap;
7007 } else { 7412 } else {
7008 resultMap = new MemberMap(); 7413 resultMap = new MemberMap();
7009 } 7414 }
7010 ClassElement superclassElt = null; 7415 ClassElement superclassElt = null;
7011 InterfaceType supertype = classElt.supertype; 7416 InterfaceType supertype = classElt.supertype;
7012 if (supertype != null) { 7417 if (supertype != null) {
7013 superclassElt = supertype.element; 7418 superclassElt = supertype.element;
7014 } else { 7419 } else {
7420 // classElt is Object
7015 _classLookup[classElt] = resultMap; 7421 _classLookup[classElt] = resultMap;
7016 return resultMap; 7422 return resultMap;
7017 } 7423 }
7018 if (superclassElt != null) { 7424 if (superclassElt != null) {
7019 if (!visitedClasses.contains(superclassElt)) { 7425 if (!visitedClasses.contains(superclassElt)) {
7020 visitedClasses.add(classElt); 7426 visitedClasses.add(classElt);
7021 resultMap = new MemberMap.con2(computeClassChainLookupMap(superclassElt, visitedClasses)); 7427 resultMap = new MemberMap.con2(computeClassChainLookupMap(superclassElt, visitedClasses));
7022 } else { 7428 } else {
7429 // This case happens only when the superclass was previously visited and not in the lookup,
7430 // meaning this is meant to shorten the compute for recursive cases.
7023 _classLookup[superclassElt] = resultMap; 7431 _classLookup[superclassElt] = resultMap;
7024 return resultMap; 7432 return resultMap;
7025 } 7433 }
7434 //
7435 // Substitute the supertypes down the hierarchy
7436 //
7026 substituteTypeParametersDownHierarchy(supertype, resultMap); 7437 substituteTypeParametersDownHierarchy(supertype, resultMap);
7438 //
7439 // Include the members from the superclass in the resultMap
7440 //
7027 recordMapWithClassMembers(resultMap, supertype); 7441 recordMapWithClassMembers(resultMap, supertype);
7028 } 7442 }
7443 //
7444 // Include the members from the mixins in the resultMap
7445 //
7029 List<InterfaceType> mixins = classElt.mixins; 7446 List<InterfaceType> mixins = classElt.mixins;
7030 for (int i = mixins.length - 1; i >= 0; i--) { 7447 for (int i = mixins.length - 1; i >= 0; i--) {
7031 recordMapWithClassMembers(resultMap, mixins[i]); 7448 recordMapWithClassMembers(resultMap, mixins[i]);
7032 } 7449 }
7033 _classLookup[classElt] = resultMap; 7450 _classLookup[classElt] = resultMap;
7034 return resultMap; 7451 return resultMap;
7035 } 7452 }
7036 7453
7037 /** 7454 /**
7038 * Compute and return the inheritance path given the context of a type and a m ember that is 7455 * Compute and return the inheritance path given the context of a type and a m ember that is
7039 * overridden in the inheritance path (for which the type is in the path). 7456 * overridden in the inheritance path (for which the type is in the path).
7040 * 7457 *
7041 * @param chain the inheritance path that is built up as this method calls its elf recursively, 7458 * @param chain the inheritance path that is built up as this method calls its elf recursively,
7042 * when this method is called an empty [LinkedList] should be provide d 7459 * when this method is called an empty [LinkedList] should be provide d
7043 * @param currentType the current type in the inheritance path 7460 * @param currentType the current type in the inheritance path
7044 * @param memberName the name of the member that is being looked up the inheri tance path 7461 * @param memberName the name of the member that is being looked up the inheri tance path
7045 */ 7462 */
7046 void computeInheritancePath(Queue<InterfaceType> chain, InterfaceType currentT ype, String memberName) { 7463 void computeInheritancePath(Queue<InterfaceType> chain, InterfaceType currentT ype, String memberName) {
7464 // TODO (jwren) create a public version of this method which doesn't require the initial chain
7465 // to be provided, then provided tests for this functionality in Inheritance ManagerTest
7047 chain.add(currentType); 7466 chain.add(currentType);
7048 ClassElement classElt = currentType.element; 7467 ClassElement classElt = currentType.element;
7049 InterfaceType supertype = classElt.supertype; 7468 InterfaceType supertype = classElt.supertype;
7469 // Base case- reached Object
7050 if (supertype == null) { 7470 if (supertype == null) {
7471 // Looked up the chain all the way to Object, return null.
7472 // This should never happen.
7051 return; 7473 return;
7052 } 7474 }
7475 // If we are done, return the chain
7476 // We are not done if this is the first recursive call on this method.
7053 if (chain.length != 1) { 7477 if (chain.length != 1) {
7478 // We are done however if the member is in this classElt
7054 if (lookupMemberInClass(classElt, memberName) != null) { 7479 if (lookupMemberInClass(classElt, memberName) != null) {
7055 return; 7480 return;
7056 } 7481 }
7057 } 7482 }
7483 // Mixins- note that mixins call lookupMemberInClass, not lookupMember
7058 List<InterfaceType> mixins = classElt.mixins; 7484 List<InterfaceType> mixins = classElt.mixins;
7059 for (int i = mixins.length - 1; i >= 0; i--) { 7485 for (int i = mixins.length - 1; i >= 0; i--) {
7060 ClassElement mixinElement = mixins[i].element; 7486 ClassElement mixinElement = mixins[i].element;
7061 if (mixinElement != null) { 7487 if (mixinElement != null) {
7062 ExecutableElement elt = lookupMemberInClass(mixinElement, memberName); 7488 ExecutableElement elt = lookupMemberInClass(mixinElement, memberName);
7063 if (elt != null) { 7489 if (elt != null) {
7490 // this is equivalent (but faster than) calling this method recursivel y
7491 // (return computeInheritancePath(chain, mixins[i], memberName);)
7064 chain.add(mixins[i]); 7492 chain.add(mixins[i]);
7065 return; 7493 return;
7066 } 7494 }
7067 } 7495 }
7068 } 7496 }
7497 // Superclass
7069 ClassElement superclassElt = supertype.element; 7498 ClassElement superclassElt = supertype.element;
7070 if (lookupMember(superclassElt, memberName) != null) { 7499 if (lookupMember(superclassElt, memberName) != null) {
7071 computeInheritancePath(chain, supertype, memberName); 7500 computeInheritancePath(chain, supertype, memberName);
7072 return; 7501 return;
7073 } 7502 }
7503 // Interfaces
7074 List<InterfaceType> interfaces = classElt.interfaces; 7504 List<InterfaceType> interfaces = classElt.interfaces;
7075 for (InterfaceType interfaceType in interfaces) { 7505 for (InterfaceType interfaceType in interfaces) {
7076 ClassElement interfaceElement = interfaceType.element; 7506 ClassElement interfaceElement = interfaceType.element;
7077 if (interfaceElement != null && lookupMember(interfaceElement, memberName) != null) { 7507 if (interfaceElement != null && lookupMember(interfaceElement, memberName) != null) {
7078 computeInheritancePath(chain, interfaceType, memberName); 7508 computeInheritancePath(chain, interfaceType, memberName);
7079 return; 7509 return;
7080 } 7510 }
7081 } 7511 }
7082 } 7512 }
7083 7513
(...skipping 12 matching lines...) Expand all
7096 MemberMap resultMap = _interfaceLookup[classElt]; 7526 MemberMap resultMap = _interfaceLookup[classElt];
7097 if (resultMap != null) { 7527 if (resultMap != null) {
7098 return resultMap; 7528 return resultMap;
7099 } else { 7529 } else {
7100 resultMap = new MemberMap(); 7530 resultMap = new MemberMap();
7101 } 7531 }
7102 InterfaceType supertype = classElt.supertype; 7532 InterfaceType supertype = classElt.supertype;
7103 ClassElement superclassElement = supertype != null ? supertype.element : nul l; 7533 ClassElement superclassElement = supertype != null ? supertype.element : nul l;
7104 List<InterfaceType> mixins = classElt.mixins; 7534 List<InterfaceType> mixins = classElt.mixins;
7105 List<InterfaceType> interfaces = classElt.interfaces; 7535 List<InterfaceType> interfaces = classElt.interfaces;
7536 // Recursively collect the list of mappings from all of the interface types
7106 List<MemberMap> lookupMaps = new List<MemberMap>(); 7537 List<MemberMap> lookupMaps = new List<MemberMap>();
7538 // Superclass element
7107 if (superclassElement != null) { 7539 if (superclassElement != null) {
7108 if (!visitedInterfaces.contains(superclassElement)) { 7540 if (!visitedInterfaces.contains(superclassElement)) {
7109 try { 7541 try {
7110 visitedInterfaces.add(superclassElement); 7542 visitedInterfaces.add(superclassElement);
7543 //
7544 // Recursively compute the map for the supertype.
7545 //
7111 MemberMap map = computeInterfaceLookupMap(superclassElement, visitedIn terfaces); 7546 MemberMap map = computeInterfaceLookupMap(superclassElement, visitedIn terfaces);
7112 map = new MemberMap.con2(map); 7547 map = new MemberMap.con2(map);
7548 //
7549 // Substitute the supertypes down the hierarchy
7550 //
7113 substituteTypeParametersDownHierarchy(supertype, map); 7551 substituteTypeParametersDownHierarchy(supertype, map);
7552 //
7553 // Add any members from the supertype into the map as well.
7554 //
7114 recordMapWithClassMembers(map, supertype); 7555 recordMapWithClassMembers(map, supertype);
7115 lookupMaps.add(map); 7556 lookupMaps.add(map);
7116 } finally { 7557 } finally {
7117 visitedInterfaces.remove(superclassElement); 7558 visitedInterfaces.remove(superclassElement);
7118 } 7559 }
7119 } else { 7560 } else {
7120 MemberMap map = _interfaceLookup[classElt]; 7561 MemberMap map = _interfaceLookup[classElt];
7121 if (map != null) { 7562 if (map != null) {
7122 lookupMaps.add(map); 7563 lookupMaps.add(map);
7123 } else { 7564 } else {
7124 _interfaceLookup[superclassElement] = resultMap; 7565 _interfaceLookup[superclassElement] = resultMap;
7125 return resultMap; 7566 return resultMap;
7126 } 7567 }
7127 } 7568 }
7128 } 7569 }
7570 // Mixin elements
7129 for (InterfaceType mixinType in mixins) { 7571 for (InterfaceType mixinType in mixins) {
7130 MemberMap mapWithMixinMembers = new MemberMap(); 7572 MemberMap mapWithMixinMembers = new MemberMap();
7131 recordMapWithClassMembers(mapWithMixinMembers, mixinType); 7573 recordMapWithClassMembers(mapWithMixinMembers, mixinType);
7132 lookupMaps.add(mapWithMixinMembers); 7574 lookupMaps.add(mapWithMixinMembers);
7133 } 7575 }
7576 // Interface elements
7134 for (InterfaceType interfaceType in interfaces) { 7577 for (InterfaceType interfaceType in interfaces) {
7135 ClassElement interfaceElement = interfaceType.element; 7578 ClassElement interfaceElement = interfaceType.element;
7136 if (interfaceElement != null) { 7579 if (interfaceElement != null) {
7137 if (!visitedInterfaces.contains(interfaceElement)) { 7580 if (!visitedInterfaces.contains(interfaceElement)) {
7138 try { 7581 try {
7139 visitedInterfaces.add(interfaceElement); 7582 visitedInterfaces.add(interfaceElement);
7583 //
7584 // Recursively compute the map for the interfaces.
7585 //
7140 MemberMap map = computeInterfaceLookupMap(interfaceElement, visitedI nterfaces); 7586 MemberMap map = computeInterfaceLookupMap(interfaceElement, visitedI nterfaces);
7141 map = new MemberMap.con2(map); 7587 map = new MemberMap.con2(map);
7588 //
7589 // Substitute the supertypes down the hierarchy
7590 //
7142 substituteTypeParametersDownHierarchy(interfaceType, map); 7591 substituteTypeParametersDownHierarchy(interfaceType, map);
7592 //
7593 // And add any members from the interface into the map as well.
7594 //
7143 recordMapWithClassMembers(map, interfaceType); 7595 recordMapWithClassMembers(map, interfaceType);
7144 lookupMaps.add(map); 7596 lookupMaps.add(map);
7145 } finally { 7597 } finally {
7146 visitedInterfaces.remove(interfaceElement); 7598 visitedInterfaces.remove(interfaceElement);
7147 } 7599 }
7148 } else { 7600 } else {
7149 MemberMap map = _interfaceLookup[classElt]; 7601 MemberMap map = _interfaceLookup[classElt];
7150 if (map != null) { 7602 if (map != null) {
7151 lookupMaps.add(map); 7603 lookupMaps.add(map);
7152 } else { 7604 } else {
7153 _interfaceLookup[interfaceElement] = resultMap; 7605 _interfaceLookup[interfaceElement] = resultMap;
7154 return resultMap; 7606 return resultMap;
7155 } 7607 }
7156 } 7608 }
7157 } 7609 }
7158 } 7610 }
7159 if (lookupMaps.length == 0) { 7611 if (lookupMaps.length == 0) {
7160 _interfaceLookup[classElt] = resultMap; 7612 _interfaceLookup[classElt] = resultMap;
7161 return resultMap; 7613 return resultMap;
7162 } 7614 }
7615 //
7616 // Union all of the maps together, grouping the ExecutableElements into sets .
7617 //
7163 Map<String, Set<ExecutableElement>> unionMap = new Map<String, Set<Executabl eElement>>(); 7618 Map<String, Set<ExecutableElement>> unionMap = new Map<String, Set<Executabl eElement>>();
7164 for (MemberMap lookupMap in lookupMaps) { 7619 for (MemberMap lookupMap in lookupMaps) {
7165 for (int i = 0; i < lookupMap.size; i++) { 7620 for (int i = 0; i < lookupMap.size; i++) {
7166 String key = lookupMap.getKey(i); 7621 String key = lookupMap.getKey(i);
7167 if (key == null) { 7622 if (key == null) {
7168 break; 7623 break;
7169 } 7624 }
7170 Set<ExecutableElement> set = unionMap[key]; 7625 Set<ExecutableElement> set = unionMap[key];
7171 if (set == null) { 7626 if (set == null) {
7172 set = new Set<ExecutableElement>(); 7627 set = new Set<ExecutableElement>();
7173 unionMap[key] = set; 7628 unionMap[key] = set;
7174 } 7629 }
7175 set.add(lookupMap.getValue(i)); 7630 set.add(lookupMap.getValue(i));
7176 } 7631 }
7177 } 7632 }
7633 //
7634 // Loop through the entries in the union map, adding them to the resultMap a ppropriately.
7635 //
7178 for (MapEntry<String, Set<ExecutableElement>> entry in getMapEntrySet(unionM ap)) { 7636 for (MapEntry<String, Set<ExecutableElement>> entry in getMapEntrySet(unionM ap)) {
7179 String key = entry.getKey(); 7637 String key = entry.getKey();
7180 Set<ExecutableElement> set = entry.getValue(); 7638 Set<ExecutableElement> set = entry.getValue();
7181 int numOfEltsWithMatchingNames = set.length; 7639 int numOfEltsWithMatchingNames = set.length;
7182 if (numOfEltsWithMatchingNames == 1) { 7640 if (numOfEltsWithMatchingNames == 1) {
7183 resultMap.put(key, new JavaIterator(set).next()); 7641 resultMap.put(key, new JavaIterator(set).next());
7184 } else { 7642 } else {
7185 bool allMethods = true; 7643 bool allMethods = true;
7186 bool allSetters = true; 7644 bool allSetters = true;
7187 bool allGetters = true; 7645 bool allGetters = true;
7188 for (ExecutableElement executableElement in set) { 7646 for (ExecutableElement executableElement in set) {
7189 if (executableElement is PropertyAccessorElement) { 7647 if (executableElement is PropertyAccessorElement) {
7190 allMethods = false; 7648 allMethods = false;
7191 if (executableElement.isSetter) { 7649 if (executableElement.isSetter) {
7192 allGetters = false; 7650 allGetters = false;
7193 } else { 7651 } else {
7194 allSetters = false; 7652 allSetters = false;
7195 } 7653 }
7196 } else { 7654 } else {
7197 allGetters = false; 7655 allGetters = false;
7198 allSetters = false; 7656 allSetters = false;
7199 } 7657 }
7200 } 7658 }
7201 if (allMethods || allGetters || allSetters) { 7659 if (allMethods || allGetters || allSetters) {
7660 // Compute the element whose type is the subtype of all of the other t ypes.
7202 List<ExecutableElement> elements = new List.from(set); 7661 List<ExecutableElement> elements = new List.from(set);
7203 List<FunctionType> executableElementTypes = new List<FunctionType>(num OfEltsWithMatchingNames); 7662 List<FunctionType> executableElementTypes = new List<FunctionType>(num OfEltsWithMatchingNames);
7204 for (int i = 0; i < numOfEltsWithMatchingNames; i++) { 7663 for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
7205 executableElementTypes[i] = elements[i].type; 7664 executableElementTypes[i] = elements[i].type;
7206 } 7665 }
7207 bool foundSubtypeOfAllTypes = false; 7666 bool foundSubtypeOfAllTypes = false;
7208 for (int i = 0; i < numOfEltsWithMatchingNames; i++) { 7667 for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
7209 FunctionType subtype = executableElementTypes[i]; 7668 FunctionType subtype = executableElementTypes[i];
7210 if (subtype == null) { 7669 if (subtype == null) {
7211 continue; 7670 continue;
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
7691 Source librarySource = library.librarySource; 8150 Source librarySource = library.librarySource;
7692 CompilationUnit definingCompilationUnit = library.definingCompilationUnit; 8151 CompilationUnit definingCompilationUnit = library.definingCompilationUnit;
7693 CompilationUnitElementImpl definingCompilationUnitElement = builder.buildCom pilationUnit(librarySource, definingCompilationUnit); 8152 CompilationUnitElementImpl definingCompilationUnitElement = builder.buildCom pilationUnit(librarySource, definingCompilationUnit);
7694 NodeList<Directive> directives = definingCompilationUnit.directives; 8153 NodeList<Directive> directives = definingCompilationUnit.directives;
7695 LibraryIdentifier libraryNameNode = null; 8154 LibraryIdentifier libraryNameNode = null;
7696 bool hasPartDirective = false; 8155 bool hasPartDirective = false;
7697 FunctionElement entryPoint = findEntryPoint(definingCompilationUnitElement); 8156 FunctionElement entryPoint = findEntryPoint(definingCompilationUnitElement);
7698 List<Directive> directivesToResolve = new List<Directive>(); 8157 List<Directive> directivesToResolve = new List<Directive>();
7699 List<CompilationUnitElementImpl> sourcedCompilationUnits = new List<Compilat ionUnitElementImpl>(); 8158 List<CompilationUnitElementImpl> sourcedCompilationUnits = new List<Compilat ionUnitElementImpl>();
7700 for (Directive directive in directives) { 8159 for (Directive directive in directives) {
8160 //
8161 // We do not build the elements representing the import and export directi ves at this point.
8162 // That is not done until we get to LibraryResolver.buildDirectiveModels() because we need the
8163 // LibraryElements for the referenced libraries, which might not exist at this point (due to
8164 // the possibility of circular references).
8165 //
7701 if (directive is LibraryDirective) { 8166 if (directive is LibraryDirective) {
7702 if (libraryNameNode == null) { 8167 if (libraryNameNode == null) {
7703 libraryNameNode = directive.name; 8168 libraryNameNode = directive.name;
7704 directivesToResolve.add(directive); 8169 directivesToResolve.add(directive);
7705 } 8170 }
7706 } else if (directive is PartDirective) { 8171 } else if (directive is PartDirective) {
7707 PartDirective partDirective = directive; 8172 PartDirective partDirective = directive;
7708 StringLiteral partUri = partDirective.uri; 8173 StringLiteral partUri = partDirective.uri;
7709 Source partSource = library.getSource(partDirective); 8174 Source partSource = library.getSource(partDirective);
7710 if (partSource != null && partSource.exists()) { 8175 if (partSource != null && partSource.exists()) {
7711 hasPartDirective = true; 8176 hasPartDirective = true;
7712 CompilationUnitElementImpl part = builder.buildCompilationUnit(partSou rce, library.getAST(partSource)); 8177 CompilationUnitElementImpl part = builder.buildCompilationUnit(partSou rce, library.getAST(partSource));
7713 part.uri = library.getUri(partDirective); 8178 part.uri = library.getUri(partDirective);
8179 //
8180 // Validate that the part contains a part-of directive with the same n ame as the library.
8181 //
7714 String partLibraryName = getPartLibraryName(library, partSource, direc tivesToResolve); 8182 String partLibraryName = getPartLibraryName(library, partSource, direc tivesToResolve);
7715 if (partLibraryName == null) { 8183 if (partLibraryName == null) {
7716 _errorListener.onError(new AnalysisError.con2(librarySource, partUri .offset, partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, [partUri.toSourc e()])); 8184 _errorListener.onError(new AnalysisError.con2(librarySource, partUri .offset, partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, [partUri.toSourc e()]));
7717 } else if (libraryNameNode == null) { 8185 } else if (libraryNameNode == null) {
7718 } else if (libraryNameNode.name != partLibraryName) { 8186 } else if (libraryNameNode.name != partLibraryName) {
7719 _errorListener.onError(new AnalysisError.con2(librarySource, partUri .offset, partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [libraryNa meNode.name, partLibraryName])); 8187 _errorListener.onError(new AnalysisError.con2(librarySource, partUri .offset, partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [libraryNa meNode.name, partLibraryName]));
7720 } 8188 }
7721 if (entryPoint == null) { 8189 if (entryPoint == null) {
7722 entryPoint = findEntryPoint(part); 8190 entryPoint = findEntryPoint(part);
7723 } 8191 }
7724 directive.element = part; 8192 directive.element = part;
7725 sourcedCompilationUnits.add(part); 8193 sourcedCompilationUnits.add(part);
7726 } 8194 }
7727 } 8195 }
7728 } 8196 }
7729 if (hasPartDirective && libraryNameNode == null) { 8197 if (hasPartDirective && libraryNameNode == null) {
7730 _errorListener.onError(new AnalysisError.con1(librarySource, ResolverError Code.MISSING_LIBRARY_DIRECTIVE_WITH_PART, [])); 8198 _errorListener.onError(new AnalysisError.con1(librarySource, ResolverError Code.MISSING_LIBRARY_DIRECTIVE_WITH_PART, []));
7731 } 8199 }
8200 //
8201 // Create and populate the library element.
8202 //
7732 LibraryElementImpl libraryElement = new LibraryElementImpl(_analysisContext, libraryNameNode); 8203 LibraryElementImpl libraryElement = new LibraryElementImpl(_analysisContext, libraryNameNode);
7733 libraryElement.definingCompilationUnit = definingCompilationUnitElement; 8204 libraryElement.definingCompilationUnit = definingCompilationUnitElement;
7734 if (entryPoint != null) { 8205 if (entryPoint != null) {
7735 libraryElement.entryPoint = entryPoint; 8206 libraryElement.entryPoint = entryPoint;
7736 } 8207 }
7737 int sourcedUnitCount = sourcedCompilationUnits.length; 8208 int sourcedUnitCount = sourcedCompilationUnits.length;
7738 libraryElement.parts = new List.from(sourcedCompilationUnits); 8209 libraryElement.parts = new List.from(sourcedCompilationUnits);
7739 for (Directive directive in directivesToResolve) { 8210 for (Directive directive in directivesToResolve) {
7740 directive.element = libraryElement; 8211 directive.element = libraryElement;
7741 } 8212 }
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
7915 * @param unit the compilation unit representing the embedded library 8386 * @param unit the compilation unit representing the embedded library
7916 * @param fullAnalysis `true` if a full analysis should be performed 8387 * @param fullAnalysis `true` if a full analysis should be performed
7917 * @return the element representing the resolved library 8388 * @return the element representing the resolved library
7918 * @throws AnalysisException if the library could not be resolved for some rea son 8389 * @throws AnalysisException if the library could not be resolved for some rea son
7919 */ 8390 */
7920 LibraryElement resolveEmbeddedLibrary(Source librarySource, int modificationSt amp, CompilationUnit unit, bool fullAnalysis) { 8391 LibraryElement resolveEmbeddedLibrary(Source librarySource, int modificationSt amp, CompilationUnit unit, bool fullAnalysis) {
7921 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.LibraryResolver.resolveEmbeddedLibrary"); 8392 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.LibraryResolver.resolveEmbeddedLibrary");
7922 try { 8393 try {
7923 instrumentation.metric("fullAnalysis", fullAnalysis); 8394 instrumentation.metric("fullAnalysis", fullAnalysis);
7924 instrumentation.data3("fullName", librarySource.fullName); 8395 instrumentation.data3("fullName", librarySource.fullName);
8396 //
8397 // Create the objects representing the library being resolved and the core library.
8398 //
7925 Library targetLibrary = createLibrary2(librarySource, modificationStamp, u nit); 8399 Library targetLibrary = createLibrary2(librarySource, modificationStamp, u nit);
7926 _coreLibrary = _libraryMap[_coreLibrarySource]; 8400 _coreLibrary = _libraryMap[_coreLibrarySource];
7927 if (_coreLibrary == null) { 8401 if (_coreLibrary == null) {
8402 // This will be true unless the library being analyzed is the core libra ry.
7928 _coreLibrary = createLibrary(_coreLibrarySource); 8403 _coreLibrary = createLibrary(_coreLibrarySource);
7929 } 8404 }
7930 instrumentation.metric3("createLibrary", "complete"); 8405 instrumentation.metric3("createLibrary", "complete");
8406 //
8407 // Compute the set of libraries that need to be resolved together.
8408 //
7931 computeLibraryDependencies2(targetLibrary, unit); 8409 computeLibraryDependencies2(targetLibrary, unit);
7932 _librariesInCycles = computeLibrariesInCycles(targetLibrary); 8410 _librariesInCycles = computeLibrariesInCycles(targetLibrary);
8411 //
8412 // Build the element models representing the libraries being resolved. Thi s is done in three
8413 // steps:
8414 //
8415 // 1. Build the basic element models without making any connections betwee n elements other than
8416 // the basic parent/child relationships. This includes building the ele ments representing the
8417 // libraries.
8418 // 2. Build the elements for the import and export directives. This requir es that we have the
8419 // elements built for the referenced libraries, but because of the poss ibility of circular
8420 // references needs to happen after all of the library elements have be en created.
8421 // 3. Build the rest of the type model by connecting superclasses, mixins, and interfaces. This
8422 // requires that we be able to compute the names visible in the librari es being resolved,
8423 // which in turn requires that we have resolved the import directives.
8424 //
7933 buildElementModels(); 8425 buildElementModels();
7934 instrumentation.metric3("buildElementModels", "complete"); 8426 instrumentation.metric3("buildElementModels", "complete");
7935 LibraryElement coreElement = _coreLibrary.libraryElement; 8427 LibraryElement coreElement = _coreLibrary.libraryElement;
7936 if (coreElement == null) { 8428 if (coreElement == null) {
7937 throw new AnalysisException.con1("Could not resolve dart:core"); 8429 throw new AnalysisException.con1("Could not resolve dart:core");
7938 } 8430 }
7939 buildDirectiveModels(); 8431 buildDirectiveModels();
7940 instrumentation.metric3("buildDirectiveModels", "complete"); 8432 instrumentation.metric3("buildDirectiveModels", "complete");
7941 _typeProvider = new TypeProviderImpl(coreElement); 8433 _typeProvider = new TypeProviderImpl(coreElement);
7942 buildTypeHierarchies(); 8434 buildTypeHierarchies();
7943 instrumentation.metric3("buildTypeHierarchies", "complete"); 8435 instrumentation.metric3("buildTypeHierarchies", "complete");
8436 //
8437 // Perform resolution and type analysis.
8438 //
8439 // TODO(brianwilkerson) Decide whether we want to resolve all of the libra ries or whether we
8440 // want to only resolve the target library. The advantage to resolving eve rything is that we
8441 // have already done part of the work so we'll avoid duplicated effort. Th e disadvantage of
8442 // resolving everything is that we might do extra work that we don't reall y care about. Another
8443 // possibility is to add a parameter to this method and punt the decision to the clients.
8444 //
8445 //if (analyzeAll) {
7944 resolveReferencesAndTypes(); 8446 resolveReferencesAndTypes();
7945 instrumentation.metric3("resolveReferencesAndTypes", "complete"); 8447 instrumentation.metric3("resolveReferencesAndTypes", "complete");
8448 //} else {
8449 // resolveReferencesAndTypes(targetLibrary);
8450 //}
7946 performConstantEvaluation(); 8451 performConstantEvaluation();
7947 instrumentation.metric3("performConstantEvaluation", "complete"); 8452 instrumentation.metric3("performConstantEvaluation", "complete");
7948 return targetLibrary.libraryElement; 8453 return targetLibrary.libraryElement;
7949 } finally { 8454 } finally {
7950 instrumentation.log(); 8455 instrumentation.log();
7951 } 8456 }
7952 } 8457 }
7953 8458
7954 /** 8459 /**
7955 * Resolve the library specified by the given source in the given context. 8460 * Resolve the library specified by the given source in the given context.
7956 * 8461 *
7957 * Note that because Dart allows circular imports between libraries, it is pos sible that more than 8462 * Note that because Dart allows circular imports between libraries, it is pos sible that more than
7958 * one library will need to be resolved. In such cases the error listener can receive errors from 8463 * one library will need to be resolved. In such cases the error listener can receive errors from
7959 * multiple libraries. 8464 * multiple libraries.
7960 * 8465 *
7961 * @param librarySource the source specifying the defining compilation unit of the library to be 8466 * @param librarySource the source specifying the defining compilation unit of the library to be
7962 * resolved 8467 * resolved
7963 * @param fullAnalysis `true` if a full analysis should be performed 8468 * @param fullAnalysis `true` if a full analysis should be performed
7964 * @return the element representing the resolved library 8469 * @return the element representing the resolved library
7965 * @throws AnalysisException if the library could not be resolved for some rea son 8470 * @throws AnalysisException if the library could not be resolved for some rea son
7966 */ 8471 */
7967 LibraryElement resolveLibrary(Source librarySource, bool fullAnalysis) { 8472 LibraryElement resolveLibrary(Source librarySource, bool fullAnalysis) {
7968 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.LibraryResolver.resolveLibrary"); 8473 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.LibraryResolver.resolveLibrary");
7969 try { 8474 try {
7970 instrumentation.metric("fullAnalysis", fullAnalysis); 8475 instrumentation.metric("fullAnalysis", fullAnalysis);
7971 instrumentation.data3("fullName", librarySource.fullName); 8476 instrumentation.data3("fullName", librarySource.fullName);
8477 //
8478 // Create the objects representing the library being resolved and the core library.
8479 //
7972 Library targetLibrary = createLibrary(librarySource); 8480 Library targetLibrary = createLibrary(librarySource);
7973 _coreLibrary = _libraryMap[_coreLibrarySource]; 8481 _coreLibrary = _libraryMap[_coreLibrarySource];
7974 if (_coreLibrary == null) { 8482 if (_coreLibrary == null) {
8483 // This will be true unless the library being analyzed is the core libra ry.
7975 _coreLibrary = createLibraryOrNull(_coreLibrarySource); 8484 _coreLibrary = createLibraryOrNull(_coreLibrarySource);
7976 if (_coreLibrary == null) { 8485 if (_coreLibrary == null) {
7977 throw new AnalysisException.con1("Core library does not exist"); 8486 throw new AnalysisException.con1("Core library does not exist");
7978 } 8487 }
7979 } 8488 }
7980 instrumentation.metric3("createLibrary", "complete"); 8489 instrumentation.metric3("createLibrary", "complete");
8490 //
8491 // Compute the set of libraries that need to be resolved together.
8492 //
7981 computeLibraryDependencies(targetLibrary); 8493 computeLibraryDependencies(targetLibrary);
7982 _librariesInCycles = computeLibrariesInCycles(targetLibrary); 8494 _librariesInCycles = computeLibrariesInCycles(targetLibrary);
8495 //
8496 // Build the element models representing the libraries being resolved. Thi s is done in three
8497 // steps:
8498 //
8499 // 1. Build the basic element models without making any connections betwee n elements other than
8500 // the basic parent/child relationships. This includes building the ele ments representing the
8501 // libraries.
8502 // 2. Build the elements for the import and export directives. This requir es that we have the
8503 // elements built for the referenced libraries, but because of the poss ibility of circular
8504 // references needs to happen after all of the library elements have be en created.
8505 // 3. Build the rest of the type model by connecting superclasses, mixins, and interfaces. This
8506 // requires that we be able to compute the names visible in the librari es being resolved,
8507 // which in turn requires that we have resolved the import directives.
8508 //
7983 buildElementModels(); 8509 buildElementModels();
7984 instrumentation.metric3("buildElementModels", "complete"); 8510 instrumentation.metric3("buildElementModels", "complete");
7985 LibraryElement coreElement = _coreLibrary.libraryElement; 8511 LibraryElement coreElement = _coreLibrary.libraryElement;
7986 if (coreElement == null) { 8512 if (coreElement == null) {
7987 throw new AnalysisException.con1("Could not resolve dart:core"); 8513 throw new AnalysisException.con1("Could not resolve dart:core");
7988 } 8514 }
7989 buildDirectiveModels(); 8515 buildDirectiveModels();
7990 instrumentation.metric3("buildDirectiveModels", "complete"); 8516 instrumentation.metric3("buildDirectiveModels", "complete");
7991 _typeProvider = new TypeProviderImpl(coreElement); 8517 _typeProvider = new TypeProviderImpl(coreElement);
7992 buildTypeHierarchies(); 8518 buildTypeHierarchies();
7993 instrumentation.metric3("buildTypeHierarchies", "complete"); 8519 instrumentation.metric3("buildTypeHierarchies", "complete");
8520 //
8521 // Perform resolution and type analysis.
8522 //
8523 // TODO(brianwilkerson) Decide whether we want to resolve all of the libra ries or whether we
8524 // want to only resolve the target library. The advantage to resolving eve rything is that we
8525 // have already done part of the work so we'll avoid duplicated effort. Th e disadvantage of
8526 // resolving everything is that we might do extra work that we don't reall y care about. Another
8527 // possibility is to add a parameter to this method and punt the decision to the clients.
8528 //
8529 //if (analyzeAll) {
7994 resolveReferencesAndTypes(); 8530 resolveReferencesAndTypes();
7995 instrumentation.metric3("resolveReferencesAndTypes", "complete"); 8531 instrumentation.metric3("resolveReferencesAndTypes", "complete");
8532 //} else {
8533 // resolveReferencesAndTypes(targetLibrary);
8534 //}
7996 performConstantEvaluation(); 8535 performConstantEvaluation();
7997 instrumentation.metric3("performConstantEvaluation", "complete"); 8536 instrumentation.metric3("performConstantEvaluation", "complete");
7998 instrumentation.metric2("librariesInCycles", _librariesInCycles.length); 8537 instrumentation.metric2("librariesInCycles", _librariesInCycles.length);
7999 for (Library lib in _librariesInCycles) { 8538 for (Library lib in _librariesInCycles) {
8000 instrumentation.metric2("librariesInCycles-CompilationUnitSources-Size", lib.compilationUnitSources.length); 8539 instrumentation.metric2("librariesInCycles-CompilationUnitSources-Size", lib.compilationUnitSources.length);
8001 } 8540 }
8002 return targetLibrary.libraryElement; 8541 return targetLibrary.libraryElement;
8003 } finally { 8542 } finally {
8004 instrumentation.log(); 8543 instrumentation.log();
8005 } 8544 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
8097 void buildDirectiveModels() { 8636 void buildDirectiveModels() {
8098 for (Library library in _librariesInCycles) { 8637 for (Library library in _librariesInCycles) {
8099 Map<String, PrefixElementImpl> nameToPrefixMap = new Map<String, PrefixEle mentImpl>(); 8638 Map<String, PrefixElementImpl> nameToPrefixMap = new Map<String, PrefixEle mentImpl>();
8100 List<ImportElement> imports = new List<ImportElement>(); 8639 List<ImportElement> imports = new List<ImportElement>();
8101 List<ExportElement> exports = new List<ExportElement>(); 8640 List<ExportElement> exports = new List<ExportElement>();
8102 for (Directive directive in library.definingCompilationUnit.directives) { 8641 for (Directive directive in library.definingCompilationUnit.directives) {
8103 if (directive is ImportDirective) { 8642 if (directive is ImportDirective) {
8104 ImportDirective importDirective = directive; 8643 ImportDirective importDirective = directive;
8105 Source importedSource = library.getSource(importDirective); 8644 Source importedSource = library.getSource(importDirective);
8106 if (importedSource != null) { 8645 if (importedSource != null) {
8646 // The imported source will be null if the URI in the import directi ve was invalid.
8107 Library importedLibrary = _libraryMap[importedSource]; 8647 Library importedLibrary = _libraryMap[importedSource];
8108 if (importedLibrary != null) { 8648 if (importedLibrary != null) {
8109 ImportElementImpl importElement = new ImportElementImpl(directive. offset); 8649 ImportElementImpl importElement = new ImportElementImpl(directive. offset);
8110 StringLiteral uriLiteral = importDirective.uri; 8650 StringLiteral uriLiteral = importDirective.uri;
8111 if (uriLiteral != null) { 8651 if (uriLiteral != null) {
8112 importElement.uriEnd = uriLiteral.end; 8652 importElement.uriEnd = uriLiteral.end;
8113 } 8653 }
8114 importElement.uri = library.getUri(importDirective); 8654 importElement.uri = library.getUri(importDirective);
8115 importElement.combinators = buildCombinators(importDirective); 8655 importElement.combinators = buildCombinators(importDirective);
8116 LibraryElement importedLibraryElement = importedLibrary.libraryEle ment; 8656 LibraryElement importedLibraryElement = importedLibrary.libraryEle ment;
(...skipping 16 matching lines...) Expand all
8133 imports.add(importElement); 8673 imports.add(importElement);
8134 if (analysisContext.computeKindOf(importedSource) != SourceKind.LI BRARY) { 8674 if (analysisContext.computeKindOf(importedSource) != SourceKind.LI BRARY) {
8135 _errorListener.onError(new AnalysisError.con2(library.librarySou rce, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.IMPORT_OF_NON_LI BRARY, [uriLiteral.toSource()])); 8675 _errorListener.onError(new AnalysisError.con2(library.librarySou rce, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.IMPORT_OF_NON_LI BRARY, [uriLiteral.toSource()]));
8136 } 8676 }
8137 } 8677 }
8138 } 8678 }
8139 } else if (directive is ExportDirective) { 8679 } else if (directive is ExportDirective) {
8140 ExportDirective exportDirective = directive; 8680 ExportDirective exportDirective = directive;
8141 Source exportedSource = library.getSource(exportDirective); 8681 Source exportedSource = library.getSource(exportDirective);
8142 if (exportedSource != null) { 8682 if (exportedSource != null) {
8683 // The exported source will be null if the URI in the export directi ve was invalid.
8143 Library exportedLibrary = _libraryMap[exportedSource]; 8684 Library exportedLibrary = _libraryMap[exportedSource];
8144 if (exportedLibrary != null) { 8685 if (exportedLibrary != null) {
8145 ExportElementImpl exportElement = new ExportElementImpl(); 8686 ExportElementImpl exportElement = new ExportElementImpl();
8146 exportElement.uri = library.getUri(exportDirective); 8687 exportElement.uri = library.getUri(exportDirective);
8147 exportElement.combinators = buildCombinators(exportDirective); 8688 exportElement.combinators = buildCombinators(exportDirective);
8148 LibraryElement exportedLibraryElement = exportedLibrary.libraryEle ment; 8689 LibraryElement exportedLibraryElement = exportedLibrary.libraryEle ment;
8149 if (exportedLibraryElement != null) { 8690 if (exportedLibraryElement != null) {
8150 exportElement.exportedLibrary = exportedLibraryElement; 8691 exportElement.exportedLibrary = exportedLibraryElement;
8151 } 8692 }
8152 directive.element = exportElement; 8693 directive.element = exportElement;
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
8449 ast.accept(visitor); 8990 ast.accept(visitor);
8450 for (ProxyConditionalAnalysisError conditionalCode in visitor.proxyCondi tionalAnalysisErrors) { 8991 for (ProxyConditionalAnalysisError conditionalCode in visitor.proxyCondi tionalAnalysisErrors) {
8451 if (conditionalCode.shouldIncludeErrorCode()) { 8992 if (conditionalCode.shouldIncludeErrorCode()) {
8452 visitor.reportError(conditionalCode.analysisError); 8993 visitor.reportError(conditionalCode.analysisError);
8453 } 8994 }
8454 } 8995 }
8455 } 8996 }
8456 } finally { 8997 } finally {
8457 timeCounter.stop(); 8998 timeCounter.stop();
8458 } 8999 }
9000 // Angular
8459 timeCounter = PerformanceStatistics.angular.start(); 9001 timeCounter = PerformanceStatistics.angular.start();
8460 try { 9002 try {
8461 for (Source source in library.compilationUnitSources) { 9003 for (Source source in library.compilationUnitSources) {
8462 CompilationUnit ast = library.getAST(source); 9004 CompilationUnit ast = library.getAST(source);
8463 new AngularCompilationUnitBuilder(_errorListener, source).build(ast); 9005 new AngularCompilationUnitBuilder(_errorListener, source).build(ast);
8464 } 9006 }
8465 } finally { 9007 } finally {
8466 timeCounter.stop(); 9008 timeCounter.stop();
8467 } 9009 }
8468 } 9010 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
8582 ExecutableElement getValue(int i) => _values[i]; 9124 ExecutableElement getValue(int i) => _values[i];
8583 9125
8584 /** 9126 /**
8585 * Given some key/value pair, store the pair in the map. If the key exists alr eady, then the new 9127 * Given some key/value pair, store the pair in the map. If the key exists alr eady, then the new
8586 * value overrides the old value. 9128 * value overrides the old value.
8587 * 9129 *
8588 * @param key the key to store in the map 9130 * @param key the key to store in the map
8589 * @param value the ExecutableElement value to store in the map 9131 * @param value the ExecutableElement value to store in the map
8590 */ 9132 */
8591 void put(String key, ExecutableElement value) { 9133 void put(String key, ExecutableElement value) {
9134 // If we already have a value with this key, override the value
8592 for (int i = 0; i < _size; i++) { 9135 for (int i = 0; i < _size; i++) {
8593 if (_keys[i] != null && _keys[i] == key) { 9136 if (_keys[i] != null && _keys[i] == key) {
8594 _values[i] = value; 9137 _values[i] = value;
8595 return; 9138 return;
8596 } 9139 }
8597 } 9140 }
9141 // If needed, double the size of our arrays and copy values over in both arr ays
8598 if (_size == _keys.length) { 9142 if (_size == _keys.length) {
8599 int newArrayLength = _size * 2; 9143 int newArrayLength = _size * 2;
8600 List<String> keys_new_array = new List<String>(newArrayLength); 9144 List<String> keys_new_array = new List<String>(newArrayLength);
8601 List<ExecutableElement> values_new_array = new List<ExecutableElement>(new ArrayLength); 9145 List<ExecutableElement> values_new_array = new List<ExecutableElement>(new ArrayLength);
8602 for (int i = 0; i < _size; i++) { 9146 for (int i = 0; i < _size; i++) {
8603 keys_new_array[i] = _keys[i]; 9147 keys_new_array[i] = _keys[i];
8604 } 9148 }
8605 for (int i = 0; i < _size; i++) { 9149 for (int i = 0; i < _size; i++) {
8606 values_new_array[i] = _values[i]; 9150 values_new_array[i] = _values[i];
8607 } 9151 }
8608 _keys = keys_new_array; 9152 _keys = keys_new_array;
8609 _values = values_new_array; 9153 _values = values_new_array;
8610 } 9154 }
9155 // Put new value at end of array
8611 _keys[_size] = key; 9156 _keys[_size] = key;
8612 _values[_size] = value; 9157 _values[_size] = value;
8613 _size++; 9158 _size++;
8614 } 9159 }
8615 9160
8616 /** 9161 /**
8617 * Given some String key, this method replaces the associated key and value pa ir with `null` 9162 * Given some String key, this method replaces the associated key and value pa ir with `null`
8618 * . The size is not decremented with this call, instead it is expected that t he users check for 9163 * . The size is not decremented with this call, instead it is expected that t he users check for
8619 * `null`. 9164 * `null`.
8620 * 9165 *
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
8829 sc.TokenType operatorType = node.operator.type; 9374 sc.TokenType operatorType = node.operator.type;
8830 Expression leftOperand = node.leftOperand; 9375 Expression leftOperand = node.leftOperand;
8831 Expression rightOperand = node.rightOperand; 9376 Expression rightOperand = node.rightOperand;
8832 if (identical(operatorType, sc.TokenType.AMPERSAND_AMPERSAND)) { 9377 if (identical(operatorType, sc.TokenType.AMPERSAND_AMPERSAND)) {
8833 safelyVisit(leftOperand); 9378 safelyVisit(leftOperand);
8834 if (rightOperand != null) { 9379 if (rightOperand != null) {
8835 try { 9380 try {
8836 _overrideManager.enterScope(); 9381 _overrideManager.enterScope();
8837 _promoteManager.enterScope(); 9382 _promoteManager.enterScope();
8838 propagateTrueState(leftOperand); 9383 propagateTrueState(leftOperand);
9384 // Type promotion.
8839 promoteTypes(leftOperand); 9385 promoteTypes(leftOperand);
8840 clearTypePromotionsIfPotentiallyMutatedIn(leftOperand); 9386 clearTypePromotionsIfPotentiallyMutatedIn(leftOperand);
8841 clearTypePromotionsIfPotentiallyMutatedIn(rightOperand); 9387 clearTypePromotionsIfPotentiallyMutatedIn(rightOperand);
8842 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(rightOper and); 9388 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(rightOper and);
9389 // Visit right operand.
8843 rightOperand.accept(this); 9390 rightOperand.accept(this);
8844 } finally { 9391 } finally {
8845 _overrideManager.exitScope(); 9392 _overrideManager.exitScope();
8846 _promoteManager.exitScope(); 9393 _promoteManager.exitScope();
8847 } 9394 }
8848 } 9395 }
8849 } else if (identical(operatorType, sc.TokenType.BAR_BAR)) { 9396 } else if (identical(operatorType, sc.TokenType.BAR_BAR)) {
8850 safelyVisit(leftOperand); 9397 safelyVisit(leftOperand);
8851 if (rightOperand != null) { 9398 if (rightOperand != null) {
8852 try { 9399 try {
(...skipping 18 matching lines...) Expand all
8871 try { 9418 try {
8872 _overrideManager.enterScope(); 9419 _overrideManager.enterScope();
8873 super.visitBlockFunctionBody(node); 9420 super.visitBlockFunctionBody(node);
8874 } finally { 9421 } finally {
8875 _overrideManager.exitScope(); 9422 _overrideManager.exitScope();
8876 } 9423 }
8877 return null; 9424 return null;
8878 } 9425 }
8879 9426
8880 Object visitBreakStatement(BreakStatement node) { 9427 Object visitBreakStatement(BreakStatement node) {
9428 //
9429 // We do not visit the label because it needs to be visited in the context o f the statement.
9430 //
8881 node.accept(_elementResolver); 9431 node.accept(_elementResolver);
8882 node.accept(_typeAnalyzer); 9432 node.accept(_typeAnalyzer);
8883 return null; 9433 return null;
8884 } 9434 }
8885 9435
8886 Object visitClassDeclaration(ClassDeclaration node) { 9436 Object visitClassDeclaration(ClassDeclaration node) {
8887 ClassElement outerType = _enclosingClass; 9437 ClassElement outerType = _enclosingClass;
8888 try { 9438 try {
8889 _enclosingClass = node.element; 9439 _enclosingClass = node.element;
8890 _typeAnalyzer.thisType = _enclosingClass == null ? null : _enclosingClass. type; 9440 _typeAnalyzer.thisType = _enclosingClass == null ? null : _enclosingClass. type;
(...skipping 11 matching lines...) Expand all
8902 _commentBeforeFunction = node; 9452 _commentBeforeFunction = node;
8903 return null; 9453 return null;
8904 } 9454 }
8905 } 9455 }
8906 super.visitComment(node); 9456 super.visitComment(node);
8907 _commentBeforeFunction = null; 9457 _commentBeforeFunction = null;
8908 return null; 9458 return null;
8909 } 9459 }
8910 9460
8911 Object visitCommentReference(CommentReference node) { 9461 Object visitCommentReference(CommentReference node) {
9462 //
9463 // We do not visit the identifier because it needs to be visited in the cont ext of the reference.
9464 //
8912 node.accept(_elementResolver); 9465 node.accept(_elementResolver);
8913 node.accept(_typeAnalyzer); 9466 node.accept(_typeAnalyzer);
8914 return null; 9467 return null;
8915 } 9468 }
8916 9469
8917 Object visitCompilationUnit(CompilationUnit node) { 9470 Object visitCompilationUnit(CompilationUnit node) {
9471 //
9472 // TODO(brianwilkerson) The goal of the code below is to visit the declarati ons in such an
9473 // order that we can infer type information for top-level variables before w e visit references
9474 // to them. This is better than making no effort, but still doesn't complete ly satisfy that
9475 // goal (consider for example "final var a = b; final var b = 0;"; we'll inf er a type of 'int'
9476 // for 'b', but not for 'a' because of the order of the visits). Ideally we would create a
9477 // dependency graph, but that would require references to be resolved, which they are not.
9478 //
8918 try { 9479 try {
8919 _overrideManager.enterScope(); 9480 _overrideManager.enterScope();
8920 NodeList<Directive> directives = node.directives; 9481 NodeList<Directive> directives = node.directives;
8921 int directiveCount = directives.length; 9482 int directiveCount = directives.length;
8922 for (int i = 0; i < directiveCount; i++) { 9483 for (int i = 0; i < directiveCount; i++) {
8923 directives[i].accept(this); 9484 directives[i].accept(this);
8924 } 9485 }
8925 NodeList<CompilationUnitMember> declarations = node.declarations; 9486 NodeList<CompilationUnitMember> declarations = node.declarations;
8926 int declarationCount = declarations.length; 9487 int declarationCount = declarations.length;
8927 for (int i = 0; i < declarationCount; i++) { 9488 for (int i = 0; i < declarationCount; i++) {
(...skipping 18 matching lines...) Expand all
8946 9507
8947 Object visitConditionalExpression(ConditionalExpression node) { 9508 Object visitConditionalExpression(ConditionalExpression node) {
8948 Expression condition = node.condition; 9509 Expression condition = node.condition;
8949 safelyVisit(condition); 9510 safelyVisit(condition);
8950 Expression thenExpression = node.thenExpression; 9511 Expression thenExpression = node.thenExpression;
8951 if (thenExpression != null) { 9512 if (thenExpression != null) {
8952 try { 9513 try {
8953 _overrideManager.enterScope(); 9514 _overrideManager.enterScope();
8954 _promoteManager.enterScope(); 9515 _promoteManager.enterScope();
8955 propagateTrueState(condition); 9516 propagateTrueState(condition);
9517 // Type promotion.
8956 promoteTypes(condition); 9518 promoteTypes(condition);
8957 clearTypePromotionsIfPotentiallyMutatedIn(thenExpression); 9519 clearTypePromotionsIfPotentiallyMutatedIn(thenExpression);
8958 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(thenExpress ion); 9520 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(thenExpress ion);
9521 // Visit "then" expression.
8959 thenExpression.accept(this); 9522 thenExpression.accept(this);
8960 } finally { 9523 } finally {
8961 _overrideManager.exitScope(); 9524 _overrideManager.exitScope();
8962 _promoteManager.exitScope(); 9525 _promoteManager.exitScope();
8963 } 9526 }
8964 } 9527 }
8965 Expression elseExpression = node.elseExpression; 9528 Expression elseExpression = node.elseExpression;
8966 if (elseExpression != null) { 9529 if (elseExpression != null) {
8967 try { 9530 try {
8968 _overrideManager.enterScope(); 9531 _overrideManager.enterScope();
(...skipping 22 matching lines...) Expand all
8991 try { 9554 try {
8992 _enclosingFunction = node.element; 9555 _enclosingFunction = node.element;
8993 super.visitConstructorDeclaration(node); 9556 super.visitConstructorDeclaration(node);
8994 } finally { 9557 } finally {
8995 _enclosingFunction = outerFunction; 9558 _enclosingFunction = outerFunction;
8996 } 9559 }
8997 return null; 9560 return null;
8998 } 9561 }
8999 9562
9000 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) { 9563 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
9564 //
9565 // We visit the expression, but do not visit the field name because it needs to be visited in
9566 // the context of the constructor field initializer node.
9567 //
9001 safelyVisit(node.expression); 9568 safelyVisit(node.expression);
9002 node.accept(_elementResolver); 9569 node.accept(_elementResolver);
9003 node.accept(_typeAnalyzer); 9570 node.accept(_typeAnalyzer);
9004 return null; 9571 return null;
9005 } 9572 }
9006 9573
9007 Object visitConstructorName(ConstructorName node) { 9574 Object visitConstructorName(ConstructorName node) {
9575 //
9576 // We do not visit either the type name, because it won't be visited anyway, or the name,
9577 // because it needs to be visited in the context of the constructor name.
9578 //
9008 node.accept(_elementResolver); 9579 node.accept(_elementResolver);
9009 node.accept(_typeAnalyzer); 9580 node.accept(_typeAnalyzer);
9010 return null; 9581 return null;
9011 } 9582 }
9012 9583
9013 Object visitContinueStatement(ContinueStatement node) { 9584 Object visitContinueStatement(ContinueStatement node) {
9585 //
9586 // We do not visit the label because it needs to be visited in the context o f the statement.
9587 //
9014 node.accept(_elementResolver); 9588 node.accept(_elementResolver);
9015 node.accept(_typeAnalyzer); 9589 node.accept(_typeAnalyzer);
9016 return null; 9590 return null;
9017 } 9591 }
9018 9592
9019 Object visitDoStatement(DoStatement node) { 9593 Object visitDoStatement(DoStatement node) {
9020 try { 9594 try {
9021 _overrideManager.enterScope(); 9595 _overrideManager.enterScope();
9022 super.visitDoStatement(node); 9596 super.visitDoStatement(node);
9023 } finally { 9597 } finally {
9024 _overrideManager.exitScope(); 9598 _overrideManager.exitScope();
9025 } 9599 }
9600 // TODO(brianwilkerson) If the loop can only be exited because the condition is false, then
9601 // propagateFalseState(node.getCondition());
9026 return null; 9602 return null;
9027 } 9603 }
9028 9604
9029 Object visitEmptyFunctionBody(EmptyFunctionBody node) { 9605 Object visitEmptyFunctionBody(EmptyFunctionBody node) {
9030 safelyVisit(_commentBeforeFunction); 9606 safelyVisit(_commentBeforeFunction);
9031 return super.visitEmptyFunctionBody(node); 9607 return super.visitEmptyFunctionBody(node);
9032 } 9608 }
9033 9609
9034 Object visitExpressionFunctionBody(ExpressionFunctionBody node) { 9610 Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
9035 safelyVisit(_commentBeforeFunction); 9611 safelyVisit(_commentBeforeFunction);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
9113 Object visitIfStatement(IfStatement node) { 9689 Object visitIfStatement(IfStatement node) {
9114 Expression condition = node.condition; 9690 Expression condition = node.condition;
9115 safelyVisit(condition); 9691 safelyVisit(condition);
9116 Map<Element, Type2> thenOverrides = null; 9692 Map<Element, Type2> thenOverrides = null;
9117 Statement thenStatement = node.thenStatement; 9693 Statement thenStatement = node.thenStatement;
9118 if (thenStatement != null) { 9694 if (thenStatement != null) {
9119 try { 9695 try {
9120 _overrideManager.enterScope(); 9696 _overrideManager.enterScope();
9121 _promoteManager.enterScope(); 9697 _promoteManager.enterScope();
9122 propagateTrueState(condition); 9698 propagateTrueState(condition);
9699 // Type promotion.
9123 promoteTypes(condition); 9700 promoteTypes(condition);
9124 clearTypePromotionsIfPotentiallyMutatedIn(thenStatement); 9701 clearTypePromotionsIfPotentiallyMutatedIn(thenStatement);
9125 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(thenStateme nt); 9702 clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(thenStateme nt);
9703 // Visit "then".
9126 visitStatementInScope(thenStatement); 9704 visitStatementInScope(thenStatement);
9127 } finally { 9705 } finally {
9128 thenOverrides = _overrideManager.captureLocalOverrides(); 9706 thenOverrides = _overrideManager.captureLocalOverrides();
9129 _overrideManager.exitScope(); 9707 _overrideManager.exitScope();
9130 _promoteManager.exitScope(); 9708 _promoteManager.exitScope();
9131 } 9709 }
9132 } 9710 }
9133 Map<Element, Type2> elseOverrides = null; 9711 Map<Element, Type2> elseOverrides = null;
9134 Statement elseStatement = node.elseStatement; 9712 Statement elseStatement = node.elseStatement;
9135 if (elseStatement != null) { 9713 if (elseStatement != null) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
9169 try { 9747 try {
9170 _enclosingFunction = node.element; 9748 _enclosingFunction = node.element;
9171 super.visitMethodDeclaration(node); 9749 super.visitMethodDeclaration(node);
9172 } finally { 9750 } finally {
9173 _enclosingFunction = outerFunction; 9751 _enclosingFunction = outerFunction;
9174 } 9752 }
9175 return null; 9753 return null;
9176 } 9754 }
9177 9755
9178 Object visitMethodInvocation(MethodInvocation node) { 9756 Object visitMethodInvocation(MethodInvocation node) {
9757 //
9758 // We visit the target and argument list, but do not visit the method name b ecause it needs to
9759 // be visited in the context of the invocation.
9760 //
9179 safelyVisit(node.target); 9761 safelyVisit(node.target);
9180 node.accept(_elementResolver); 9762 node.accept(_elementResolver);
9181 inferFunctionExpressionsParametersTypes(node.argumentList); 9763 inferFunctionExpressionsParametersTypes(node.argumentList);
9182 safelyVisit(node.argumentList); 9764 safelyVisit(node.argumentList);
9183 node.accept(_typeAnalyzer); 9765 node.accept(_typeAnalyzer);
9184 return null; 9766 return null;
9185 } 9767 }
9186 9768
9187 Object visitNode(ASTNode node) { 9769 Object visitNode(ASTNode node) {
9188 node.visitChildren(this); 9770 node.visitChildren(this);
9189 node.accept(_elementResolver); 9771 node.accept(_elementResolver);
9190 node.accept(_typeAnalyzer); 9772 node.accept(_typeAnalyzer);
9191 return null; 9773 return null;
9192 } 9774 }
9193 9775
9194 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 9776 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
9777 //
9778 // We visit the prefix, but do not visit the identifier because it needs to be visited in the
9779 // context of the prefix.
9780 //
9195 safelyVisit(node.prefix); 9781 safelyVisit(node.prefix);
9196 node.accept(_elementResolver); 9782 node.accept(_elementResolver);
9197 node.accept(_typeAnalyzer); 9783 node.accept(_typeAnalyzer);
9198 return null; 9784 return null;
9199 } 9785 }
9200 9786
9201 Object visitPropertyAccess(PropertyAccess node) { 9787 Object visitPropertyAccess(PropertyAccess node) {
9788 //
9789 // We visit the target, but do not visit the property name because it needs to be visited in the
9790 // context of the property access node.
9791 //
9202 safelyVisit(node.target); 9792 safelyVisit(node.target);
9203 node.accept(_elementResolver); 9793 node.accept(_elementResolver);
9204 node.accept(_typeAnalyzer); 9794 node.accept(_typeAnalyzer);
9205 return null; 9795 return null;
9206 } 9796 }
9207 9797
9208 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) { 9798 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
9799 //
9800 // We visit the argument list, but do not visit the optional identifier beca use it needs to be
9801 // visited in the context of the constructor invocation.
9802 //
9209 safelyVisit(node.argumentList); 9803 safelyVisit(node.argumentList);
9210 node.accept(_elementResolver); 9804 node.accept(_elementResolver);
9211 node.accept(_typeAnalyzer); 9805 node.accept(_typeAnalyzer);
9212 return null; 9806 return null;
9213 } 9807 }
9214 9808
9215 Object visitShowCombinator(ShowCombinator node) => null; 9809 Object visitShowCombinator(ShowCombinator node) => null;
9216 9810
9217 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) { 9811 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
9812 //
9813 // We visit the argument list, but do not visit the optional identifier beca use it needs to be
9814 // visited in the context of the constructor invocation.
9815 //
9218 safelyVisit(node.argumentList); 9816 safelyVisit(node.argumentList);
9219 node.accept(_elementResolver); 9817 node.accept(_elementResolver);
9220 node.accept(_typeAnalyzer); 9818 node.accept(_typeAnalyzer);
9221 return null; 9819 return null;
9222 } 9820 }
9223 9821
9224 Object visitSwitchCase(SwitchCase node) { 9822 Object visitSwitchCase(SwitchCase node) {
9225 try { 9823 try {
9226 _overrideManager.enterScope(); 9824 _overrideManager.enterScope();
9227 super.visitSwitchCase(node); 9825 super.visitSwitchCase(node);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
9261 Statement body = node.body; 9859 Statement body = node.body;
9262 if (body != null) { 9860 if (body != null) {
9263 try { 9861 try {
9264 _overrideManager.enterScope(); 9862 _overrideManager.enterScope();
9265 propagateTrueState(condition); 9863 propagateTrueState(condition);
9266 visitStatementInScope(body); 9864 visitStatementInScope(body);
9267 } finally { 9865 } finally {
9268 _overrideManager.exitScope(); 9866 _overrideManager.exitScope();
9269 } 9867 }
9270 } 9868 }
9869 // TODO(brianwilkerson) If the loop can only be exited because the condition is false, then
9870 // propagateFalseState(condition);
9271 node.accept(_elementResolver); 9871 node.accept(_elementResolver);
9272 node.accept(_typeAnalyzer); 9872 node.accept(_typeAnalyzer);
9273 return null; 9873 return null;
9274 } 9874 }
9275 9875
9276 /** 9876 /**
9277 * Return the class element representing the class containing the current node , or `null` if 9877 * Return the class element representing the class containing the current node , or `null` if
9278 * the current node is not contained in a class. 9878 * the current node is not contained in a class.
9279 * 9879 *
9280 * @return the class element representing the class containing the current nod e 9880 * @return the class element representing the class containing the current nod e
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
9437 * @param enclosingElement the enclosing element 10037 * @param enclosingElement the enclosing element
9438 * @param errorCode the error code of the error to be reported 10038 * @param errorCode the error code of the error to be reported
9439 * @param token the token specifying the location of the error 10039 * @param token the token specifying the location of the error
9440 * @param arguments the arguments to the error, used to compose the error mess age 10040 * @param arguments the arguments to the error, used to compose the error mess age
9441 */ 10041 */
9442 void reportErrorProxyConditionalAnalysisError3(Element enclosingElement, Error Code errorCode, sc.Token token, List<Object> arguments) { 10042 void reportErrorProxyConditionalAnalysisError3(Element enclosingElement, Error Code errorCode, sc.Token token, List<Object> arguments) {
9443 _proxyConditionalAnalysisErrors.add(new ProxyConditionalAnalysisError(enclos ingElement, new AnalysisError.con2(source, token.offset, token.length, errorCode , arguments))); 10043 _proxyConditionalAnalysisErrors.add(new ProxyConditionalAnalysisError(enclos ingElement, new AnalysisError.con2(source, token.offset, token.length, errorCode , arguments)));
9444 } 10044 }
9445 10045
9446 void visitForEachStatementInScope(ForEachStatement node) { 10046 void visitForEachStatementInScope(ForEachStatement node) {
10047 //
10048 // We visit the iterator before the loop variable because the loop variable cannot be in scope
10049 // while visiting the iterator.
10050 //
9447 Expression iterator = node.iterator; 10051 Expression iterator = node.iterator;
9448 safelyVisit(iterator); 10052 safelyVisit(iterator);
9449 DeclaredIdentifier loopVariable = node.loopVariable; 10053 DeclaredIdentifier loopVariable = node.loopVariable;
9450 SimpleIdentifier identifier = node.identifier; 10054 SimpleIdentifier identifier = node.identifier;
9451 safelyVisit(loopVariable); 10055 safelyVisit(loopVariable);
9452 safelyVisit(identifier); 10056 safelyVisit(identifier);
9453 Statement body = node.body; 10057 Statement body = node.body;
9454 if (body != null) { 10058 if (body != null) {
9455 try { 10059 try {
9456 _overrideManager.enterScope(); 10060 _overrideManager.enterScope();
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
9549 * 10153 *
9550 * @param iterator the iterator for a for-each statement 10154 * @param iterator the iterator for a for-each statement
9551 * @return the type of objects that will be assigned to the loop variable 10155 * @return the type of objects that will be assigned to the loop variable
9552 */ 10156 */
9553 Type2 getIteratorElementType(Expression iteratorExpression) { 10157 Type2 getIteratorElementType(Expression iteratorExpression) {
9554 Type2 expressionType = iteratorExpression.staticType; 10158 Type2 expressionType = iteratorExpression.staticType;
9555 if (expressionType is InterfaceType) { 10159 if (expressionType is InterfaceType) {
9556 InterfaceType interfaceType = expressionType; 10160 InterfaceType interfaceType = expressionType;
9557 FunctionType iteratorFunction = _inheritanceManager.lookupMemberType(inter faceType, "iterator"); 10161 FunctionType iteratorFunction = _inheritanceManager.lookupMemberType(inter faceType, "iterator");
9558 if (iteratorFunction == null) { 10162 if (iteratorFunction == null) {
10163 // TODO(brianwilkerson) Should we report this error?
9559 return null; 10164 return null;
9560 } 10165 }
9561 Type2 iteratorType = iteratorFunction.returnType; 10166 Type2 iteratorType = iteratorFunction.returnType;
9562 if (iteratorType is InterfaceType) { 10167 if (iteratorType is InterfaceType) {
9563 InterfaceType iteratorInterfaceType = iteratorType; 10168 InterfaceType iteratorInterfaceType = iteratorType;
9564 FunctionType currentFunction = _inheritanceManager.lookupMemberType(iter atorInterfaceType, "current"); 10169 FunctionType currentFunction = _inheritanceManager.lookupMemberType(iter atorInterfaceType, "current");
9565 if (currentFunction == null) { 10170 if (currentFunction == null) {
10171 // TODO(brianwilkerson) Should we report this error?
9566 return null; 10172 return null;
9567 } 10173 }
9568 return currentFunction.returnType; 10174 return currentFunction.returnType;
9569 } 10175 }
9570 } 10176 }
9571 return null; 10177 return null;
9572 } 10178 }
9573 10179
9574 /** 10180 /**
9575 * If given "mayBeClosure" is [FunctionExpression] without explicit parameters types and its 10181 * If given "mayBeClosure" is [FunctionExpression] without explicit parameters types and its
9576 * required type is [FunctionType], then infer parameters types from [Function Type]. 10182 * required type is [FunctionType], then infer parameters types from [Function Type].
9577 */ 10183 */
9578 void inferFunctionExpressionParametersTypes(Expression mayBeClosure, Type2 may ByFunctionType) { 10184 void inferFunctionExpressionParametersTypes(Expression mayBeClosure, Type2 may ByFunctionType) {
10185 // prepare closure
9579 if (mayBeClosure is! FunctionExpression) { 10186 if (mayBeClosure is! FunctionExpression) {
9580 return; 10187 return;
9581 } 10188 }
9582 FunctionExpression closure = mayBeClosure as FunctionExpression; 10189 FunctionExpression closure = mayBeClosure as FunctionExpression;
10190 // prepare expected closure type
9583 if (mayByFunctionType is! FunctionType) { 10191 if (mayByFunctionType is! FunctionType) {
9584 return; 10192 return;
9585 } 10193 }
9586 FunctionType expectedClosureType = mayByFunctionType as FunctionType; 10194 FunctionType expectedClosureType = mayByFunctionType as FunctionType;
10195 // set propagated type for the closure
9587 closure.propagatedType = expectedClosureType; 10196 closure.propagatedType = expectedClosureType;
10197 // set inferred types for parameters
9588 NodeList<FormalParameter> parameters = closure.parameters.parameters; 10198 NodeList<FormalParameter> parameters = closure.parameters.parameters;
9589 List<ParameterElement> expectedParameters = expectedClosureType.parameters; 10199 List<ParameterElement> expectedParameters = expectedClosureType.parameters;
9590 for (int i = 0; i < parameters.length && i < expectedParameters.length; i++) { 10200 for (int i = 0; i < parameters.length && i < expectedParameters.length; i++) {
9591 FormalParameter parameter = parameters[i]; 10201 FormalParameter parameter = parameters[i];
9592 ParameterElement element = parameter.element; 10202 ParameterElement element = parameter.element;
9593 Type2 currentType = getBestType(element); 10203 Type2 currentType = getBestType(element);
10204 // may be override the type
9594 Type2 expectedType = expectedParameters[i].type; 10205 Type2 expectedType = expectedParameters[i].type;
9595 if (currentType == null || expectedType.isMoreSpecificThan(currentType)) { 10206 if (currentType == null || expectedType.isMoreSpecificThan(currentType)) {
9596 _overrideManager.setType(element, expectedType); 10207 _overrideManager.setType(element, expectedType);
9597 } 10208 }
9598 } 10209 }
9599 } 10210 }
9600 10211
9601 /** 10212 /**
9602 * Try to infer types of parameters of the [FunctionExpression] arguments. 10213 * Try to infer types of parameters of the [FunctionExpression] arguments.
9603 */ 10214 */
(...skipping 10 matching lines...) Expand all
9614 } 10225 }
9615 10226
9616 /** 10227 /**
9617 * Return `true` if the given expression terminates abruptly (that is, if any expression 10228 * Return `true` if the given expression terminates abruptly (that is, if any expression
9618 * following the given expression will not be reached). 10229 * following the given expression will not be reached).
9619 * 10230 *
9620 * @param expression the expression being tested 10231 * @param expression the expression being tested
9621 * @return `true` if the given expression terminates abruptly 10232 * @return `true` if the given expression terminates abruptly
9622 */ 10233 */
9623 bool isAbruptTermination(Expression expression) { 10234 bool isAbruptTermination(Expression expression) {
10235 // TODO(brianwilkerson) This needs to be significantly improved. Ideally we would eventually
10236 // turn this into a method on Expression that returns a termination indicati on (normal, abrupt
10237 // with no exception, abrupt with an exception).
9624 while (expression is ParenthesizedExpression) { 10238 while (expression is ParenthesizedExpression) {
9625 expression = (expression as ParenthesizedExpression).expression; 10239 expression = (expression as ParenthesizedExpression).expression;
9626 } 10240 }
9627 return expression is ThrowExpression || expression is RethrowExpression; 10241 return expression is ThrowExpression || expression is RethrowExpression;
9628 } 10242 }
9629 10243
9630 /** 10244 /**
9631 * Return `true` if the given statement terminates abruptly (that is, if any s tatement 10245 * Return `true` if the given statement terminates abruptly (that is, if any s tatement
9632 * following the given statement will not be reached). 10246 * following the given statement will not be reached).
9633 * 10247 *
9634 * @param statement the statement being tested 10248 * @param statement the statement being tested
9635 * @return `true` if the given statement terminates abruptly 10249 * @return `true` if the given statement terminates abruptly
9636 */ 10250 */
9637 bool isAbruptTermination2(Statement statement) { 10251 bool isAbruptTermination2(Statement statement) {
10252 // TODO(brianwilkerson) This needs to be significantly improved. Ideally we would eventually
10253 // turn this into a method on Statement that returns a termination indicatio n (normal, abrupt
10254 // with no exception, abrupt with an exception).
9638 if (statement is ReturnStatement || statement is BreakStatement || statement is ContinueStatement) { 10255 if (statement is ReturnStatement || statement is BreakStatement || statement is ContinueStatement) {
9639 return true; 10256 return true;
9640 } else if (statement is ExpressionStatement) { 10257 } else if (statement is ExpressionStatement) {
9641 return isAbruptTermination(statement.expression); 10258 return isAbruptTermination(statement.expression);
9642 } else if (statement is Block) { 10259 } else if (statement is Block) {
9643 NodeList<Statement> statements = statement.statements; 10260 NodeList<Statement> statements = statement.statements;
9644 int size = statements.length; 10261 int size = statements.length;
9645 if (size == 0) { 10262 if (size == 0) {
9646 return false; 10263 return false;
9647 } 10264 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
9684 * the given expression with the given type. Generally speaking, it is appropr iate if the given 10301 * the given expression with the given type. Generally speaking, it is appropr iate if the given
9685 * type is more specific than the current type. 10302 * type is more specific than the current type.
9686 * 10303 *
9687 * @param expression the expression used to access the static element whose ty pes might be 10304 * @param expression the expression used to access the static element whose ty pes might be
9688 * promoted 10305 * promoted
9689 * @param potentialType the potential type of the elements 10306 * @param potentialType the potential type of the elements
9690 */ 10307 */
9691 void promote(Expression expression, Type2 potentialType) { 10308 void promote(Expression expression, Type2 potentialType) {
9692 VariableElement element = getPromotionStaticElement(expression); 10309 VariableElement element = getPromotionStaticElement(expression);
9693 if (element != null) { 10310 if (element != null) {
10311 // may be mutated somewhere in closure
9694 if ((element as VariableElementImpl).isPotentiallyMutatedInClosure) { 10312 if ((element as VariableElementImpl).isPotentiallyMutatedInClosure) {
9695 return; 10313 return;
9696 } 10314 }
10315 // prepare current variable type
9697 Type2 type = _promoteManager.getType(element); 10316 Type2 type = _promoteManager.getType(element);
9698 if (type == null) { 10317 if (type == null) {
9699 type = expression.staticType; 10318 type = expression.staticType;
9700 } 10319 }
10320 // Declared type should not be "dynamic".
9701 if (type == null || type.isDynamic) { 10321 if (type == null || type.isDynamic) {
9702 return; 10322 return;
9703 } 10323 }
10324 // Promoted type should not be "dynamic".
9704 if (potentialType == null || potentialType.isDynamic) { 10325 if (potentialType == null || potentialType.isDynamic) {
9705 return; 10326 return;
9706 } 10327 }
10328 // Promoted type should be more specific than declared.
9707 if (!potentialType.isMoreSpecificThan(type)) { 10329 if (!potentialType.isMoreSpecificThan(type)) {
9708 return; 10330 return;
9709 } 10331 }
10332 // Do promote type of variable.
9710 _promoteManager.setType(element, potentialType); 10333 _promoteManager.setType(element, potentialType);
9711 } 10334 }
9712 } 10335 }
9713 10336
9714 /** 10337 /**
9715 * Promotes type information using given condition. 10338 * Promotes type information using given condition.
9716 */ 10339 */
9717 void promoteTypes(Expression condition) { 10340 void promoteTypes(Expression condition) {
9718 if (condition is BinaryExpression) { 10341 if (condition is BinaryExpression) {
9719 BinaryExpression binary = condition; 10342 BinaryExpression binary = condition;
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
10098 visitForEachStatementInScope(node); 10721 visitForEachStatementInScope(node);
10099 } finally { 10722 } finally {
10100 _labelScope = outerLabelScope; 10723 _labelScope = outerLabelScope;
10101 _nameScope = outerNameScope; 10724 _nameScope = outerNameScope;
10102 } 10725 }
10103 return null; 10726 return null;
10104 } 10727 }
10105 10728
10106 Object visitFormalParameterList(FormalParameterList node) { 10729 Object visitFormalParameterList(FormalParameterList node) {
10107 super.visitFormalParameterList(node); 10730 super.visitFormalParameterList(node);
10731 // We finished resolving function signature, now include formal parameters s cope.
10108 if (_nameScope is FunctionScope) { 10732 if (_nameScope is FunctionScope) {
10109 (_nameScope as FunctionScope).defineParameters(); 10733 (_nameScope as FunctionScope).defineParameters();
10110 } 10734 }
10111 if (_nameScope is FunctionTypeScope) { 10735 if (_nameScope is FunctionTypeScope) {
10112 (_nameScope as FunctionTypeScope).defineParameters(); 10736 (_nameScope as FunctionTypeScope).defineParameters();
10113 } 10737 }
10114 return null; 10738 return null;
10115 } 10739 }
10116 10740
10117 Object visitForStatement(ForStatement node) { 10741 Object visitForStatement(ForStatement node) {
(...skipping 20 matching lines...) Expand all
10138 _nameScope = outerScope; 10762 _nameScope = outerScope;
10139 } 10763 }
10140 if (function.enclosingElement is! CompilationUnitElement) { 10764 if (function.enclosingElement is! CompilationUnitElement) {
10141 _nameScope.define(function); 10765 _nameScope.define(function);
10142 } 10766 }
10143 return null; 10767 return null;
10144 } 10768 }
10145 10769
10146 Object visitFunctionExpression(FunctionExpression node) { 10770 Object visitFunctionExpression(FunctionExpression node) {
10147 if (node.parent is FunctionDeclaration) { 10771 if (node.parent is FunctionDeclaration) {
10772 // We have already created a function scope and don't need to do so again.
10148 super.visitFunctionExpression(node); 10773 super.visitFunctionExpression(node);
10149 } else { 10774 } else {
10150 Scope outerScope = _nameScope; 10775 Scope outerScope = _nameScope;
10151 try { 10776 try {
10152 ExecutableElement functionElement = node.element; 10777 ExecutableElement functionElement = node.element;
10153 if (functionElement == null) { 10778 if (functionElement == null) {
10154 } else { 10779 } else {
10155 _nameScope = new FunctionScope(_nameScope, functionElement); 10780 _nameScope = new FunctionScope(_nameScope, functionElement);
10156 } 10781 }
10157 super.visitFunctionExpression(node); 10782 super.visitFunctionExpression(node);
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
10325 } 10950 }
10326 10951
10327 /** 10952 /**
10328 * Visit the given statement after it's scope has been created. This replaces the normal call to 10953 * Visit the given statement after it's scope has been created. This replaces the normal call to
10329 * the inherited visit method so that ResolverVisitor can intervene when type propagation is 10954 * the inherited visit method so that ResolverVisitor can intervene when type propagation is
10330 * enabled. 10955 * enabled.
10331 * 10956 *
10332 * @param node the statement to be visited 10957 * @param node the statement to be visited
10333 */ 10958 */
10334 void visitForEachStatementInScope(ForEachStatement node) { 10959 void visitForEachStatementInScope(ForEachStatement node) {
10960 //
10961 // We visit the iterator before the loop variable because the loop variable cannot be in scope
10962 // while visiting the iterator.
10963 //
10335 safelyVisit(node.identifier); 10964 safelyVisit(node.identifier);
10336 safelyVisit(node.iterator); 10965 safelyVisit(node.iterator);
10337 safelyVisit(node.loopVariable); 10966 safelyVisit(node.loopVariable);
10338 visitStatementInScope(node.body); 10967 visitStatementInScope(node.body);
10339 } 10968 }
10340 10969
10341 /** 10970 /**
10342 * Visit the given statement after it's scope has been created. This replaces the normal call to 10971 * Visit the given statement after it's scope has been created. This replaces the normal call to
10343 * the inherited visit method so that ResolverVisitor can intervene when type propagation is 10972 * the inherited visit method so that ResolverVisitor can intervene when type propagation is
10344 * enabled. 10973 * enabled.
10345 * 10974 *
10346 * @param node the statement to be visited 10975 * @param node the statement to be visited
10347 */ 10976 */
10348 void visitForStatementInScope(ForStatement node) { 10977 void visitForStatementInScope(ForStatement node) {
10349 safelyVisit(node.variables); 10978 safelyVisit(node.variables);
10350 safelyVisit(node.initialization); 10979 safelyVisit(node.initialization);
10351 safelyVisit(node.condition); 10980 safelyVisit(node.condition);
10352 node.updaters.accept(this); 10981 node.updaters.accept(this);
10353 visitStatementInScope(node.body); 10982 visitStatementInScope(node.body);
10354 } 10983 }
10355 10984
10356 /** 10985 /**
10357 * Visit the given statement after it's scope has been created. This is used b y ResolverVisitor to 10986 * Visit the given statement after it's scope has been created. This is used b y ResolverVisitor to
10358 * correctly visit the 'then' and 'else' statements of an 'if' statement. 10987 * correctly visit the 'then' and 'else' statements of an 'if' statement.
10359 * 10988 *
10360 * @param node the statement to be visited 10989 * @param node the statement to be visited
10361 */ 10990 */
10362 void visitStatementInScope(Statement node) { 10991 void visitStatementInScope(Statement node) {
10363 if (node is Block) { 10992 if (node is Block) {
10993 // Don't create a scope around a block because the block will create it's own scope.
10364 visitBlock(node); 10994 visitBlock(node);
10365 } else if (node != null) { 10995 } else if (node != null) {
10366 Scope outerNameScope = _nameScope; 10996 Scope outerNameScope = _nameScope;
10367 try { 10997 try {
10368 _nameScope = new EnclosedScope(_nameScope); 10998 _nameScope = new EnclosedScope(_nameScope);
10369 node.accept(this); 10999 node.accept(this);
10370 } finally { 11000 } finally {
10371 _nameScope = outerNameScope; 11001 _nameScope = outerNameScope;
10372 } 11002 }
10373 } 11003 }
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
10738 * 11368 *
10739 * It is a static type warning if the type of e<sub>1</sub> may not be assigne d to `bool`. 11369 * It is a static type warning if the type of e<sub>1</sub> may not be assigne d to `bool`.
10740 * 11370 *
10741 * The static type of <i>c</i> is the least upper bound of the static type of <i>e<sub>2</sub></i> 11371 * The static type of <i>c</i> is the least upper bound of the static type of <i>e<sub>2</sub></i>
10742 * and the static type of <i>e<sub>3</sub></i>.</blockquote> 11372 * and the static type of <i>e<sub>3</sub></i>.</blockquote>
10743 */ 11373 */
10744 Object visitConditionalExpression(ConditionalExpression node) { 11374 Object visitConditionalExpression(ConditionalExpression node) {
10745 Type2 staticThenType = getStaticType(node.thenExpression); 11375 Type2 staticThenType = getStaticType(node.thenExpression);
10746 Type2 staticElseType = getStaticType(node.elseExpression); 11376 Type2 staticElseType = getStaticType(node.elseExpression);
10747 if (staticThenType == null) { 11377 if (staticThenType == null) {
11378 // TODO(brianwilkerson) Determine whether this can still happen.
10748 staticThenType = _dynamicType; 11379 staticThenType = _dynamicType;
10749 } 11380 }
10750 if (staticElseType == null) { 11381 if (staticElseType == null) {
11382 // TODO(brianwilkerson) Determine whether this can still happen.
10751 staticElseType = _dynamicType; 11383 staticElseType = _dynamicType;
10752 } 11384 }
10753 Type2 staticType = staticThenType.getLeastUpperBound(staticElseType); 11385 Type2 staticType = staticThenType.getLeastUpperBound(staticElseType);
10754 if (staticType == null) { 11386 if (staticType == null) {
10755 staticType = _dynamicType; 11387 staticType = _dynamicType;
10756 } 11388 }
10757 recordStaticType(node, staticType); 11389 recordStaticType(node, staticType);
10758 Type2 propagatedThenType = node.thenExpression.propagatedType; 11390 Type2 propagatedThenType = node.thenExpression.propagatedType;
10759 Type2 propagatedElseType = node.elseExpression.propagatedType; 11391 Type2 propagatedElseType = node.elseExpression.propagatedType;
10760 if (propagatedThenType != null || propagatedElseType != null) { 11392 if (propagatedThenType != null || propagatedElseType != null) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
10815 * 11447 *
10816 * The static type of a function literal of the form <i>(T<sub>1</sub> a<sub>1 </sub>, &hellip;, 11448 * The static type of a function literal of the form <i>(T<sub>1</sub> a<sub>1 </sub>, &hellip;,
10817 * T<sub>n</sub> a<sub>n</sub>, {T<sub>n+1</sub> x<sub>n+1</sub> : d1, &hellip ;, T<sub>n+k</sub> 11449 * T<sub>n</sub> a<sub>n</sub>, {T<sub>n+1</sub> x<sub>n+1</sub> : d1, &hellip ;, T<sub>n+k</sub>
10818 * x<sub>n+k</sub> : dk}) {s}</i> is <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub >, {T<sub>n+1</sub> 11450 * x<sub>n+k</sub> : dk}) {s}</i> is <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub >, {T<sub>n+1</sub>
10819 * x<sub>n+1</sub>, &hellip;, T<sub>n+k</sub> x<sub>n+k</sub>}) &rarr; dynamic </i>. In any case 11451 * x<sub>n+1</sub>, &hellip;, T<sub>n+k</sub> x<sub>n+k</sub>}) &rarr; dynamic </i>. In any case
10820 * where <i>T<sub>i</sub>, 1 &lt;= i &lt;= n</i>, is not specified, it is cons idered to have been 11452 * where <i>T<sub>i</sub>, 1 &lt;= i &lt;= n</i>, is not specified, it is cons idered to have been
10821 * specified as dynamic.</blockquote> 11453 * specified as dynamic.</blockquote>
10822 */ 11454 */
10823 Object visitFunctionExpression(FunctionExpression node) { 11455 Object visitFunctionExpression(FunctionExpression node) {
10824 if (node.parent is FunctionDeclaration) { 11456 if (node.parent is FunctionDeclaration) {
11457 // The function type will be resolved and set when we visit the parent nod e.
10825 return null; 11458 return null;
10826 } 11459 }
10827 ExecutableElementImpl functionElement = node.element as ExecutableElementImp l; 11460 ExecutableElementImpl functionElement = node.element as ExecutableElementImp l;
10828 functionElement.returnType = computeStaticReturnType3(node); 11461 functionElement.returnType = computeStaticReturnType3(node);
10829 recordPropagatedType(functionElement, node.body); 11462 recordPropagatedType(functionElement, node.body);
10830 recordStaticType(node, node.element.type); 11463 recordStaticType(node, node.element.type);
10831 return null; 11464 return null;
10832 } 11465 }
10833 11466
10834 /** 11467 /**
10835 * The Dart Language Specification, 12.14.4: <blockquote>A function expression invocation <i>i</i> 11468 * The Dart Language Specification, 12.14.4: <blockquote>A function expression invocation <i>i</i>
10836 * has the form <i>e<sub>f</sub>(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub >n+1</sub>: 11469 * has the form <i>e<sub>f</sub>(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub >n+1</sub>:
10837 * a<sub>n+1</sub>, &hellip;, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>, where <i> e<sub>f</sub></i> is 11470 * a<sub>n+1</sub>, &hellip;, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>, where <i> e<sub>f</sub></i> is
10838 * an expression. 11471 * an expression.
10839 * 11472 *
10840 * It is a static type warning if the static type <i>F</i> of <i>e<sub>f</sub> </i> may not be 11473 * It is a static type warning if the static type <i>F</i> of <i>e<sub>f</sub> </i> may not be
10841 * assigned to a function type. 11474 * assigned to a function type.
10842 * 11475 *
10843 * If <i>F</i> is not a function type, the static type of <i>i</i> is dynamic. Otherwise the 11476 * If <i>F</i> is not a function type, the static type of <i>i</i> is dynamic. Otherwise the
10844 * static type of <i>i</i> is the declared return type of <i>F</i>.</blockquot e> 11477 * static type of <i>i</i> is the declared return type of <i>F</i>.</blockquot e>
10845 */ 11478 */
10846 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 11479 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
10847 ExecutableElement staticMethodElement = node.staticElement; 11480 ExecutableElement staticMethodElement = node.staticElement;
11481 // Record static return type of the static element.
10848 Type2 staticStaticType = computeStaticReturnType(staticMethodElement); 11482 Type2 staticStaticType = computeStaticReturnType(staticMethodElement);
10849 recordStaticType(node, staticStaticType); 11483 recordStaticType(node, staticStaticType);
11484 // Record propagated return type of the static element.
10850 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement ); 11485 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement );
10851 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) { 11486 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) {
10852 recordPropagatedType2(node, staticPropagatedType); 11487 recordPropagatedType2(node, staticPropagatedType);
10853 } 11488 }
10854 ExecutableElement propagatedMethodElement = node.propagatedElement; 11489 ExecutableElement propagatedMethodElement = node.propagatedElement;
10855 if (propagatedMethodElement != staticMethodElement) { 11490 if (propagatedMethodElement != staticMethodElement) {
11491 // Record static return type of the propagated element.
10856 Type2 propagatedStaticType = computeStaticReturnType(propagatedMethodEleme nt); 11492 Type2 propagatedStaticType = computeStaticReturnType(propagatedMethodEleme nt);
10857 if (propagatedStaticType != null && (staticStaticType == null || propagate dStaticType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedType == nu ll || propagatedStaticType.isMoreSpecificThan(staticPropagatedType))) { 11493 if (propagatedStaticType != null && (staticStaticType == null || propagate dStaticType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedType == nu ll || propagatedStaticType.isMoreSpecificThan(staticPropagatedType))) {
10858 recordPropagatedType2(node, propagatedStaticType); 11494 recordPropagatedType2(node, propagatedStaticType);
10859 } 11495 }
11496 // Record propagated return type of the propagated element.
10860 Type2 propagatedPropagatedType = computePropagatedReturnType(propagatedMet hodElement); 11497 Type2 propagatedPropagatedType = computePropagatedReturnType(propagatedMet hodElement);
10861 if (propagatedPropagatedType != null && (staticStaticType == null || propa gatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedTy pe == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType)) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificThan (propagatedStaticType))) { 11498 if (propagatedPropagatedType != null && (staticStaticType == null || propa gatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedTy pe == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType)) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificThan (propagatedStaticType))) {
10862 recordPropagatedType2(node, propagatedPropagatedType); 11499 recordPropagatedType2(node, propagatedPropagatedType);
10863 } 11500 }
10864 } 11501 }
10865 return null; 11502 return null;
10866 } 11503 }
10867 11504
10868 /** 11505 /**
10869 * The Dart Language Specification, 12.29: <blockquote>An assignable expressio n of the form 11506 * The Dart Language Specification, 12.29: <blockquote>An assignable expressio n of the form
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
11099 * <i>S.m</i> exists, it is a static warning if the type <i>F</i> of <i>S.m</i > may not be 11736 * <i>S.m</i> exists, it is a static warning if the type <i>F</i> of <i>S.m</i > may not be
11100 * assigned to a function type. 11737 * assigned to a function type.
11101 * 11738 *
11102 * If <i>S.m</i> does not exist, or if <i>F</i> is not a function type, the st atic type of 11739 * If <i>S.m</i> does not exist, or if <i>F</i> is not a function type, the st atic type of
11103 * <i>i</i> is dynamic. Otherwise the static type of <i>i</i> is the declared return type of 11740 * <i>i</i> is dynamic. Otherwise the static type of <i>i</i> is the declared return type of
11104 * <i>F</i>.</blockquote> 11741 * <i>F</i>.</blockquote>
11105 */ 11742 */
11106 Object visitMethodInvocation(MethodInvocation node) { 11743 Object visitMethodInvocation(MethodInvocation node) {
11107 SimpleIdentifier methodNameNode = node.methodName; 11744 SimpleIdentifier methodNameNode = node.methodName;
11108 Element staticMethodElement = methodNameNode.staticElement; 11745 Element staticMethodElement = methodNameNode.staticElement;
11746 // Record types of the local variable invoked as a function.
11109 if (staticMethodElement is LocalVariableElement) { 11747 if (staticMethodElement is LocalVariableElement) {
11110 LocalVariableElement variable = staticMethodElement; 11748 LocalVariableElement variable = staticMethodElement;
11111 Type2 staticType = variable.type; 11749 Type2 staticType = variable.type;
11112 recordStaticType(methodNameNode, staticType); 11750 recordStaticType(methodNameNode, staticType);
11113 Type2 propagatedType = _overrideManager.getType(variable); 11751 Type2 propagatedType = _overrideManager.getType(variable);
11114 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType )) { 11752 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType )) {
11115 recordPropagatedType2(methodNameNode, propagatedType); 11753 recordPropagatedType2(methodNameNode, propagatedType);
11116 } 11754 }
11117 } 11755 }
11756 // Record static return type of the static element.
11118 Type2 staticStaticType = computeStaticReturnType(staticMethodElement); 11757 Type2 staticStaticType = computeStaticReturnType(staticMethodElement);
11119 recordStaticType(node, staticStaticType); 11758 recordStaticType(node, staticStaticType);
11759 // Record propagated return type of the static element.
11120 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement ); 11760 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement );
11121 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) { 11761 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) {
11122 recordPropagatedType2(node, staticPropagatedType); 11762 recordPropagatedType2(node, staticPropagatedType);
11123 } 11763 }
11124 String methodName = methodNameNode.name; 11764 String methodName = methodNameNode.name;
11765 // Future.then(closure) return type is:
11766 // 1) the returned Future type, if the closure returns a Future;
11767 // 2) Future<valueType>, if the closure returns a value.
11125 if (methodName == "then") { 11768 if (methodName == "then") {
11126 Expression target = node.realTarget; 11769 Expression target = node.realTarget;
11127 Type2 targetType = target == null ? null : target.bestType; 11770 Type2 targetType = target == null ? null : target.bestType;
11128 if (isAsyncFutureType(targetType)) { 11771 if (isAsyncFutureType(targetType)) {
11129 NodeList<Expression> arguments = node.argumentList.arguments; 11772 NodeList<Expression> arguments = node.argumentList.arguments;
11130 if (arguments.length == 1) { 11773 if (arguments.length == 1) {
11774 // TODO(brianwilkerson) Handle the case where both arguments are provi ded.
11131 Expression closureArg = arguments[0]; 11775 Expression closureArg = arguments[0];
11132 if (closureArg is FunctionExpression) { 11776 if (closureArg is FunctionExpression) {
11133 FunctionExpression closureExpr = closureArg; 11777 FunctionExpression closureExpr = closureArg;
11134 Type2 returnType = computePropagatedReturnType(closureExpr.element); 11778 Type2 returnType = computePropagatedReturnType(closureExpr.element);
11135 if (returnType != null) { 11779 if (returnType != null) {
11780 // prepare the type of the returned Future
11136 InterfaceTypeImpl newFutureType; 11781 InterfaceTypeImpl newFutureType;
11137 if (isAsyncFutureType(returnType)) { 11782 if (isAsyncFutureType(returnType)) {
11138 newFutureType = returnType as InterfaceTypeImpl; 11783 newFutureType = returnType as InterfaceTypeImpl;
11139 } else { 11784 } else {
11140 InterfaceType futureType = targetType as InterfaceType; 11785 InterfaceType futureType = targetType as InterfaceType;
11141 newFutureType = new InterfaceTypeImpl.con1(futureType.element); 11786 newFutureType = new InterfaceTypeImpl.con1(futureType.element);
11142 newFutureType.typeArguments = <Type2> [returnType]; 11787 newFutureType.typeArguments = <Type2> [returnType];
11143 } 11788 }
11789 // set the 'then' invocation type
11144 recordPropagatedType2(node, newFutureType); 11790 recordPropagatedType2(node, newFutureType);
11145 return null; 11791 return null;
11146 } 11792 }
11147 } 11793 }
11148 } 11794 }
11149 } 11795 }
11150 } 11796 }
11151 if (methodName == "\$dom_createEvent") { 11797 if (methodName == "\$dom_createEvent") {
11152 Expression target = node.realTarget; 11798 Expression target = node.realTarget;
11153 if (target != null) { 11799 if (target != null) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
11200 } 11846 }
11201 } 11847 }
11202 } else if (methodName == "JS") { 11848 } else if (methodName == "JS") {
11203 Type2 returnType = getFirstArgumentAsType(_typeProvider.objectType.element .library, node.argumentList); 11849 Type2 returnType = getFirstArgumentAsType(_typeProvider.objectType.element .library, node.argumentList);
11204 if (returnType != null) { 11850 if (returnType != null) {
11205 recordPropagatedType2(node, returnType); 11851 recordPropagatedType2(node, returnType);
11206 } 11852 }
11207 } else { 11853 } else {
11208 Element propagatedElement = methodNameNode.propagatedElement; 11854 Element propagatedElement = methodNameNode.propagatedElement;
11209 if (propagatedElement != staticMethodElement) { 11855 if (propagatedElement != staticMethodElement) {
11856 // Record static return type of the propagated element.
11210 Type2 propagatedStaticType = computeStaticReturnType(propagatedElement); 11857 Type2 propagatedStaticType = computeStaticReturnType(propagatedElement);
11211 if (propagatedStaticType != null && (staticStaticType == null || propaga tedStaticType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedType == null || propagatedStaticType.isMoreSpecificThan(staticPropagatedType))) { 11858 if (propagatedStaticType != null && (staticStaticType == null || propaga tedStaticType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedType == null || propagatedStaticType.isMoreSpecificThan(staticPropagatedType))) {
11212 recordPropagatedType2(node, propagatedStaticType); 11859 recordPropagatedType2(node, propagatedStaticType);
11213 } 11860 }
11861 // Record propagated return type of the propagated element.
11214 Type2 propagatedPropagatedType = computePropagatedReturnType(propagatedE lement); 11862 Type2 propagatedPropagatedType = computePropagatedReturnType(propagatedE lement);
11215 if (propagatedPropagatedType != null && (staticStaticType == null || pro pagatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagated Type == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType )) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificTh an(propagatedStaticType))) { 11863 if (propagatedPropagatedType != null && (staticStaticType == null || pro pagatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagated Type == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType )) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificTh an(propagatedStaticType))) {
11216 recordPropagatedType2(node, propagatedPropagatedType); 11864 recordPropagatedType2(node, propagatedPropagatedType);
11217 } 11865 }
11218 } 11866 }
11219 } 11867 }
11220 return null; 11868 return null;
11221 } 11869 }
11222 11870
11223 Object visitNamedExpression(NamedExpression node) { 11871 Object visitNamedExpression(NamedExpression node) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
11351 /** 11999 /**
11352 * The Dart Language Specification, 12.27: <blockquote>A unary expression <i>u </i> of the form 12000 * The Dart Language Specification, 12.27: <blockquote>A unary expression <i>u </i> of the form
11353 * <i>op e</i> is equivalent to a method invocation <i>expression e.op()</i>. An expression of the 12001 * <i>op e</i> is equivalent to a method invocation <i>expression e.op()</i>. An expression of the
11354 * form <i>op super</i> is equivalent to the method invocation <i>super.op()<i >.</blockquote> 12002 * form <i>op super</i> is equivalent to the method invocation <i>super.op()<i >.</blockquote>
11355 */ 12003 */
11356 Object visitPrefixExpression(PrefixExpression node) { 12004 Object visitPrefixExpression(PrefixExpression node) {
11357 sc.TokenType operator = node.operator.type; 12005 sc.TokenType operator = node.operator.type;
11358 if (identical(operator, sc.TokenType.BANG)) { 12006 if (identical(operator, sc.TokenType.BANG)) {
11359 recordStaticType(node, _typeProvider.boolType); 12007 recordStaticType(node, _typeProvider.boolType);
11360 } else { 12008 } else {
12009 // The other cases are equivalent to invoking a method.
11361 ExecutableElement staticMethodElement = node.staticElement; 12010 ExecutableElement staticMethodElement = node.staticElement;
11362 Type2 staticType = computeStaticReturnType(staticMethodElement); 12011 Type2 staticType = computeStaticReturnType(staticMethodElement);
11363 if (identical(operator, sc.TokenType.MINUS_MINUS) || identical(operator, s c.TokenType.PLUS_PLUS)) { 12012 if (identical(operator, sc.TokenType.MINUS_MINUS) || identical(operator, s c.TokenType.PLUS_PLUS)) {
11364 Type2 intType = _typeProvider.intType; 12013 Type2 intType = _typeProvider.intType;
11365 if (identical(getStaticType(node.operand), intType)) { 12014 if (identical(getStaticType(node.operand), intType)) {
11366 staticType = intType; 12015 staticType = intType;
11367 } 12016 }
11368 } 12017 }
11369 recordStaticType(node, staticType); 12018 recordStaticType(node, staticType);
11370 MethodElement propagatedMethodElement = node.propagatedElement; 12019 MethodElement propagatedMethodElement = node.propagatedElement;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
11426 Element element = propertyName.staticElement; 12075 Element element = propertyName.staticElement;
11427 Type2 staticType = _dynamicType; 12076 Type2 staticType = _dynamicType;
11428 if (element is MethodElement) { 12077 if (element is MethodElement) {
11429 staticType = element.type; 12078 staticType = element.type;
11430 } else if (element is PropertyAccessorElement) { 12079 } else if (element is PropertyAccessorElement) {
11431 staticType = getType(element, node.target != null ? getStaticType(node.tar get) : null); 12080 staticType = getType(element, node.target != null ? getStaticType(node.tar get) : null);
11432 } else { 12081 } else {
11433 } 12082 }
11434 recordStaticType(propertyName, staticType); 12083 recordStaticType(propertyName, staticType);
11435 recordStaticType(node, staticType); 12084 recordStaticType(node, staticType);
12085 // TODO(brianwilkerson) I think we want to repeat the logic above using the propagated element
12086 // to get another candidate for the propagated type.
11436 Type2 propagatedType = _overrideManager.getType(element); 12087 Type2 propagatedType = _overrideManager.getType(element);
11437 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType)) { 12088 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType)) {
11438 recordPropagatedType2(node, propagatedType); 12089 recordPropagatedType2(node, propagatedType);
11439 } 12090 }
11440 return null; 12091 return null;
11441 } 12092 }
11442 12093
11443 /** 12094 /**
11444 * The Dart Language Specification, 12.9: <blockquote>The static type of a ret hrow expression is 12095 * The Dart Language Specification, 12.9: <blockquote>The static type of a ret hrow expression is
11445 * bottom.</blockquote> 12096 * bottom.</blockquote>
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
11506 } else { 12157 } else {
11507 staticType = _typeProvider.typeType; 12158 staticType = _typeProvider.typeType;
11508 } 12159 }
11509 } else if (element is MethodElement) { 12160 } else if (element is MethodElement) {
11510 staticType = element.type; 12161 staticType = element.type;
11511 } else if (element is PropertyAccessorElement) { 12162 } else if (element is PropertyAccessorElement) {
11512 staticType = getType(element, null); 12163 staticType = getType(element, null);
11513 } else if (element is ExecutableElement) { 12164 } else if (element is ExecutableElement) {
11514 staticType = element.type; 12165 staticType = element.type;
11515 } else if (element is TypeParameterElement) { 12166 } else if (element is TypeParameterElement) {
12167 // if (isTypeName(node)) {
11516 staticType = element.type; 12168 staticType = element.type;
11517 } else if (element is VariableElement) { 12169 } else if (element is VariableElement) {
11518 VariableElement variable = element; 12170 VariableElement variable = element;
11519 staticType = _promoteManager.getStaticType(variable); 12171 staticType = _promoteManager.getStaticType(variable);
11520 } else if (element is PrefixElement) { 12172 } else if (element is PrefixElement) {
11521 return null; 12173 return null;
11522 } else { 12174 } else {
11523 staticType = _dynamicType; 12175 staticType = _dynamicType;
11524 } 12176 }
11525 recordStaticType(node, staticType); 12177 recordStaticType(node, staticType);
12178 // TODO(brianwilkerson) I think we want to repeat the logic above using the propagated element
12179 // to get another candidate for the propagated type.
11526 Type2 propagatedType = _overrideManager.getType(element); 12180 Type2 propagatedType = _overrideManager.getType(element);
11527 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType)) { 12181 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType)) {
11528 recordPropagatedType2(node, propagatedType); 12182 recordPropagatedType2(node, propagatedType);
11529 } 12183 }
11530 return null; 12184 return null;
11531 } 12185 }
11532 12186
11533 /** 12187 /**
11534 * The Dart Language Specification, 12.5: <blockquote>The static type of a str ing literal is 12188 * The Dart Language Specification, 12.5: <blockquote>The static type of a str ing literal is
11535 * `String`.</blockquote> 12189 * `String`.</blockquote>
11536 */ 12190 */
11537 Object visitSimpleStringLiteral(SimpleStringLiteral node) { 12191 Object visitSimpleStringLiteral(SimpleStringLiteral node) {
11538 recordStaticType(node, _typeProvider.stringType); 12192 recordStaticType(node, _typeProvider.stringType);
11539 return null; 12193 return null;
11540 } 12194 }
11541 12195
11542 /** 12196 /**
11543 * The Dart Language Specification, 12.5: <blockquote>The static type of a str ing literal is 12197 * The Dart Language Specification, 12.5: <blockquote>The static type of a str ing literal is
11544 * `String`.</blockquote> 12198 * `String`.</blockquote>
11545 */ 12199 */
11546 Object visitStringInterpolation(StringInterpolation node) { 12200 Object visitStringInterpolation(StringInterpolation node) {
11547 recordStaticType(node, _typeProvider.stringType); 12201 recordStaticType(node, _typeProvider.stringType);
11548 return null; 12202 return null;
11549 } 12203 }
11550 12204
11551 Object visitSuperExpression(SuperExpression node) { 12205 Object visitSuperExpression(SuperExpression node) {
11552 if (_thisType == null) { 12206 if (_thisType == null) {
12207 // TODO(brianwilkerson) Report this error if it hasn't already been report ed
11553 recordStaticType(node, _dynamicType); 12208 recordStaticType(node, _dynamicType);
11554 } else { 12209 } else {
11555 recordStaticType(node, _thisType); 12210 recordStaticType(node, _thisType);
11556 } 12211 }
11557 return null; 12212 return null;
11558 } 12213 }
11559 12214
11560 Object visitSymbolLiteral(SymbolLiteral node) { 12215 Object visitSymbolLiteral(SymbolLiteral node) {
11561 recordStaticType(node, _typeProvider.symbolType); 12216 recordStaticType(node, _typeProvider.symbolType);
11562 return null; 12217 return null;
11563 } 12218 }
11564 12219
11565 /** 12220 /**
11566 * The Dart Language Specification, 12.10: <blockquote>The static type of `thi s` is the 12221 * The Dart Language Specification, 12.10: <blockquote>The static type of `thi s` is the
11567 * interface of the immediately enclosing class.</blockquote> 12222 * interface of the immediately enclosing class.</blockquote>
11568 */ 12223 */
11569 Object visitThisExpression(ThisExpression node) { 12224 Object visitThisExpression(ThisExpression node) {
11570 if (_thisType == null) { 12225 if (_thisType == null) {
12226 // TODO(brianwilkerson) Report this error if it hasn't already been report ed
11571 recordStaticType(node, _dynamicType); 12227 recordStaticType(node, _dynamicType);
11572 } else { 12228 } else {
11573 recordStaticType(node, _thisType); 12229 recordStaticType(node, _thisType);
11574 } 12230 }
11575 return null; 12231 return null;
11576 } 12232 }
11577 12233
11578 /** 12234 /**
11579 * The Dart Language Specification, 12.8: <blockquote>The static type of a thr ow expression is 12235 * The Dart Language Specification, 12.8: <blockquote>The static type of a thr ow expression is
11580 * bottom.</blockquote> 12236 * bottom.</blockquote>
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
11649 } 12305 }
11650 12306
11651 /** 12307 /**
11652 * Compute the static return type of the method or function represented by the given element. 12308 * Compute the static return type of the method or function represented by the given element.
11653 * 12309 *
11654 * @param element the element representing the method or function invoked by t he given node 12310 * @param element the element representing the method or function invoked by t he given node
11655 * @return the static return type that was computed 12311 * @return the static return type that was computed
11656 */ 12312 */
11657 Type2 computeStaticReturnType(Element element) { 12313 Type2 computeStaticReturnType(Element element) {
11658 if (element is PropertyAccessorElement) { 12314 if (element is PropertyAccessorElement) {
12315 //
12316 // This is a function invocation expression disguised as something else. W e are invoking a
12317 // getter and then invoking the returned function.
12318 //
11659 FunctionType propertyType = element.type; 12319 FunctionType propertyType = element.type;
11660 if (propertyType != null) { 12320 if (propertyType != null) {
11661 Type2 returnType = propertyType.returnType; 12321 Type2 returnType = propertyType.returnType;
11662 if (returnType.isDartCoreFunction) { 12322 if (returnType.isDartCoreFunction) {
11663 return _dynamicType; 12323 return _dynamicType;
11664 } else if (returnType is InterfaceType) { 12324 } else if (returnType is InterfaceType) {
11665 MethodElement callMethod = returnType.lookUpMethod(ElementResolver.CAL L_METHOD_NAME, _resolver.definingLibrary); 12325 MethodElement callMethod = returnType.lookUpMethod(ElementResolver.CAL L_METHOD_NAME, _resolver.definingLibrary);
11666 if (callMethod != null) { 12326 if (callMethod != null) {
11667 return callMethod.type.returnType; 12327 return callMethod.type.returnType;
11668 } 12328 }
11669 } else if (returnType is FunctionType) { 12329 } else if (returnType is FunctionType) {
11670 Type2 innerReturnType = returnType.returnType; 12330 Type2 innerReturnType = returnType.returnType;
11671 if (innerReturnType != null) { 12331 if (innerReturnType != null) {
11672 return innerReturnType; 12332 return innerReturnType;
11673 } 12333 }
11674 } 12334 }
11675 if (returnType != null) { 12335 if (returnType != null) {
11676 return returnType; 12336 return returnType;
11677 } 12337 }
11678 } 12338 }
11679 } else if (element is ExecutableElement) { 12339 } else if (element is ExecutableElement) {
11680 FunctionType type = element.type; 12340 FunctionType type = element.type;
11681 if (type != null) { 12341 if (type != null) {
12342 // TODO(brianwilkerson) Figure out the conditions under which the type i s null.
11682 return type.returnType; 12343 return type.returnType;
11683 } 12344 }
11684 } else if (element is VariableElement) { 12345 } else if (element is VariableElement) {
11685 VariableElement variable = element; 12346 VariableElement variable = element;
11686 Type2 variableType = _promoteManager.getStaticType(variable); 12347 Type2 variableType = _promoteManager.getStaticType(variable);
11687 if (variableType is FunctionType) { 12348 if (variableType is FunctionType) {
11688 return variableType.returnType; 12349 return variableType.returnType;
11689 } 12350 }
11690 } 12351 }
11691 return _dynamicType; 12352 return _dynamicType;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
11750 * string literal, then parse that argument as a query string and return the t ype specified by the 12411 * string literal, then parse that argument as a query string and return the t ype specified by the
11751 * argument. 12412 * argument.
11752 * 12413 *
11753 * @param library the library in which the specified type would be defined 12414 * @param library the library in which the specified type would be defined
11754 * @param argumentList the list of arguments from which a type is to be extrac ted 12415 * @param argumentList the list of arguments from which a type is to be extrac ted
11755 * @return the type specified by the first argument in the argument list 12416 * @return the type specified by the first argument in the argument list
11756 */ 12417 */
11757 Type2 getFirstArgumentAsQuery(LibraryElement library, ArgumentList argumentLis t) { 12418 Type2 getFirstArgumentAsQuery(LibraryElement library, ArgumentList argumentLis t) {
11758 String argumentValue = getFirstArgumentAsString(argumentList); 12419 String argumentValue = getFirstArgumentAsString(argumentList);
11759 if (argumentValue != null) { 12420 if (argumentValue != null) {
12421 //
12422 // If the query has spaces, full parsing is required because it might be:
12423 // E[text='warning text']
12424 //
11760 if (argumentValue.contains(" ")) { 12425 if (argumentValue.contains(" ")) {
11761 return null; 12426 return null;
11762 } 12427 }
12428 //
12429 // Otherwise, try to extract the tag based on http://www.w3.org/TR/CSS2/se lector.html.
12430 //
11763 String tag = argumentValue; 12431 String tag = argumentValue;
11764 tag = StringUtilities.substringBefore(tag, ":"); 12432 tag = StringUtilities.substringBefore(tag, ":");
11765 tag = StringUtilities.substringBefore(tag, "["); 12433 tag = StringUtilities.substringBefore(tag, "[");
11766 tag = StringUtilities.substringBefore(tag, "."); 12434 tag = StringUtilities.substringBefore(tag, ".");
11767 tag = StringUtilities.substringBefore(tag, "#"); 12435 tag = StringUtilities.substringBefore(tag, "#");
11768 tag = _HTML_ELEMENT_TO_CLASS_MAP[tag.toLowerCase()]; 12436 tag = _HTML_ELEMENT_TO_CLASS_MAP[tag.toLowerCase()];
11769 ClassElement returnType = library.getType(tag); 12437 ClassElement returnType = library.getType(tag);
11770 if (returnType != null) { 12438 if (returnType != null) {
11771 return returnType.type; 12439 return returnType.type;
11772 } 12440 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
11817 12485
11818 /** 12486 /**
11819 * Return the static type of the given expression. 12487 * Return the static type of the given expression.
11820 * 12488 *
11821 * @param expression the expression whose type is to be returned 12489 * @param expression the expression whose type is to be returned
11822 * @return the static type of the given expression 12490 * @return the static type of the given expression
11823 */ 12491 */
11824 Type2 getStaticType(Expression expression) { 12492 Type2 getStaticType(Expression expression) {
11825 Type2 type = expression.staticType; 12493 Type2 type = expression.staticType;
11826 if (type == null) { 12494 if (type == null) {
12495 // TODO(brianwilkerson) Determine the conditions for which the static type is null.
11827 return _dynamicType; 12496 return _dynamicType;
11828 } 12497 }
11829 return type; 12498 return type;
11830 } 12499 }
11831 12500
11832 /** 12501 /**
11833 * Return the type that should be recorded for a node that resolved to the giv en accessor. 12502 * Return the type that should be recorded for a node that resolved to the giv en accessor.
11834 * 12503 *
11835 * @param accessor the accessor that the node resolved to 12504 * @param accessor the accessor that the node resolved to
11836 * @param context if the accessor element has context [by being the RHS of a 12505 * @param context if the accessor element has context [by being the RHS of a
11837 * [PrefixedIdentifier] or [PropertyAccess]], and the return type of the 12506 * [PrefixedIdentifier] or [PropertyAccess]], and the return type of the
11838 * accessor is a parameter type, then the type of the LHS can be used to get more 12507 * accessor is a parameter type, then the type of the LHS can be used to get more
11839 * specific type information 12508 * specific type information
11840 * @return the type that should be recorded for a node that resolved to the gi ven accessor 12509 * @return the type that should be recorded for a node that resolved to the gi ven accessor
11841 */ 12510 */
11842 Type2 getType(PropertyAccessorElement accessor, Type2 context) { 12511 Type2 getType(PropertyAccessorElement accessor, Type2 context) {
11843 FunctionType functionType = accessor.type; 12512 FunctionType functionType = accessor.type;
11844 if (functionType == null) { 12513 if (functionType == null) {
12514 // TODO(brianwilkerson) Report this internal error. This happens when we a re analyzing a
12515 // reference to a property before we have analyzed the declaration of the property or when
12516 // the property does not have a defined type.
11845 return _dynamicType; 12517 return _dynamicType;
11846 } 12518 }
11847 if (accessor.isSetter) { 12519 if (accessor.isSetter) {
11848 List<Type2> parameterTypes = functionType.normalParameterTypes; 12520 List<Type2> parameterTypes = functionType.normalParameterTypes;
11849 if (parameterTypes != null && parameterTypes.length > 0) { 12521 if (parameterTypes != null && parameterTypes.length > 0) {
11850 return parameterTypes[0]; 12522 return parameterTypes[0];
11851 } 12523 }
11852 PropertyAccessorElement getter = accessor.variable.getter; 12524 PropertyAccessorElement getter = accessor.variable.getter;
11853 if (getter != null) { 12525 if (getter != null) {
11854 functionType = getter.type; 12526 functionType = getter.type;
11855 if (functionType != null) { 12527 if (functionType != null) {
11856 return functionType.returnType; 12528 return functionType.returnType;
11857 } 12529 }
11858 } 12530 }
11859 return _dynamicType; 12531 return _dynamicType;
11860 } 12532 }
11861 Type2 returnType = functionType.returnType; 12533 Type2 returnType = functionType.returnType;
11862 if (returnType is TypeParameterType && context is InterfaceType) { 12534 if (returnType is TypeParameterType && context is InterfaceType) {
12535 // if the return type is a TypeParameter, we try to use the context [that the function is being
12536 // called on] to get a more accurate returnType type
11863 InterfaceType interfaceTypeContext = context; 12537 InterfaceType interfaceTypeContext = context;
12538 // Type[] argumentTypes = interfaceTypeContext.getTypeArguments();
11864 List<TypeParameterElement> typeParameterElements = interfaceTypeContext.el ement != null ? interfaceTypeContext.element.typeParameters : null; 12539 List<TypeParameterElement> typeParameterElements = interfaceTypeContext.el ement != null ? interfaceTypeContext.element.typeParameters : null;
11865 if (typeParameterElements != null) { 12540 if (typeParameterElements != null) {
11866 for (int i = 0; i < typeParameterElements.length; i++) { 12541 for (int i = 0; i < typeParameterElements.length; i++) {
11867 TypeParameterElement typeParameterElement = typeParameterElements[i]; 12542 TypeParameterElement typeParameterElement = typeParameterElements[i];
11868 if (returnType.name == typeParameterElement.name) { 12543 if (returnType.name == typeParameterElement.name) {
11869 return interfaceTypeContext.typeArguments[i]; 12544 return interfaceTypeContext.typeArguments[i];
11870 } 12545 }
11871 } 12546 }
11872 } 12547 }
11873 } 12548 }
11874 return returnType; 12549 return returnType;
11875 } 12550 }
11876 12551
11877 /** 12552 /**
11878 * Return the type represented by the given type name. 12553 * Return the type represented by the given type name.
11879 * 12554 *
11880 * @param typeName the type name representing the type to be returned 12555 * @param typeName the type name representing the type to be returned
11881 * @return the type represented by the type name 12556 * @return the type represented by the type name
11882 */ 12557 */
11883 Type2 getType2(TypeName typeName) { 12558 Type2 getType2(TypeName typeName) {
11884 Type2 type = typeName.type; 12559 Type2 type = typeName.type;
11885 if (type == null) { 12560 if (type == null) {
12561 //TODO(brianwilkerson) Determine the conditions for which the type is null .
11886 return _dynamicType; 12562 return _dynamicType;
11887 } 12563 }
11888 return type; 12564 return type;
11889 } 12565 }
11890 12566
11891 /** 12567 /**
11892 * Return `true` if the given [Type] is the `Future` form the 'dart:async' 12568 * Return `true` if the given [Type] is the `Future` form the 'dart:async'
11893 * library. 12569 * library.
11894 */ 12570 */
11895 bool isAsyncFutureType(Type2 type) => type is InterfaceType && type.name == "F uture" && isAsyncLibrary(type.element.library); 12571 bool isAsyncFutureType(Type2 type) => type is InterfaceType && type.name == "F uture" && isAsyncLibrary(type.element.library);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
11928 * @param functionElement the function element to record propagated return typ e for 12604 * @param functionElement the function element to record propagated return typ e for
11929 * @param body the boy of the function whose propagated return type is to be c omputed 12605 * @param body the boy of the function whose propagated return type is to be c omputed
11930 * @return the propagated return type that was computed, may be `null` if it i s not more 12606 * @return the propagated return type that was computed, may be `null` if it i s not more
11931 * specific than the static return type. 12607 * specific than the static return type.
11932 */ 12608 */
11933 void recordPropagatedType(ExecutableElement functionElement, FunctionBody body ) { 12609 void recordPropagatedType(ExecutableElement functionElement, FunctionBody body ) {
11934 Type2 propagatedReturnType = computePropagatedReturnType2(body); 12610 Type2 propagatedReturnType = computePropagatedReturnType2(body);
11935 if (propagatedReturnType == null) { 12611 if (propagatedReturnType == null) {
11936 return; 12612 return;
11937 } 12613 }
12614 // Ignore 'bottom' type.
11938 if (propagatedReturnType.isBottom) { 12615 if (propagatedReturnType.isBottom) {
11939 return; 12616 return;
11940 } 12617 }
12618 // Record only if we inferred more specific type.
11941 Type2 staticReturnType = functionElement.returnType; 12619 Type2 staticReturnType = functionElement.returnType;
11942 if (!propagatedReturnType.isMoreSpecificThan(staticReturnType)) { 12620 if (!propagatedReturnType.isMoreSpecificThan(staticReturnType)) {
11943 return; 12621 return;
11944 } 12622 }
12623 // OK, do record.
11945 _propagatedReturnTypes[functionElement] = propagatedReturnType; 12624 _propagatedReturnTypes[functionElement] = propagatedReturnType;
11946 } 12625 }
11947 12626
11948 /** 12627 /**
11949 * Record that the propagated type of the given node is the given type. 12628 * Record that the propagated type of the given node is the given type.
11950 * 12629 *
11951 * @param expression the node whose type is to be recorded 12630 * @param expression the node whose type is to be recorded
11952 * @param type the propagated type of the node 12631 * @param type the propagated type of the node
11953 */ 12632 */
11954 void recordPropagatedType2(Expression expression, Type2 type) { 12633 void recordPropagatedType2(Expression expression, Type2 type) {
(...skipping 18 matching lines...) Expand all
11973 12652
11974 /** 12653 /**
11975 * Attempts to make a better guess for the static type of the given binary exp ression. 12654 * Attempts to make a better guess for the static type of the given binary exp ression.
11976 * 12655 *
11977 * @param node the binary expression to analyze 12656 * @param node the binary expression to analyze
11978 * @param staticType the static type of the expression as resolved 12657 * @param staticType the static type of the expression as resolved
11979 * @return the better type guess, or the same static type as given 12658 * @return the better type guess, or the same static type as given
11980 */ 12659 */
11981 Type2 refineBinaryExpressionType(BinaryExpression node, Type2 staticType) { 12660 Type2 refineBinaryExpressionType(BinaryExpression node, Type2 staticType) {
11982 sc.TokenType operator = node.operator.type; 12661 sc.TokenType operator = node.operator.type;
12662 // bool
11983 if (identical(operator, sc.TokenType.AMPERSAND_AMPERSAND) || identical(opera tor, sc.TokenType.BAR_BAR) || identical(operator, sc.TokenType.EQ_EQ) || identic al(operator, sc.TokenType.BANG_EQ)) { 12663 if (identical(operator, sc.TokenType.AMPERSAND_AMPERSAND) || identical(opera tor, sc.TokenType.BAR_BAR) || identical(operator, sc.TokenType.EQ_EQ) || identic al(operator, sc.TokenType.BANG_EQ)) {
11984 return _typeProvider.boolType; 12664 return _typeProvider.boolType;
11985 } 12665 }
11986 Type2 intType = _typeProvider.intType; 12666 Type2 intType = _typeProvider.intType;
11987 if (getStaticType(node.leftOperand) == intType) { 12667 if (getStaticType(node.leftOperand) == intType) {
12668 // int op double
11988 if (identical(operator, sc.TokenType.MINUS) || identical(operator, sc.Toke nType.PERCENT) || identical(operator, sc.TokenType.PLUS) || identical(operator, sc.TokenType.STAR)) { 12669 if (identical(operator, sc.TokenType.MINUS) || identical(operator, sc.Toke nType.PERCENT) || identical(operator, sc.TokenType.PLUS) || identical(operator, sc.TokenType.STAR)) {
11989 Type2 doubleType = _typeProvider.doubleType; 12670 Type2 doubleType = _typeProvider.doubleType;
11990 if (getStaticType(node.rightOperand) == doubleType) { 12671 if (getStaticType(node.rightOperand) == doubleType) {
11991 return doubleType; 12672 return doubleType;
11992 } 12673 }
11993 } 12674 }
12675 // int op int
11994 if (identical(operator, sc.TokenType.MINUS) || identical(operator, sc.Toke nType.PERCENT) || identical(operator, sc.TokenType.PLUS) || identical(operator, sc.TokenType.STAR) || identical(operator, sc.TokenType.TILDE_SLASH)) { 12676 if (identical(operator, sc.TokenType.MINUS) || identical(operator, sc.Toke nType.PERCENT) || identical(operator, sc.TokenType.PLUS) || identical(operator, sc.TokenType.STAR) || identical(operator, sc.TokenType.TILDE_SLASH)) {
11995 if (getStaticType(node.rightOperand) == intType) { 12677 if (getStaticType(node.rightOperand) == intType) {
11996 staticType = intType; 12678 staticType = intType;
11997 } 12679 }
11998 } 12680 }
11999 } 12681 }
12682 // default
12000 return staticType; 12683 return staticType;
12001 } 12684 }
12002 12685
12003 get thisType_J2DAccessor => _thisType; 12686 get thisType_J2DAccessor => _thisType;
12004 12687
12005 set thisType_J2DAccessor(__v) => _thisType = __v; 12688 set thisType_J2DAccessor(__v) => _thisType = __v;
12006 } 12689 }
12007 12690
12008 class GeneralizingASTVisitor_StaticTypeAnalyzer_computePropagatedReturnType2 ext ends GeneralizingASTVisitor<Object> { 12691 class GeneralizingASTVisitor_StaticTypeAnalyzer_computePropagatedReturnType2 ext ends GeneralizingASTVisitor<Object> {
12009 List<Type2> result; 12692 List<Type2> result;
12010 12693
12011 GeneralizingASTVisitor_StaticTypeAnalyzer_computePropagatedReturnType2(this.re sult) : super(); 12694 GeneralizingASTVisitor_StaticTypeAnalyzer_computePropagatedReturnType2(this.re sult) : super();
12012 12695
12013 Object visitExpression(Expression node) => null; 12696 Object visitExpression(Expression node) => null;
12014 12697
12015 Object visitReturnStatement(ReturnStatement node) { 12698 Object visitReturnStatement(ReturnStatement node) {
12699 // prepare this 'return' type
12016 Type2 type; 12700 Type2 type;
12017 Expression expression = node.expression; 12701 Expression expression = node.expression;
12018 if (expression != null) { 12702 if (expression != null) {
12019 type = expression.bestType; 12703 type = expression.bestType;
12020 } else { 12704 } else {
12021 type = BottomTypeImpl.instance; 12705 type = BottomTypeImpl.instance;
12022 } 12706 }
12707 // merge types
12023 if (result[0] == null) { 12708 if (result[0] == null) {
12024 result[0] = type; 12709 result[0] = type;
12025 } else { 12710 } else {
12026 result[0] = result[0].getLeastUpperBound(type); 12711 result[0] = result[0].getLeastUpperBound(type);
12027 } 12712 }
12028 return null; 12713 return null;
12029 } 12714 }
12030 } 12715 }
12031 12716
12032 /** 12717 /**
(...skipping 12 matching lines...) Expand all
12045 * libraries visited by this manager. 12730 * libraries visited by this manager.
12046 */ 12731 */
12047 Set<LibraryElement> _visitedLibraries = new Set<LibraryElement>(); 12732 Set<LibraryElement> _visitedLibraries = new Set<LibraryElement>();
12048 12733
12049 /** 12734 /**
12050 * Given some [ClassElement], return the set of all subtypes, and subtypes of subtypes. 12735 * Given some [ClassElement], return the set of all subtypes, and subtypes of subtypes.
12051 * 12736 *
12052 * @param classElement the class to recursively return the set of subtypes of 12737 * @param classElement the class to recursively return the set of subtypes of
12053 */ 12738 */
12054 Set<ClassElement> computeAllSubtypes(ClassElement classElement) { 12739 Set<ClassElement> computeAllSubtypes(ClassElement classElement) {
12740 // Ensure that we have generated the subtype map for the library
12055 computeSubtypesInLibrary(classElement.library); 12741 computeSubtypesInLibrary(classElement.library);
12742 // use the subtypeMap to compute the set of all subtypes and subtype's subty pes
12056 Set<ClassElement> allSubtypes = new Set<ClassElement>(); 12743 Set<ClassElement> allSubtypes = new Set<ClassElement>();
12057 computeAllSubtypes2(classElement, new Set<ClassElement>(), allSubtypes); 12744 computeAllSubtypes2(classElement, new Set<ClassElement>(), allSubtypes);
12058 return allSubtypes; 12745 return allSubtypes;
12059 } 12746 }
12060 12747
12061 /** 12748 /**
12062 * Given some [LibraryElement], visit all of the types in the library, the pas sed library, 12749 * Given some [LibraryElement], visit all of the types in the library, the pas sed library,
12063 * and any imported libraries, will be in the [visitedLibraries] set. 12750 * and any imported libraries, will be in the [visitedLibraries] set.
12064 * 12751 *
12065 * @param libraryElement the library to visit, it it hasn't been visited alrea dy 12752 * @param libraryElement the library to visit, it it hasn't been visited alrea dy
12066 */ 12753 */
12067 void ensureLibraryVisited(LibraryElement libraryElement) { 12754 void ensureLibraryVisited(LibraryElement libraryElement) {
12068 computeSubtypesInLibrary(libraryElement); 12755 computeSubtypesInLibrary(libraryElement);
12069 } 12756 }
12070 12757
12071 /** 12758 /**
12072 * Given some [ClassElement] and a [HashSet<ClassElement>], this method recurs ively 12759 * Given some [ClassElement] and a [HashSet<ClassElement>], this method recurs ively
12073 * adds all of the subtypes of the [ClassElement] to the passed array. 12760 * adds all of the subtypes of the [ClassElement] to the passed array.
12074 * 12761 *
12075 * @param classElement the type to compute the set of subtypes of 12762 * @param classElement the type to compute the set of subtypes of
12076 * @param visitedClasses the set of class elements that this method has alread y recursively seen 12763 * @param visitedClasses the set of class elements that this method has alread y recursively seen
12077 * @param allSubtypes the computed set of subtypes of the passed class element 12764 * @param allSubtypes the computed set of subtypes of the passed class element
12078 */ 12765 */
12079 void computeAllSubtypes2(ClassElement classElement, Set<ClassElement> visitedC lasses, Set<ClassElement> allSubtypes) { 12766 void computeAllSubtypes2(ClassElement classElement, Set<ClassElement> visitedC lasses, Set<ClassElement> allSubtypes) {
12080 if (!visitedClasses.add(classElement)) { 12767 if (!visitedClasses.add(classElement)) {
12768 // if this class has already been called on this class element
12081 return; 12769 return;
12082 } 12770 }
12083 Set<ClassElement> subtypes = _subtypeMap[classElement]; 12771 Set<ClassElement> subtypes = _subtypeMap[classElement];
12084 if (subtypes == null) { 12772 if (subtypes == null) {
12085 return; 12773 return;
12086 } 12774 }
12087 for (ClassElement subtype in subtypes) { 12775 for (ClassElement subtype in subtypes) {
12088 computeAllSubtypes2(subtype, visitedClasses, allSubtypes); 12776 computeAllSubtypes2(subtype, visitedClasses, allSubtypes);
12089 } 12777 }
12090 allSubtypes.addAll(subtypes); 12778 allSubtypes.addAll(subtypes);
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after
12873 * during resolution 13561 * during resolution
12874 */ 13562 */
12875 TypeResolverVisitor.con3(LibraryElement definingLibrary, Source source, TypePr ovider typeProvider, Scope nameScope, AnalysisErrorListener errorListener) : sup er.con3(definingLibrary, source, typeProvider, nameScope, errorListener) { 13563 TypeResolverVisitor.con3(LibraryElement definingLibrary, Source source, TypePr ovider typeProvider, Scope nameScope, AnalysisErrorListener errorListener) : sup er.con3(definingLibrary, source, typeProvider, nameScope, errorListener) {
12876 _dynamicType = typeProvider.dynamicType; 13564 _dynamicType = typeProvider.dynamicType;
12877 } 13565 }
12878 13566
12879 Object visitCatchClause(CatchClause node) { 13567 Object visitCatchClause(CatchClause node) {
12880 super.visitCatchClause(node); 13568 super.visitCatchClause(node);
12881 SimpleIdentifier exception = node.exceptionParameter; 13569 SimpleIdentifier exception = node.exceptionParameter;
12882 if (exception != null) { 13570 if (exception != null) {
13571 // If an 'on' clause is provided the type of the exception parameter is th e type in the 'on'
13572 // clause. Otherwise, the type of the exception parameter is 'Object'.
12883 TypeName exceptionTypeName = node.exceptionType; 13573 TypeName exceptionTypeName = node.exceptionType;
12884 Type2 exceptionType; 13574 Type2 exceptionType;
12885 if (exceptionTypeName == null) { 13575 if (exceptionTypeName == null) {
12886 exceptionType = typeProvider.dynamicType; 13576 exceptionType = typeProvider.dynamicType;
12887 } else { 13577 } else {
12888 exceptionType = getType3(exceptionTypeName); 13578 exceptionType = getType3(exceptionTypeName);
12889 } 13579 }
12890 recordType(exception, exceptionType); 13580 recordType(exception, exceptionType);
12891 Element element = exception.staticElement; 13581 Element element = exception.staticElement;
12892 if (element is VariableElementImpl) { 13582 if (element is VariableElementImpl) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
12963 } else { 13653 } else {
12964 declaredType = getType3(typeName); 13654 declaredType = getType3(typeName);
12965 } 13655 }
12966 LocalVariableElementImpl element = node.element as LocalVariableElementImpl; 13656 LocalVariableElementImpl element = node.element as LocalVariableElementImpl;
12967 element.type = declaredType; 13657 element.type = declaredType;
12968 return null; 13658 return null;
12969 } 13659 }
12970 13660
12971 Object visitDefaultFormalParameter(DefaultFormalParameter node) { 13661 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
12972 super.visitDefaultFormalParameter(node); 13662 super.visitDefaultFormalParameter(node);
13663 // Expression defaultValue = node.getDefaultValue();
13664 // if (defaultValue != null) {
13665 // Type valueType = getType(defaultValue);
13666 // Type parameterType = getType(node.getParameter());
13667 // if (!valueType.isAssignableTo(parameterType)) {
13668 // TODO(brianwilkerson) Determine whether this is really an error. I can't f ind in the spec
13669 // anything that says it is, but a side comment from Gilad states that it sh ould be a static
13670 // warning.
13671 // resolver.reportError(ResolverErrorCode.?, defaultValue);
13672 // }
13673 // }
12973 return null; 13674 return null;
12974 } 13675 }
12975 13676
12976 Object visitFieldFormalParameter(FieldFormalParameter node) { 13677 Object visitFieldFormalParameter(FieldFormalParameter node) {
12977 super.visitFieldFormalParameter(node); 13678 super.visitFieldFormalParameter(node);
12978 Element element = node.identifier.staticElement; 13679 Element element = node.identifier.staticElement;
12979 if (element is ParameterElementImpl) { 13680 if (element is ParameterElementImpl) {
12980 ParameterElementImpl parameter = element; 13681 ParameterElementImpl parameter = element;
12981 FormalParameterList parameterList = node.parameters; 13682 FormalParameterList parameterList = node.parameters;
12982 if (parameterList == null) { 13683 if (parameterList == null) {
12983 Type2 type; 13684 Type2 type;
12984 TypeName typeName = node.type; 13685 TypeName typeName = node.type;
12985 if (typeName == null) { 13686 if (typeName == null) {
13687 // TODO(brianwilkerson) Find the field's declaration and use it's type .
12986 type = _dynamicType; 13688 type = _dynamicType;
12987 } else { 13689 } else {
12988 type = getType3(typeName); 13690 type = getType3(typeName);
12989 } 13691 }
12990 parameter.type = type; 13692 parameter.type = type;
12991 } else { 13693 } else {
12992 setFunctionTypedParameterType(parameter, node.type, node.parameters); 13694 setFunctionTypedParameterType(parameter, node.type, node.parameters);
12993 } 13695 }
12994 } else { 13696 } else {
12995 } 13697 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
13072 _hasReferenceToSuper = true; 13774 _hasReferenceToSuper = true;
13073 return super.visitSuperExpression(node); 13775 return super.visitSuperExpression(node);
13074 } 13776 }
13075 13777
13076 Object visitTypeName(TypeName node) { 13778 Object visitTypeName(TypeName node) {
13077 super.visitTypeName(node); 13779 super.visitTypeName(node);
13078 Identifier typeName = node.name; 13780 Identifier typeName = node.name;
13079 TypeArgumentList argumentList = node.typeArguments; 13781 TypeArgumentList argumentList = node.typeArguments;
13080 Element element = nameScope.lookup(typeName, definingLibrary); 13782 Element element = nameScope.lookup(typeName, definingLibrary);
13081 if (element == null) { 13783 if (element == null) {
13784 //
13785 // Check to see whether the type name is either 'dynamic' or 'void', neith er of which are in
13786 // the name scope and hence will not be found by normal means.
13787 //
13082 if (typeName.name == this._dynamicType.name) { 13788 if (typeName.name == this._dynamicType.name) {
13083 setElement(typeName, this._dynamicType.element); 13789 setElement(typeName, this._dynamicType.element);
13084 if (argumentList != null) { 13790 if (argumentList != null) {
13085 } 13791 }
13086 typeName.staticType = this._dynamicType; 13792 typeName.staticType = this._dynamicType;
13087 node.type = this._dynamicType; 13793 node.type = this._dynamicType;
13088 return null; 13794 return null;
13089 } 13795 }
13090 VoidTypeImpl voidType = VoidTypeImpl.instance; 13796 VoidTypeImpl voidType = VoidTypeImpl.instance;
13091 if (typeName.name == voidType.name) { 13797 if (typeName.name == voidType.name) {
13798 // There is no element for 'void'.
13092 if (argumentList != null) { 13799 if (argumentList != null) {
13093 } 13800 }
13094 typeName.staticType = voidType; 13801 typeName.staticType = voidType;
13095 node.type = voidType; 13802 node.type = voidType;
13096 return null; 13803 return null;
13097 } 13804 }
13805 //
13806 // If not, the look to see whether we might have created the wrong AST str ucture for a
13807 // constructor name. If so, fix the AST structure and then proceed.
13808 //
13098 ASTNode parent = node.parent; 13809 ASTNode parent = node.parent;
13099 if (typeName is PrefixedIdentifier && parent is ConstructorName && argumen tList == null) { 13810 if (typeName is PrefixedIdentifier && parent is ConstructorName && argumen tList == null) {
13100 ConstructorName name = parent; 13811 ConstructorName name = parent;
13101 if (name.name == null) { 13812 if (name.name == null) {
13102 PrefixedIdentifier prefixedIdentifier = typeName as PrefixedIdentifier ; 13813 PrefixedIdentifier prefixedIdentifier = typeName as PrefixedIdentifier ;
13103 SimpleIdentifier prefix = prefixedIdentifier.prefix; 13814 SimpleIdentifier prefix = prefixedIdentifier.prefix;
13104 element = nameScope.lookup(prefix, definingLibrary); 13815 element = nameScope.lookup(prefix, definingLibrary);
13105 if (element is PrefixElement) { 13816 if (element is PrefixElement) {
13106 if (parent.parent is InstanceCreationExpression && (parent.parent as InstanceCreationExpression).isConst) { 13817 if (parent.parent is InstanceCreationExpression && (parent.parent as InstanceCreationExpression).isConst) {
13818 // If, if this is a const expression, then generate a
13819 // CompileTimeErrorCode.CONST_WITH_NON_TYPE error.
13107 reportError7(CompileTimeErrorCode.CONST_WITH_NON_TYPE, prefixedIde ntifier.identifier, [prefixedIdentifier.identifier.name]); 13820 reportError7(CompileTimeErrorCode.CONST_WITH_NON_TYPE, prefixedIde ntifier.identifier, [prefixedIdentifier.identifier.name]);
13108 } else { 13821 } else {
13822 // Else, if this expression is a new expression, report a NEW_WITH _NON_TYPE warning.
13109 reportError7(StaticWarningCode.NEW_WITH_NON_TYPE, prefixedIdentifi er.identifier, [prefixedIdentifier.identifier.name]); 13823 reportError7(StaticWarningCode.NEW_WITH_NON_TYPE, prefixedIdentifi er.identifier, [prefixedIdentifier.identifier.name]);
13110 } 13824 }
13111 setElement(prefix, element); 13825 setElement(prefix, element);
13112 return null; 13826 return null;
13113 } else if (element != null) { 13827 } else if (element != null) {
13828 //
13829 // Rewrite the constructor name. The parser, when it sees a construc tor named "a.b",
13830 // cannot tell whether "a" is a prefix and "b" is a class name, or w hether "a" is a
13831 // class name and "b" is a constructor name. It arbitrarily chooses the former, but
13832 // in this case was wrong.
13833 //
13114 name.name = prefixedIdentifier.identifier; 13834 name.name = prefixedIdentifier.identifier;
13115 name.period = prefixedIdentifier.period; 13835 name.period = prefixedIdentifier.period;
13116 node.name = prefix; 13836 node.name = prefix;
13117 typeName = prefix; 13837 typeName = prefix;
13118 } 13838 }
13119 } 13839 }
13120 } 13840 }
13121 } 13841 }
13842 // check element
13122 bool elementValid = element is! MultiplyDefinedElement; 13843 bool elementValid = element is! MultiplyDefinedElement;
13123 if (elementValid && element is! ClassElement && isTypeNameInInstanceCreation Expression(node)) { 13844 if (elementValid && element is! ClassElement && isTypeNameInInstanceCreation Expression(node)) {
13124 SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName); 13845 SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName);
13125 InstanceCreationExpression creation = node.parent.parent as InstanceCreati onExpression; 13846 InstanceCreationExpression creation = node.parent.parent as InstanceCreati onExpression;
13126 if (creation.isConst) { 13847 if (creation.isConst) {
13127 if (element == null) { 13848 if (element == null) {
13128 reportError7(CompileTimeErrorCode.UNDEFINED_CLASS, typeNameSimple, [ty peName]); 13849 reportError7(CompileTimeErrorCode.UNDEFINED_CLASS, typeNameSimple, [ty peName]);
13129 } else { 13850 } else {
13130 reportError7(CompileTimeErrorCode.CONST_WITH_NON_TYPE, typeNameSimple, [typeName]); 13851 reportError7(CompileTimeErrorCode.CONST_WITH_NON_TYPE, typeNameSimple, [typeName]);
13131 } 13852 }
13132 elementValid = false; 13853 elementValid = false;
13133 } else { 13854 } else {
13134 if (element != null) { 13855 if (element != null) {
13135 reportError7(StaticWarningCode.NEW_WITH_NON_TYPE, typeNameSimple, [typ eName]); 13856 reportError7(StaticWarningCode.NEW_WITH_NON_TYPE, typeNameSimple, [typ eName]);
13136 elementValid = false; 13857 elementValid = false;
13137 } 13858 }
13138 } 13859 }
13139 } 13860 }
13140 if (elementValid && element == null) { 13861 if (elementValid && element == null) {
13862 // We couldn't resolve the type name.
13863 // TODO(jwren) Consider moving the check for CompileTimeErrorCode.BUILT_IN _IDENTIFIER_AS_TYPE
13864 // from the ErrorVerifier, so that we don't have two errors on a built in identifier being
13865 // used as a class name. See CompileTimeErrorCodeTest.test_builtInIdentifi erAsType().
13141 SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName); 13866 SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName);
13142 RedirectingConstructorKind redirectingConstructorKind; 13867 RedirectingConstructorKind redirectingConstructorKind;
13143 if (isBuiltInIdentifier(node) && isTypeAnnotation(node)) { 13868 if (isBuiltInIdentifier(node) && isTypeAnnotation(node)) {
13144 reportError7(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, typeName, [typeName.name]); 13869 reportError7(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, typeName, [typeName.name]);
13145 } else if (typeNameSimple.name == "boolean") { 13870 } else if (typeNameSimple.name == "boolean") {
13146 reportError7(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, typeNameSimple, []); 13871 reportError7(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, typeNameSimple, []);
13147 } else if (isTypeNameInCatchClause(node)) { 13872 } else if (isTypeNameInCatchClause(node)) {
13148 reportError7(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName, [type Name.name]); 13873 reportError7(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName, [type Name.name]);
13149 } else if (isTypeNameInAsExpression(node)) { 13874 } else if (isTypeNameInAsExpression(node)) {
13150 reportError7(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.nam e]); 13875 reportError7(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.nam e]);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
13182 type = (element as TypeParameterElement).type; 13907 type = (element as TypeParameterElement).type;
13183 if (argumentList != null) { 13908 if (argumentList != null) {
13184 } 13909 }
13185 } else if (element is MultiplyDefinedElement) { 13910 } else if (element is MultiplyDefinedElement) {
13186 List<Element> elements = (element as MultiplyDefinedElement).conflictingEl ements; 13911 List<Element> elements = (element as MultiplyDefinedElement).conflictingEl ements;
13187 type = getType(elements); 13912 type = getType(elements);
13188 if (type != null) { 13913 if (type != null) {
13189 node.type = type; 13914 node.type = type;
13190 } 13915 }
13191 } else { 13916 } else {
13917 // The name does not represent a type.
13192 RedirectingConstructorKind redirectingConstructorKind; 13918 RedirectingConstructorKind redirectingConstructorKind;
13193 if (isTypeNameInCatchClause(node)) { 13919 if (isTypeNameInCatchClause(node)) {
13194 reportError7(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName, [type Name.name]); 13920 reportError7(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName, [type Name.name]);
13195 } else if (isTypeNameInAsExpression(node)) { 13921 } else if (isTypeNameInAsExpression(node)) {
13196 reportError7(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.nam e]); 13922 reportError7(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.nam e]);
13197 } else if (isTypeNameInIsExpression(node)) { 13923 } else if (isTypeNameInIsExpression(node)) {
13198 reportError7(StaticWarningCode.TYPE_TEST_NON_TYPE, typeName, [typeName.n ame]); 13924 reportError7(StaticWarningCode.TYPE_TEST_NON_TYPE, typeName, [typeName.n ame]);
13199 } else if ((redirectingConstructorKind = getRedirectingConstructorKind(nod e)) != null) { 13925 } else if ((redirectingConstructorKind = getRedirectingConstructorKind(nod e)) != null) {
13200 ErrorCode errorCode = (identical(redirectingConstructorKind, Redirecting ConstructorKind.CONST) ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS : StaticWarn ingCode.REDIRECT_TO_NON_CLASS) as ErrorCode; 13926 ErrorCode errorCode = (identical(redirectingConstructorKind, Redirecting ConstructorKind.CONST) ? CompileTimeErrorCode.REDIRECT_TO_NON_CLASS : StaticWarn ingCode.REDIRECT_TO_NON_CLASS) as ErrorCode;
13201 reportError7(errorCode, typeName, [typeName.name]); 13927 reportError7(errorCode, typeName, [typeName.name]);
(...skipping 25 matching lines...) Expand all
13227 Type2 argumentType = getType3(arguments[i]); 13953 Type2 argumentType = getType3(arguments[i]);
13228 if (argumentType != null) { 13954 if (argumentType != null) {
13229 typeArguments.add(argumentType); 13955 typeArguments.add(argumentType);
13230 } 13956 }
13231 } 13957 }
13232 if (argumentCount != parameterCount) { 13958 if (argumentCount != parameterCount) {
13233 reportError7(getInvalidTypeParametersErrorCode(node), node, [typeName.na me, parameterCount, argumentCount]); 13959 reportError7(getInvalidTypeParametersErrorCode(node), node, [typeName.na me, parameterCount, argumentCount]);
13234 } 13960 }
13235 argumentCount = typeArguments.length; 13961 argumentCount = typeArguments.length;
13236 if (argumentCount < parameterCount) { 13962 if (argumentCount < parameterCount) {
13963 //
13964 // If there were too many arguments, we already handled it by not adding the values of the
13965 // extra arguments to the list. If there are too few, we handle it by ad ding 'dynamic'
13966 // enough times to make the count equal.
13967 //
13237 for (int i = argumentCount; i < parameterCount; i++) { 13968 for (int i = argumentCount; i < parameterCount; i++) {
13238 typeArguments.add(this._dynamicType); 13969 typeArguments.add(this._dynamicType);
13239 } 13970 }
13240 } 13971 }
13241 if (type is InterfaceTypeImpl) { 13972 if (type is InterfaceTypeImpl) {
13242 InterfaceTypeImpl interfaceType = type as InterfaceTypeImpl; 13973 InterfaceTypeImpl interfaceType = type as InterfaceTypeImpl;
13243 type = interfaceType.substitute4(new List.from(typeArguments)); 13974 type = interfaceType.substitute4(new List.from(typeArguments));
13244 } else if (type is FunctionTypeImpl) { 13975 } else if (type is FunctionTypeImpl) {
13245 FunctionTypeImpl functionType = type as FunctionTypeImpl; 13976 FunctionTypeImpl functionType = type as FunctionTypeImpl;
13246 type = functionType.substitute3(new List.from(typeArguments)); 13977 type = functionType.substitute3(new List.from(typeArguments));
13247 } else { 13978 } else {
13248 } 13979 }
13249 } else { 13980 } else {
13981 //
13982 // Check for the case where there are no type arguments given for a parame terized type.
13983 //
13250 List<Type2> parameters = getTypeArguments(type); 13984 List<Type2> parameters = getTypeArguments(type);
13251 int parameterCount = parameters.length; 13985 int parameterCount = parameters.length;
13252 if (parameterCount > 0) { 13986 if (parameterCount > 0) {
13253 DynamicTypeImpl dynamicType = DynamicTypeImpl.instance; 13987 DynamicTypeImpl dynamicType = DynamicTypeImpl.instance;
13254 List<Type2> arguments = new List<Type2>(parameterCount); 13988 List<Type2> arguments = new List<Type2>(parameterCount);
13255 for (int i = 0; i < parameterCount; i++) { 13989 for (int i = 0; i < parameterCount; i++) {
13256 arguments[i] = dynamicType; 13990 arguments[i] = dynamicType;
13257 } 13991 }
13258 type = type.substitute2(arguments, parameters); 13992 type = type.substitute2(arguments, parameters);
13259 } 13993 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
13319 } 14053 }
13320 } 14054 }
13321 14055
13322 /** 14056 /**
13323 * Return the class element that represents the class whose name was provided. 14057 * Return the class element that represents the class whose name was provided.
13324 * 14058 *
13325 * @param identifier the name from the declaration of a class 14059 * @param identifier the name from the declaration of a class
13326 * @return the class element that represents the class 14060 * @return the class element that represents the class
13327 */ 14061 */
13328 ClassElementImpl getClassElement(SimpleIdentifier identifier) { 14062 ClassElementImpl getClassElement(SimpleIdentifier identifier) {
14063 // TODO(brianwilkerson) Seems like we should be using ClassDeclaration.getEl ement().
13329 if (identifier == null) { 14064 if (identifier == null) {
14065 // TODO(brianwilkerson) Report this
14066 // Internal error: We should never build a class declaration without a nam e.
13330 return null; 14067 return null;
13331 } 14068 }
13332 Element element = identifier.staticElement; 14069 Element element = identifier.staticElement;
13333 if (element is! ClassElementImpl) { 14070 if (element is! ClassElementImpl) {
14071 // TODO(brianwilkerson) Report this
14072 // Internal error: Failed to create an element for a class declaration.
13334 return null; 14073 return null;
13335 } 14074 }
13336 return element as ClassElementImpl; 14075 return element as ClassElementImpl;
13337 } 14076 }
13338 14077
13339 /** 14078 /**
13340 * Return an array containing all of the elements associated with the paramete rs in the given 14079 * Return an array containing all of the elements associated with the paramete rs in the given
13341 * list. 14080 * list.
13342 * 14081 *
13343 * @param parameterList the list of parameters whose elements are to be return ed 14082 * @param parameterList the list of parameters whose elements are to be return ed
13344 * @return the elements associated with the parameters 14083 * @return the elements associated with the parameters
13345 */ 14084 */
13346 List<ParameterElement> getElements(FormalParameterList parameterList) { 14085 List<ParameterElement> getElements(FormalParameterList parameterList) {
13347 List<ParameterElement> elements = new List<ParameterElement>(); 14086 List<ParameterElement> elements = new List<ParameterElement>();
13348 for (FormalParameter parameter in parameterList.parameters) { 14087 for (FormalParameter parameter in parameterList.parameters) {
13349 ParameterElement element = parameter.identifier.staticElement as Parameter Element; 14088 ParameterElement element = parameter.identifier.staticElement as Parameter Element;
14089 // TODO(brianwilkerson) Understand why the element would be null.
13350 if (element != null) { 14090 if (element != null) {
13351 elements.add(element); 14091 elements.add(element);
13352 } 14092 }
13353 } 14093 }
13354 return new List.from(elements); 14094 return new List.from(elements);
13355 } 14095 }
13356 14096
13357 /** 14097 /**
13358 * The number of type arguments in the given type name does not match the numb er of parameters in 14098 * The number of type arguments in the given type name does not match the numb er of parameters in
13359 * the corresponding class element. Return the error code that should be used to report this 14099 * the corresponding class element. Return the error code that should be used to report this
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
13565 if (classElement != null) { 14305 if (classElement != null) {
13566 classElement.mixins = mixinTypes; 14306 classElement.mixins = mixinTypes;
13567 } 14307 }
13568 } 14308 }
13569 if (implementsClause != null) { 14309 if (implementsClause != null) {
13570 NodeList<TypeName> interfaces = implementsClause.interfaces; 14310 NodeList<TypeName> interfaces = implementsClause.interfaces;
13571 List<InterfaceType> interfaceTypes = resolveTypes(interfaces, CompileTimeE rrorCode.IMPLEMENTS_NON_CLASS, CompileTimeErrorCode.IMPLEMENTS_DYNAMIC); 14311 List<InterfaceType> interfaceTypes = resolveTypes(interfaces, CompileTimeE rrorCode.IMPLEMENTS_NON_CLASS, CompileTimeErrorCode.IMPLEMENTS_DYNAMIC);
13572 if (classElement != null) { 14312 if (classElement != null) {
13573 classElement.interfaces = interfaceTypes; 14313 classElement.interfaces = interfaceTypes;
13574 } 14314 }
14315 // TODO(brianwilkerson) Move the following checks to ErrorVerifier.
13575 List<TypeName> typeNames = new List.from(interfaces); 14316 List<TypeName> typeNames = new List.from(interfaces);
13576 List<bool> detectedRepeatOnIndex = new List<bool>.filled(typeNames.length, false); 14317 List<bool> detectedRepeatOnIndex = new List<bool>.filled(typeNames.length, false);
13577 for (int i = 0; i < detectedRepeatOnIndex.length; i++) { 14318 for (int i = 0; i < detectedRepeatOnIndex.length; i++) {
13578 detectedRepeatOnIndex[i] = false; 14319 detectedRepeatOnIndex[i] = false;
13579 } 14320 }
13580 for (int i = 0; i < typeNames.length; i++) { 14321 for (int i = 0; i < typeNames.length; i++) {
13581 TypeName typeName = typeNames[i]; 14322 TypeName typeName = typeNames[i];
13582 if (!detectedRepeatOnIndex[i]) { 14323 if (!detectedRepeatOnIndex[i]) {
13583 Element element = typeName.name.staticElement; 14324 Element element = typeName.name.staticElement;
13584 for (int j = i + 1; j < typeNames.length; j++) { 14325 for (int j = i + 1; j < typeNames.length; j++) {
(...skipping 18 matching lines...) Expand all
13603 * @param nonTypeError the error to produce if the type name is defined to be something other than 14344 * @param nonTypeError the error to produce if the type name is defined to be something other than
13604 * a type 14345 * a type
13605 * @param dynamicTypeError the error to produce if the type name is "dynamic" 14346 * @param dynamicTypeError the error to produce if the type name is "dynamic"
13606 * @return the type specified by the type name 14347 * @return the type specified by the type name
13607 */ 14348 */
13608 InterfaceType resolveType(TypeName typeName, ErrorCode nonTypeError, ErrorCode dynamicTypeError) { 14349 InterfaceType resolveType(TypeName typeName, ErrorCode nonTypeError, ErrorCode dynamicTypeError) {
13609 Type2 type = typeName.type; 14350 Type2 type = typeName.type;
13610 if (type is InterfaceType) { 14351 if (type is InterfaceType) {
13611 return type; 14352 return type;
13612 } 14353 }
14354 // If the type is not an InterfaceType, then visitTypeName() sets the type t o be a DynamicTypeImpl
13613 Identifier name = typeName.name; 14355 Identifier name = typeName.name;
13614 if (name.name == sc.Keyword.DYNAMIC.syntax) { 14356 if (name.name == sc.Keyword.DYNAMIC.syntax) {
13615 reportError7(dynamicTypeError, name, [name.name]); 14357 reportError7(dynamicTypeError, name, [name.name]);
13616 } else { 14358 } else {
13617 reportError7(nonTypeError, name, [name.name]); 14359 reportError7(nonTypeError, name, [name.name]);
13618 } 14360 }
13619 return null; 14361 return null;
13620 } 14362 }
13621 14363
13622 /** 14364 /**
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
13755 return super.visitFunctionExpression(node); 14497 return super.visitFunctionExpression(node);
13756 } finally { 14498 } finally {
13757 _enclosingFunction = outerFunction; 14499 _enclosingFunction = outerFunction;
13758 } 14500 }
13759 } else { 14501 } else {
13760 return super.visitFunctionExpression(node); 14502 return super.visitFunctionExpression(node);
13761 } 14503 }
13762 } 14504 }
13763 14505
13764 Object visitSimpleIdentifier(SimpleIdentifier node) { 14506 Object visitSimpleIdentifier(SimpleIdentifier node) {
14507 // Ignore if already resolved - declaration or type.
13765 if (node.staticElement != null) { 14508 if (node.staticElement != null) {
13766 return null; 14509 return null;
13767 } 14510 }
14511 // Ignore if qualified.
13768 ASTNode parent = node.parent; 14512 ASTNode parent = node.parent;
13769 if (parent is PrefixedIdentifier && identical(parent.identifier, node)) { 14513 if (parent is PrefixedIdentifier && identical(parent.identifier, node)) {
13770 return null; 14514 return null;
13771 } 14515 }
13772 if (parent is PropertyAccess && identical(parent.propertyName, node)) { 14516 if (parent is PropertyAccess && identical(parent.propertyName, node)) {
13773 return null; 14517 return null;
13774 } 14518 }
13775 if (parent is MethodInvocation && identical(parent.methodName, node)) { 14519 if (parent is MethodInvocation && identical(parent.methodName, node)) {
13776 return null; 14520 return null;
13777 } 14521 }
13778 if (parent is ConstructorName) { 14522 if (parent is ConstructorName) {
13779 return null; 14523 return null;
13780 } 14524 }
13781 if (parent is Label) { 14525 if (parent is Label) {
13782 return null; 14526 return null;
13783 } 14527 }
14528 // Prepare VariableElement.
13784 Element element = nameScope.lookup(node, definingLibrary); 14529 Element element = nameScope.lookup(node, definingLibrary);
13785 if (element is! VariableElement) { 14530 if (element is! VariableElement) {
13786 return null; 14531 return null;
13787 } 14532 }
14533 // Must be local or parameter.
13788 ElementKind kind = element.kind; 14534 ElementKind kind = element.kind;
13789 if (identical(kind, ElementKind.LOCAL_VARIABLE)) { 14535 if (identical(kind, ElementKind.LOCAL_VARIABLE)) {
13790 node.staticElement = element; 14536 node.staticElement = element;
13791 if (node.inSetterContext()) { 14537 if (node.inSetterContext()) {
13792 LocalVariableElementImpl variableImpl = element as LocalVariableElementI mpl; 14538 LocalVariableElementImpl variableImpl = element as LocalVariableElementI mpl;
13793 variableImpl.markPotentiallyMutatedInScope(); 14539 variableImpl.markPotentiallyMutatedInScope();
13794 if (element.enclosingElement != _enclosingFunction) { 14540 if (element.enclosingElement != _enclosingFunction) {
13795 variableImpl.markPotentiallyMutatedInClosure(); 14541 variableImpl.markPotentiallyMutatedInClosure();
13796 } 14542 }
13797 } 14543 }
13798 } else if (identical(kind, ElementKind.PARAMETER)) { 14544 } else if (identical(kind, ElementKind.PARAMETER)) {
13799 node.staticElement = element; 14545 node.staticElement = element;
13800 if (node.inSetterContext()) { 14546 if (node.inSetterContext()) {
13801 ParameterElementImpl parameterImpl = element as ParameterElementImpl; 14547 ParameterElementImpl parameterImpl = element as ParameterElementImpl;
13802 parameterImpl.markPotentiallyMutatedInScope(); 14548 parameterImpl.markPotentiallyMutatedInScope();
14549 // If we are in some closure, check if it is not the same as where varia ble is declared.
13803 if (_enclosingFunction != null && (element.enclosingElement != _enclosin gFunction)) { 14550 if (_enclosingFunction != null && (element.enclosingElement != _enclosin gFunction)) {
13804 parameterImpl.markPotentiallyMutatedInClosure(); 14551 parameterImpl.markPotentiallyMutatedInClosure();
13805 } 14552 }
13806 } 14553 }
13807 } 14554 }
13808 return null; 14555 return null;
13809 } 14556 }
13810 } 14557 }
13811 14558
13812 /** 14559 /**
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
13912 _hasHiddenName = true; 14659 _hasHiddenName = true;
13913 } 14660 }
13914 } 14661 }
13915 } 14662 }
13916 14663
13917 Element lookup3(Identifier identifier, String name, LibraryElement referencing Library) { 14664 Element lookup3(Identifier identifier, String name, LibraryElement referencing Library) {
13918 Element element = localLookup(name, referencingLibrary); 14665 Element element = localLookup(name, referencingLibrary);
13919 if (element != null) { 14666 if (element != null) {
13920 return element; 14667 return element;
13921 } 14668 }
14669 // May be there is a hidden Element.
13922 if (_hasHiddenName) { 14670 if (_hasHiddenName) {
13923 Element hiddenElement = _hiddenElements[name]; 14671 Element hiddenElement = _hiddenElements[name];
13924 if (hiddenElement != null) { 14672 if (hiddenElement != null) {
13925 errorListener.onError(new AnalysisError.con2(getSource(identifier), iden tifier.offset, identifier.length, CompileTimeErrorCode.REFERENCED_BEFORE_DECLARA TION, [])); 14673 errorListener.onError(new AnalysisError.con2(getSource(identifier), iden tifier.offset, identifier.length, CompileTimeErrorCode.REFERENCED_BEFORE_DECLARA TION, []));
13926 return hiddenElement; 14674 return hiddenElement;
13927 } 14675 }
13928 } 14676 }
14677 // Check enclosing scope.
13929 return enclosingScope.lookup3(identifier, name, referencingLibrary); 14678 return enclosingScope.lookup3(identifier, name, referencingLibrary);
13930 } 14679 }
13931 } 14680 }
13932 14681
13933 /** 14682 /**
13934 * Instances of the class `FunctionScope` implement the scope defined by a funct ion. 14683 * Instances of the class `FunctionScope` implement the scope defined by a funct ion.
13935 * 14684 *
13936 * @coverage dart.engine.resolver 14685 * @coverage dart.engine.resolver
13937 */ 14686 */
13938 class FunctionScope extends EnclosedScope { 14687 class FunctionScope extends EnclosedScope {
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
14163 } 14912 }
14164 } 14913 }
14165 if (foundElement is MultiplyDefinedElementImpl) { 14914 if (foundElement is MultiplyDefinedElementImpl) {
14166 foundElement = removeSdkElements(identifier, name, foundElement as Multipl yDefinedElementImpl); 14915 foundElement = removeSdkElements(identifier, name, foundElement as Multipl yDefinedElementImpl);
14167 } 14916 }
14168 if (foundElement is MultiplyDefinedElementImpl) { 14917 if (foundElement is MultiplyDefinedElementImpl) {
14169 String foundEltName = foundElement.displayName; 14918 String foundEltName = foundElement.displayName;
14170 List<Element> conflictingMembers = (foundElement as MultiplyDefinedElement Impl).conflictingElements; 14919 List<Element> conflictingMembers = (foundElement as MultiplyDefinedElement Impl).conflictingElements;
14171 String libName1 = getLibraryName(conflictingMembers[0], ""); 14920 String libName1 = getLibraryName(conflictingMembers[0], "");
14172 String libName2 = getLibraryName(conflictingMembers[1], ""); 14921 String libName2 = getLibraryName(conflictingMembers[1], "");
14922 // TODO (jwren) Change the error message to include a list of all library names instead of
14923 // just the first two
14173 errorListener.onError(new AnalysisError.con2(getSource(identifier), identi fier.offset, identifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltNam e, libName1, libName2])); 14924 errorListener.onError(new AnalysisError.con2(getSource(identifier), identi fier.offset, identifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltNam e, libName1, libName2]));
14174 return foundElement; 14925 return foundElement;
14175 } 14926 }
14176 if (foundElement != null) { 14927 if (foundElement != null) {
14177 defineWithoutChecking2(name, foundElement); 14928 defineWithoutChecking2(name, foundElement);
14178 } 14929 }
14179 return foundElement; 14930 return foundElement;
14180 } 14931 }
14181 14932
14182 /** 14933 /**
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
14235 } else { 14986 } else {
14236 conflictingMembers[to++] = member; 14987 conflictingMembers[to++] = member;
14237 } 14988 }
14238 } 14989 }
14239 if (sdkElement != null && to > 0) { 14990 if (sdkElement != null && to > 0) {
14240 String sdkLibName = getLibraryName(sdkElement, ""); 14991 String sdkLibName = getLibraryName(sdkElement, "");
14241 String otherLibName = getLibraryName(conflictingMembers[0], ""); 14992 String otherLibName = getLibraryName(conflictingMembers[0], "");
14242 errorListener.onError(new AnalysisError.con2(getSource(identifier), identi fier.offset, identifier.length, StaticWarningCode.CONFLICTING_DART_IMPORT, [name , sdkLibName, otherLibName])); 14993 errorListener.onError(new AnalysisError.con2(getSource(identifier), identi fier.offset, identifier.length, StaticWarningCode.CONFLICTING_DART_IMPORT, [name , sdkLibName, otherLibName]));
14243 } 14994 }
14244 if (to == length) { 14995 if (to == length) {
14996 // None of the members were removed
14245 return foundElement; 14997 return foundElement;
14246 } else if (to == 1) { 14998 } else if (to == 1) {
14999 // All but one member was removed
14247 return conflictingMembers[0]; 15000 return conflictingMembers[0];
14248 } else if (to == 0) { 15001 } else if (to == 0) {
15002 // All members were removed
14249 AnalysisEngine.instance.logger.logInformation("Multiply defined SDK elemen t: ${foundElement}"); 15003 AnalysisEngine.instance.logger.logInformation("Multiply defined SDK elemen t: ${foundElement}");
14250 return foundElement; 15004 return foundElement;
14251 } 15005 }
14252 List<Element> remaining = new List<Element>(to); 15006 List<Element> remaining = new List<Element>(to);
14253 JavaSystem.arraycopy(conflictingMembers, 0, remaining, 0, to); 15007 JavaSystem.arraycopy(conflictingMembers, 0, remaining, 0, to);
14254 return new MultiplyDefinedElementImpl(_definingLibrary.context, remaining); 15008 return new MultiplyDefinedElementImpl(_definingLibrary.context, remaining);
14255 } 15009 }
14256 } 15010 }
14257 15011
14258 /** 15012 /**
14259 * Instances of the class `LibraryScope` implement a scope containing all of the names defined 15013 * Instances of the class `LibraryScope` implement a scope containing all of the names defined
14260 * in a given library. 15014 * in a given library.
14261 * 15015 *
14262 * @coverage dart.engine.resolver 15016 * @coverage dart.engine.resolver
14263 */ 15017 */
14264 class LibraryScope extends EnclosedScope { 15018 class LibraryScope extends EnclosedScope {
14265 /** 15019 /**
14266 * Initialize a newly created scope representing the names defined in the give n library. 15020 * Initialize a newly created scope representing the names defined in the give n library.
14267 * 15021 *
14268 * @param definingLibrary the element representing the library represented by this scope 15022 * @param definingLibrary the element representing the library represented by this scope
14269 * @param errorListener the listener that is to be informed when an error is e ncountered 15023 * @param errorListener the listener that is to be informed when an error is e ncountered
14270 */ 15024 */
14271 LibraryScope(LibraryElement definingLibrary, AnalysisErrorListener errorListen er) : super(new LibraryImportScope(definingLibrary, errorListener)) { 15025 LibraryScope(LibraryElement definingLibrary, AnalysisErrorListener errorListen er) : super(new LibraryImportScope(definingLibrary, errorListener)) {
14272 defineTopLevelNames(definingLibrary); 15026 defineTopLevelNames(definingLibrary);
14273 } 15027 }
14274 15028
14275 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) { 15029 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
14276 if (existing is PrefixElement) { 15030 if (existing is PrefixElement) {
15031 // TODO(scheglov) consider providing actual 'nameOffset' from the syntheti c accessor
14277 int offset = duplicate.nameOffset; 15032 int offset = duplicate.nameOffset;
14278 if (duplicate is PropertyAccessorElement) { 15033 if (duplicate is PropertyAccessorElement) {
14279 PropertyAccessorElement accessor = duplicate; 15034 PropertyAccessorElement accessor = duplicate;
14280 if (accessor.isSynthetic) { 15035 if (accessor.isSynthetic) {
14281 offset = accessor.variable.nameOffset; 15036 offset = accessor.variable.nameOffset;
14282 } 15037 }
14283 } 15038 }
14284 return new AnalysisError.con2(duplicate.source, offset, duplicate.displayN ame.length, CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, [existin g.displayName]); 15039 return new AnalysisError.con2(duplicate.source, offset, duplicate.displayN ame.length, CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, [existin g.displayName]);
14285 } 15040 }
14286 return super.getErrorForDuplicate(existing, duplicate); 15041 return super.getErrorForDuplicate(existing, duplicate);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
14379 class NamespaceBuilder { 15134 class NamespaceBuilder {
14380 /** 15135 /**
14381 * Create a namespace representing the export namespace of the given [ExportEl ement]. 15136 * Create a namespace representing the export namespace of the given [ExportEl ement].
14382 * 15137 *
14383 * @param element the export element whose export namespace is to be created 15138 * @param element the export element whose export namespace is to be created
14384 * @return the export namespace that was created 15139 * @return the export namespace that was created
14385 */ 15140 */
14386 Namespace createExportNamespace(ExportElement element) { 15141 Namespace createExportNamespace(ExportElement element) {
14387 LibraryElement exportedLibrary = element.exportedLibrary; 15142 LibraryElement exportedLibrary = element.exportedLibrary;
14388 if (exportedLibrary == null) { 15143 if (exportedLibrary == null) {
15144 //
15145 // The exported library will be null if the URI does not reference a valid library.
15146 //
14389 return Namespace.EMPTY; 15147 return Namespace.EMPTY;
14390 } 15148 }
14391 Map<String, Element> definedNames = createExportMapping(exportedLibrary, new Set<LibraryElement>()); 15149 Map<String, Element> definedNames = createExportMapping(exportedLibrary, new Set<LibraryElement>());
14392 definedNames = apply(definedNames, element.combinators); 15150 definedNames = apply(definedNames, element.combinators);
14393 return new Namespace(definedNames); 15151 return new Namespace(definedNames);
14394 } 15152 }
14395 15153
14396 /** 15154 /**
14397 * Create a namespace representing the export namespace of the given library. 15155 * Create a namespace representing the export namespace of the given library.
14398 * 15156 *
14399 * @param library the library whose export namespace is to be created 15157 * @param library the library whose export namespace is to be created
14400 * @return the export namespace that was created 15158 * @return the export namespace that was created
14401 */ 15159 */
14402 Namespace createExportNamespace2(LibraryElement library) => new Namespace(crea teExportMapping(library, new Set<LibraryElement>())); 15160 Namespace createExportNamespace2(LibraryElement library) => new Namespace(crea teExportMapping(library, new Set<LibraryElement>()));
14403 15161
14404 /** 15162 /**
14405 * Create a namespace representing the import namespace of the given library. 15163 * Create a namespace representing the import namespace of the given library.
14406 * 15164 *
14407 * @param library the library whose import namespace is to be created 15165 * @param library the library whose import namespace is to be created
14408 * @return the import namespace that was created 15166 * @return the import namespace that was created
14409 */ 15167 */
14410 Namespace createImportNamespace(ImportElement element) { 15168 Namespace createImportNamespace(ImportElement element) {
14411 LibraryElement importedLibrary = element.importedLibrary; 15169 LibraryElement importedLibrary = element.importedLibrary;
14412 if (importedLibrary == null) { 15170 if (importedLibrary == null) {
15171 //
15172 // The imported library will be null if the URI does not reference a valid library.
15173 //
14413 return Namespace.EMPTY; 15174 return Namespace.EMPTY;
14414 } 15175 }
14415 Map<String, Element> definedNames = createExportMapping(importedLibrary, new Set<LibraryElement>()); 15176 Map<String, Element> definedNames = createExportMapping(importedLibrary, new Set<LibraryElement>());
14416 definedNames = apply(definedNames, element.combinators); 15177 definedNames = apply(definedNames, element.combinators);
14417 definedNames = apply2(definedNames, element.prefix); 15178 definedNames = apply2(definedNames, element.prefix);
14418 return new Namespace(definedNames); 15179 return new Namespace(definedNames);
14419 } 15180 }
14420 15181
14421 /** 15182 /**
14422 * Create a namespace representing the public namespace of the given library. 15183 * Create a namespace representing the public namespace of the given library.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
14499 * @param definedNames the mapping table to which the namespace operations are to be applied 15260 * @param definedNames the mapping table to which the namespace operations are to be applied
14500 * @param combinators the combinators to be applied 15261 * @param combinators the combinators to be applied
14501 */ 15262 */
14502 Map<String, Element> apply(Map<String, Element> definedNames, List<NamespaceCo mbinator> combinators) { 15263 Map<String, Element> apply(Map<String, Element> definedNames, List<NamespaceCo mbinator> combinators) {
14503 for (NamespaceCombinator combinator in combinators) { 15264 for (NamespaceCombinator combinator in combinators) {
14504 if (combinator is HideElementCombinator) { 15265 if (combinator is HideElementCombinator) {
14505 hide(definedNames, combinator.hiddenNames); 15266 hide(definedNames, combinator.hiddenNames);
14506 } else if (combinator is ShowElementCombinator) { 15267 } else if (combinator is ShowElementCombinator) {
14507 definedNames = show(definedNames, combinator.shownNames); 15268 definedNames = show(definedNames, combinator.shownNames);
14508 } else { 15269 } else {
15270 // Internal error.
14509 AnalysisEngine.instance.logger.logError("Unknown type of combinator: ${c ombinator.runtimeType.toString()}"); 15271 AnalysisEngine.instance.logger.logError("Unknown type of combinator: ${c ombinator.runtimeType.toString()}");
14510 } 15272 }
14511 } 15273 }
14512 return definedNames; 15274 return definedNames;
14513 } 15275 }
14514 15276
14515 /** 15277 /**
14516 * Apply the given prefix to all of the names in the table of defined names. 15278 * Apply the given prefix to all of the names in the table of defined names.
14517 * 15279 *
14518 * @param definedNames the names that were defined before this operation 15280 * @param definedNames the names that were defined before this operation
(...skipping 21 matching lines...) Expand all
14540 * be added by another library 15302 * be added by another library
14541 * @return the mapping table that was created 15303 * @return the mapping table that was created
14542 */ 15304 */
14543 Map<String, Element> createExportMapping(LibraryElement library, Set<LibraryEl ement> visitedElements) { 15305 Map<String, Element> createExportMapping(LibraryElement library, Set<LibraryEl ement> visitedElements) {
14544 visitedElements.add(library); 15306 visitedElements.add(library);
14545 try { 15307 try {
14546 Map<String, Element> definedNames = new Map<String, Element>(); 15308 Map<String, Element> definedNames = new Map<String, Element>();
14547 for (ExportElement element in library.exports) { 15309 for (ExportElement element in library.exports) {
14548 LibraryElement exportedLibrary = element.exportedLibrary; 15310 LibraryElement exportedLibrary = element.exportedLibrary;
14549 if (exportedLibrary != null && !visitedElements.contains(exportedLibrary )) { 15311 if (exportedLibrary != null && !visitedElements.contains(exportedLibrary )) {
15312 //
15313 // The exported library will be null if the URI does not reference a v alid library.
15314 //
14550 Map<String, Element> exportedNames = createExportMapping(exportedLibra ry, visitedElements); 15315 Map<String, Element> exportedNames = createExportMapping(exportedLibra ry, visitedElements);
14551 exportedNames = apply(exportedNames, element.combinators); 15316 exportedNames = apply(exportedNames, element.combinators);
14552 addAll(definedNames, exportedNames); 15317 addAll(definedNames, exportedNames);
14553 } 15318 }
14554 } 15319 }
14555 addAll2(definedNames, (library.context as InternalAnalysisContext).getPubl icNamespace(library)); 15320 addAll2(definedNames, (library.context as InternalAnalysisContext).getPubl icNamespace(library));
14556 return definedNames; 15321 return definedNames;
14557 } finally { 15322 } finally {
14558 visitedElements.remove(library); 15323 visitedElements.remove(library);
14559 } 15324 }
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
14700 15465
14701 /** 15466 /**
14702 * Return the error code to be used when reporting that a name being defined l ocally conflicts 15467 * Return the error code to be used when reporting that a name being defined l ocally conflicts
14703 * with another element of the same name in the local scope. 15468 * with another element of the same name in the local scope.
14704 * 15469 *
14705 * @param existing the first element to be declared with the conflicting name 15470 * @param existing the first element to be declared with the conflicting name
14706 * @param duplicate another element declared with the conflicting name 15471 * @param duplicate another element declared with the conflicting name
14707 * @return the error code used to report duplicate names within a scope 15472 * @return the error code used to report duplicate names within a scope
14708 */ 15473 */
14709 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) { 15474 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
15475 // TODO(brianwilkerson) Customize the error message based on the types of el ements that share
15476 // the same name.
15477 // TODO(jwren) There are 4 error codes for duplicate, but only 1 is being ge nerated.
14710 Source source = duplicate.source; 15478 Source source = duplicate.source;
14711 return new AnalysisError.con2(source, duplicate.nameOffset, duplicate.displa yName.length, CompileTimeErrorCode.DUPLICATE_DEFINITION, [existing.displayName]) ; 15479 return new AnalysisError.con2(source, duplicate.nameOffset, duplicate.displa yName.length, CompileTimeErrorCode.DUPLICATE_DEFINITION, [existing.displayName]) ;
14712 } 15480 }
14713 15481
14714 /** 15482 /**
14715 * Return the listener that is to be informed when an error is encountered. 15483 * Return the listener that is to be informed when an error is encountered.
14716 * 15484 *
14717 * @return the listener that is to be informed when an error is encountered 15485 * @return the listener that is to be informed when an error is encountered
14718 */ 15486 */
14719 AnalysisErrorListener get errorListener; 15487 AnalysisErrorListener get errorListener;
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after
14929 this._errorReporter = errorReporter; 15697 this._errorReporter = errorReporter;
14930 this._typeProvider = typeProvider; 15698 this._typeProvider = typeProvider;
14931 this._boolType = typeProvider.boolType; 15699 this._boolType = typeProvider.boolType;
14932 this._intType = typeProvider.intType; 15700 this._intType = typeProvider.intType;
14933 this._numType = typeProvider.numType; 15701 this._numType = typeProvider.numType;
14934 this._stringType = typeProvider.stringType; 15702 this._stringType = typeProvider.stringType;
14935 } 15703 }
14936 15704
14937 Object visitAnnotation(Annotation node) { 15705 Object visitAnnotation(Annotation node) {
14938 super.visitAnnotation(node); 15706 super.visitAnnotation(node);
15707 // check annotation creation
14939 Element element = node.element; 15708 Element element = node.element;
14940 if (element is ConstructorElement) { 15709 if (element is ConstructorElement) {
14941 ConstructorElement constructorElement = element; 15710 ConstructorElement constructorElement = element;
15711 // should 'const' constructor
14942 if (!constructorElement.isConst) { 15712 if (!constructorElement.isConst) {
14943 _errorReporter.reportError3(CompileTimeErrorCode.NON_CONSTANT_ANNOTATION _CONSTRUCTOR, node, []); 15713 _errorReporter.reportError3(CompileTimeErrorCode.NON_CONSTANT_ANNOTATION _CONSTRUCTOR, node, []);
14944 return null; 15714 return null;
14945 } 15715 }
15716 // should have arguments
14946 ArgumentList argumentList = node.arguments; 15717 ArgumentList argumentList = node.arguments;
14947 if (argumentList == null) { 15718 if (argumentList == null) {
14948 _errorReporter.reportError3(CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCT OR_ARGUMENTS, node, []); 15719 _errorReporter.reportError3(CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCT OR_ARGUMENTS, node, []);
14949 return null; 15720 return null;
14950 } 15721 }
15722 // arguments should be constants
14951 validateConstantArguments(argumentList); 15723 validateConstantArguments(argumentList);
14952 } 15724 }
14953 return null; 15725 return null;
14954 } 15726 }
14955 15727
14956 Object visitConstructorDeclaration(ConstructorDeclaration node) { 15728 Object visitConstructorDeclaration(ConstructorDeclaration node) {
14957 if (node.constKeyword != null) { 15729 if (node.constKeyword != null) {
14958 validateInitializers(node); 15730 validateInitializers(node);
14959 } 15731 }
14960 validateDefaultValues(node.parameters); 15732 validateDefaultValues(node.parameters);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
15035 return null; 15807 return null;
15036 } 15808 }
15037 15809
15038 Object visitVariableDeclaration(VariableDeclaration node) { 15810 Object visitVariableDeclaration(VariableDeclaration node) {
15039 super.visitVariableDeclaration(node); 15811 super.visitVariableDeclaration(node);
15040 Expression initializer = node.initializer; 15812 Expression initializer = node.initializer;
15041 if (initializer != null && node.isConst) { 15813 if (initializer != null && node.isConst) {
15042 VariableElementImpl element = node.element as VariableElementImpl; 15814 VariableElementImpl element = node.element as VariableElementImpl;
15043 EvaluationResultImpl result = element.evaluationResult; 15815 EvaluationResultImpl result = element.evaluationResult;
15044 if (result == null) { 15816 if (result == null) {
15817 //
15818 // Normally we don't need to visit const variable declarations because w e have already
15819 // computed their values. But if we missed it for some reason, this give s us a second
15820 // chance.
15821 //
15045 result = validate(initializer, CompileTimeErrorCode.CONST_INITIALIZED_WI TH_NON_CONSTANT_VALUE); 15822 result = validate(initializer, CompileTimeErrorCode.CONST_INITIALIZED_WI TH_NON_CONSTANT_VALUE);
15046 element.evaluationResult = result; 15823 element.evaluationResult = result;
15047 } else if (result is ErrorResult) { 15824 } else if (result is ErrorResult) {
15048 reportErrors(result, CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CON STANT_VALUE); 15825 reportErrors(result, CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CON STANT_VALUE);
15049 } 15826 }
15050 } 15827 }
15051 return null; 15828 return null;
15052 } 15829 }
15053 15830
15054 /** 15831 /**
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
15503 checkForNoDefaultSuperConstructorImplicit(node); 16280 checkForNoDefaultSuperConstructorImplicit(node);
15504 checkForAllMixinErrorCodes(withClause); 16281 checkForAllMixinErrorCodes(withClause);
15505 checkForConflictingTypeVariableErrorCodes(node); 16282 checkForConflictingTypeVariableErrorCodes(node);
15506 if (implementsClause != null || extendsClause != null) { 16283 if (implementsClause != null || extendsClause != null) {
15507 if (!checkForImplementsDisallowedClass(implementsClause) && !checkForExt endsDisallowedClass(extendsClause)) { 16284 if (!checkForImplementsDisallowedClass(implementsClause) && !checkForExt endsDisallowedClass(extendsClause)) {
15508 checkForNonAbstractClassInheritsAbstractMember(node); 16285 checkForNonAbstractClassInheritsAbstractMember(node);
15509 checkForInconsistentMethodInheritance(); 16286 checkForInconsistentMethodInheritance();
15510 checkForRecursiveInterfaceInheritance(_enclosingClass); 16287 checkForRecursiveInterfaceInheritance(_enclosingClass);
15511 } 16288 }
15512 } 16289 }
16290 // initialize initialFieldElementsMap
15513 ClassElement classElement = node.element; 16291 ClassElement classElement = node.element;
15514 if (classElement != null) { 16292 if (classElement != null) {
15515 List<FieldElement> fieldElements = classElement.fields; 16293 List<FieldElement> fieldElements = classElement.fields;
15516 _initialFieldElementsMap = new Map<FieldElement, INIT_STATE>(); 16294 _initialFieldElementsMap = new Map<FieldElement, INIT_STATE>();
15517 for (FieldElement fieldElement in fieldElements) { 16295 for (FieldElement fieldElement in fieldElements) {
15518 if (!fieldElement.isSynthetic) { 16296 if (!fieldElement.isSynthetic) {
15519 _initialFieldElementsMap[fieldElement] = fieldElement.initializer == null ? INIT_STATE.NOT_INIT : INIT_STATE.INIT_IN_DECLARATION; 16297 _initialFieldElementsMap[fieldElement] = fieldElement.initializer == null ? INIT_STATE.NOT_INIT : INIT_STATE.INIT_IN_DECLARATION;
15520 } 16298 }
15521 } 16299 }
15522 } 16300 }
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
15667 checkForNonVoidReturnTypeForSetter(returnType); 16445 checkForNonVoidReturnTypeForSetter(returnType);
15668 } 16446 }
15669 } 16447 }
15670 return super.visitFunctionDeclaration(node); 16448 return super.visitFunctionDeclaration(node);
15671 } finally { 16449 } finally {
15672 _enclosingFunction = outerFunction; 16450 _enclosingFunction = outerFunction;
15673 } 16451 }
15674 } 16452 }
15675 16453
15676 Object visitFunctionExpression(FunctionExpression node) { 16454 Object visitFunctionExpression(FunctionExpression node) {
16455 // If this function expression is wrapped in a function declaration, don't c hange the
16456 // enclosingFunction field.
15677 if (node.parent is! FunctionDeclaration) { 16457 if (node.parent is! FunctionDeclaration) {
15678 ExecutableElement outerFunction = _enclosingFunction; 16458 ExecutableElement outerFunction = _enclosingFunction;
15679 try { 16459 try {
15680 _enclosingFunction = node.element; 16460 _enclosingFunction = node.element;
15681 return super.visitFunctionExpression(node); 16461 return super.visitFunctionExpression(node);
15682 } finally { 16462 } finally {
15683 _enclosingFunction = outerFunction; 16463 _enclosingFunction = outerFunction;
15684 } 16464 }
15685 } else { 16465 } else {
15686 return super.visitFunctionExpression(node); 16466 return super.visitFunctionExpression(node);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
15826 ClassElement typeReference = ElementResolver.getTypeReference(target); 16606 ClassElement typeReference = ElementResolver.getTypeReference(target);
15827 checkForStaticAccessToInstanceMember(typeReference, methodName); 16607 checkForStaticAccessToInstanceMember(typeReference, methodName);
15828 checkForInstanceAccessToStaticMember(typeReference, methodName); 16608 checkForInstanceAccessToStaticMember(typeReference, methodName);
15829 } else { 16609 } else {
15830 checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); 16610 checkForUnqualifiedReferenceToNonLocalStaticMember(methodName);
15831 } 16611 }
15832 return super.visitMethodInvocation(node); 16612 return super.visitMethodInvocation(node);
15833 } 16613 }
15834 16614
15835 Object visitNativeClause(NativeClause node) { 16615 Object visitNativeClause(NativeClause node) {
16616 // TODO(brianwilkerson) Figure out the right rule for when 'native' is allow ed.
15836 if (!_isInSystemLibrary) { 16617 if (!_isInSystemLibrary) {
15837 _errorReporter.reportError3(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node, []); 16618 _errorReporter.reportError3(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node, []);
15838 } 16619 }
15839 return super.visitNativeClause(node); 16620 return super.visitNativeClause(node);
15840 } 16621 }
15841 16622
15842 Object visitNativeFunctionBody(NativeFunctionBody node) { 16623 Object visitNativeFunctionBody(NativeFunctionBody node) {
15843 checkForNativeFunctionBodyInNonSDKCode(node); 16624 checkForNativeFunctionBodyInNonSDKCode(node);
15844 return super.visitNativeFunctionBody(node); 16625 return super.visitNativeFunctionBody(node);
15845 } 16626 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
15957 16738
15958 Object visitTypeParameter(TypeParameter node) { 16739 Object visitTypeParameter(TypeParameter node) {
15959 checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDE NTIFIER_AS_TYPE_PARAMETER_NAME); 16740 checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDE NTIFIER_AS_TYPE_PARAMETER_NAME);
15960 checkForTypeParameterSupertypeOfItsBound(node); 16741 checkForTypeParameterSupertypeOfItsBound(node);
15961 return super.visitTypeParameter(node); 16742 return super.visitTypeParameter(node);
15962 } 16743 }
15963 16744
15964 Object visitVariableDeclaration(VariableDeclaration node) { 16745 Object visitVariableDeclaration(VariableDeclaration node) {
15965 SimpleIdentifier nameNode = node.name; 16746 SimpleIdentifier nameNode = node.name;
15966 Expression initializerNode = node.initializer; 16747 Expression initializerNode = node.initializer;
16748 // do checks
15967 checkForInvalidAssignment2(nameNode, initializerNode); 16749 checkForInvalidAssignment2(nameNode, initializerNode);
16750 // visit name
15968 nameNode.accept(this); 16751 nameNode.accept(this);
16752 // visit initializer
15969 String name = nameNode.name; 16753 String name = nameNode.name;
15970 _namesForReferenceToDeclaredVariableInInitializer.add(name); 16754 _namesForReferenceToDeclaredVariableInInitializer.add(name);
15971 _isInInstanceVariableInitializer = _isInInstanceVariableDeclaration; 16755 _isInInstanceVariableInitializer = _isInInstanceVariableDeclaration;
15972 try { 16756 try {
15973 if (initializerNode != null) { 16757 if (initializerNode != null) {
15974 initializerNode.accept(this); 16758 initializerNode.accept(this);
15975 } 16759 }
15976 } finally { 16760 } finally {
15977 _isInInstanceVariableInitializer = false; 16761 _isInInstanceVariableInitializer = false;
15978 _namesForReferenceToDeclaredVariableInInitializer.remove(name); 16762 _namesForReferenceToDeclaredVariableInInitializer.remove(name);
15979 } 16763 }
16764 // done
15980 return null; 16765 return null;
15981 } 16766 }
15982 16767
15983 Object visitVariableDeclarationList(VariableDeclarationList node) => super.vis itVariableDeclarationList(node); 16768 Object visitVariableDeclarationList(VariableDeclarationList node) => super.vis itVariableDeclarationList(node);
15984 16769
15985 Object visitVariableDeclarationStatement(VariableDeclarationStatement node) { 16770 Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
15986 checkForFinalNotInitialized2(node.variables); 16771 checkForFinalNotInitialized2(node.variables);
15987 return super.visitVariableDeclarationStatement(node); 16772 return super.visitVariableDeclarationStatement(node);
15988 } 16773 }
15989 16774
15990 Object visitWhileStatement(WhileStatement node) { 16775 Object visitWhileStatement(WhileStatement node) {
15991 checkForNonBoolCondition(node.condition); 16776 checkForNonBoolCondition(node.condition);
15992 return super.visitWhileStatement(node); 16777 return super.visitWhileStatement(node);
15993 } 16778 }
15994 16779
15995 /** 16780 /**
15996 * This verifies if the passed map literal has type arguments then there is ex actly two. 16781 * This verifies if the passed map literal has type arguments then there is ex actly two.
15997 * 16782 *
15998 * @param node the map literal to evaluate 16783 * @param node the map literal to evaluate
15999 * @return `true` if and only if an error code is generated on the passed node 16784 * @return `true` if and only if an error code is generated on the passed node
16000 * @see StaticTypeWarningCode#EXPECTED_TWO_MAP_TYPE_ARGUMENTS 16785 * @see StaticTypeWarningCode#EXPECTED_TWO_MAP_TYPE_ARGUMENTS
16001 */ 16786 */
16002 bool checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) { 16787 bool checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) {
16788 // has type arguments
16003 if (typeArguments == null) { 16789 if (typeArguments == null) {
16004 return false; 16790 return false;
16005 } 16791 }
16792 // check number of type arguments
16006 int num = typeArguments.arguments.length; 16793 int num = typeArguments.arguments.length;
16007 if (num == 2) { 16794 if (num == 2) {
16008 return false; 16795 return false;
16009 } 16796 }
16797 // report problem
16010 _errorReporter.reportError3(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGU MENTS, typeArguments, [num]); 16798 _errorReporter.reportError3(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGU MENTS, typeArguments, [num]);
16011 return true; 16799 return true;
16012 } 16800 }
16013 16801
16014 /** 16802 /**
16015 * This verifies that the passed constructor declaration does not violate any of the error codes 16803 * This verifies that the passed constructor declaration does not violate any of the error codes
16016 * relating to the initialization of fields in the enclosing class. 16804 * relating to the initialization of fields in the enclosing class.
16017 * 16805 *
16018 * @param node the [ConstructorDeclaration] to evaluate 16806 * @param node the [ConstructorDeclaration] to evaluate
16019 * @return `true` if and only if an error code is generated on the passed node 16807 * @return `true` if and only if an error code is generated on the passed node
16020 * @see #initialFieldElementsMap 16808 * @see #initialFieldElementsMap
16021 * @see CompileTimeErrorCode#FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR 16809 * @see CompileTimeErrorCode#FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR
16022 * @see CompileTimeErrorCode#FINAL_INITIALIZED_MULTIPLE_TIMES 16810 * @see CompileTimeErrorCode#FINAL_INITIALIZED_MULTIPLE_TIMES
16023 */ 16811 */
16024 bool checkForAllFinalInitializedErrorCodes(ConstructorDeclaration node) { 16812 bool checkForAllFinalInitializedErrorCodes(ConstructorDeclaration node) {
16025 if (node.factoryKeyword != null || node.redirectedConstructor != null || nod e.externalKeyword != null) { 16813 if (node.factoryKeyword != null || node.redirectedConstructor != null || nod e.externalKeyword != null) {
16026 return false; 16814 return false;
16027 } 16815 }
16816 // Ignore if native class.
16028 if (_isInNativeClass) { 16817 if (_isInNativeClass) {
16029 return false; 16818 return false;
16030 } 16819 }
16031 bool foundError = false; 16820 bool foundError = false;
16032 Map<FieldElement, INIT_STATE> fieldElementsMap = new Map<FieldElement, INIT_ STATE>.from(_initialFieldElementsMap); 16821 Map<FieldElement, INIT_STATE> fieldElementsMap = new Map<FieldElement, INIT_ STATE>.from(_initialFieldElementsMap);
16822 // Visit all of the field formal parameters
16033 NodeList<FormalParameter> formalParameters = node.parameters.parameters; 16823 NodeList<FormalParameter> formalParameters = node.parameters.parameters;
16034 for (FormalParameter formalParameter in formalParameters) { 16824 for (FormalParameter formalParameter in formalParameters) {
16035 FormalParameter parameter = formalParameter; 16825 FormalParameter parameter = formalParameter;
16036 if (parameter is DefaultFormalParameter) { 16826 if (parameter is DefaultFormalParameter) {
16037 parameter = (parameter as DefaultFormalParameter).parameter; 16827 parameter = (parameter as DefaultFormalParameter).parameter;
16038 } 16828 }
16039 if (parameter is FieldFormalParameter) { 16829 if (parameter is FieldFormalParameter) {
16040 FieldElement fieldElement = (parameter.element as FieldFormalParameterEl ementImpl).field; 16830 FieldElement fieldElement = (parameter.element as FieldFormalParameterEl ementImpl).field;
16041 INIT_STATE state = fieldElementsMap[fieldElement]; 16831 INIT_STATE state = fieldElementsMap[fieldElement];
16042 if (identical(state, INIT_STATE.NOT_INIT)) { 16832 if (identical(state, INIT_STATE.NOT_INIT)) {
16043 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_FIELD_FORMAL; 16833 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_FIELD_FORMAL;
16044 } else if (identical(state, INIT_STATE.INIT_IN_DECLARATION)) { 16834 } else if (identical(state, INIT_STATE.INIT_IN_DECLARATION)) {
16045 if (fieldElement.isFinal || fieldElement.isConst) { 16835 if (fieldElement.isFinal || fieldElement.isConst) {
16046 _errorReporter.reportError3(StaticWarningCode.FINAL_INITIALIZED_IN_D ECLARATION_AND_CONSTRUCTOR, formalParameter.identifier, [fieldElement.displayNam e]); 16836 _errorReporter.reportError3(StaticWarningCode.FINAL_INITIALIZED_IN_D ECLARATION_AND_CONSTRUCTOR, formalParameter.identifier, [fieldElement.displayNam e]);
16047 foundError = true; 16837 foundError = true;
16048 } 16838 }
16049 } else if (identical(state, INIT_STATE.INIT_IN_FIELD_FORMAL)) { 16839 } else if (identical(state, INIT_STATE.INIT_IN_FIELD_FORMAL)) {
16050 if (fieldElement.isFinal || fieldElement.isConst) { 16840 if (fieldElement.isFinal || fieldElement.isConst) {
16051 _errorReporter.reportError3(CompileTimeErrorCode.FINAL_INITIALIZED_M ULTIPLE_TIMES, formalParameter.identifier, [fieldElement.displayName]); 16841 _errorReporter.reportError3(CompileTimeErrorCode.FINAL_INITIALIZED_M ULTIPLE_TIMES, formalParameter.identifier, [fieldElement.displayName]);
16052 foundError = true; 16842 foundError = true;
16053 } 16843 }
16054 } 16844 }
16055 } 16845 }
16056 } 16846 }
16847 // Visit all of the initializers
16057 NodeList<ConstructorInitializer> initializers = node.initializers; 16848 NodeList<ConstructorInitializer> initializers = node.initializers;
16058 for (ConstructorInitializer constructorInitializer in initializers) { 16849 for (ConstructorInitializer constructorInitializer in initializers) {
16059 if (constructorInitializer is RedirectingConstructorInvocation) { 16850 if (constructorInitializer is RedirectingConstructorInvocation) {
16060 return false; 16851 return false;
16061 } 16852 }
16062 if (constructorInitializer is ConstructorFieldInitializer) { 16853 if (constructorInitializer is ConstructorFieldInitializer) {
16063 ConstructorFieldInitializer constructorFieldInitializer = constructorIni tializer; 16854 ConstructorFieldInitializer constructorFieldInitializer = constructorIni tializer;
16064 SimpleIdentifier fieldName = constructorFieldInitializer.fieldName; 16855 SimpleIdentifier fieldName = constructorFieldInitializer.fieldName;
16065 Element element = fieldName.staticElement; 16856 Element element = fieldName.staticElement;
16066 if (element is FieldElement) { 16857 if (element is FieldElement) {
16067 FieldElement fieldElement = element; 16858 FieldElement fieldElement = element;
16068 INIT_STATE state = fieldElementsMap[fieldElement]; 16859 INIT_STATE state = fieldElementsMap[fieldElement];
16069 if (identical(state, INIT_STATE.NOT_INIT)) { 16860 if (identical(state, INIT_STATE.NOT_INIT)) {
16070 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_INITIALIZERS; 16861 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_INITIALIZERS;
16071 } else if (identical(state, INIT_STATE.INIT_IN_DECLARATION)) { 16862 } else if (identical(state, INIT_STATE.INIT_IN_DECLARATION)) {
16072 if (fieldElement.isFinal || fieldElement.isConst) { 16863 if (fieldElement.isFinal || fieldElement.isConst) {
16073 _errorReporter.reportError3(StaticWarningCode.FIELD_INITIALIZED_IN _INITIALIZER_AND_DECLARATION, fieldName, []); 16864 _errorReporter.reportError3(StaticWarningCode.FIELD_INITIALIZED_IN _INITIALIZER_AND_DECLARATION, fieldName, []);
16074 foundError = true; 16865 foundError = true;
16075 } 16866 }
16076 } else if (identical(state, INIT_STATE.INIT_IN_FIELD_FORMAL)) { 16867 } else if (identical(state, INIT_STATE.INIT_IN_FIELD_FORMAL)) {
16077 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZED_I N_PARAMETER_AND_INITIALIZER, fieldName, []); 16868 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZED_I N_PARAMETER_AND_INITIALIZER, fieldName, []);
16078 foundError = true; 16869 foundError = true;
16079 } else if (identical(state, INIT_STATE.INIT_IN_INITIALIZERS)) { 16870 } else if (identical(state, INIT_STATE.INIT_IN_INITIALIZERS)) {
16080 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZED_B Y_MULTIPLE_INITIALIZERS, fieldName, [fieldElement.displayName]); 16871 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZED_B Y_MULTIPLE_INITIALIZERS, fieldName, [fieldElement.displayName]);
16081 foundError = true; 16872 foundError = true;
16082 } 16873 }
16083 } 16874 }
16084 } 16875 }
16085 } 16876 }
16877 // Visit all of the states in the map to ensure that none were never initial ized.
16086 for (MapEntry<FieldElement, INIT_STATE> entry in getMapEntrySet(fieldElement sMap)) { 16878 for (MapEntry<FieldElement, INIT_STATE> entry in getMapEntrySet(fieldElement sMap)) {
16087 if (identical(entry.getValue(), INIT_STATE.NOT_INIT)) { 16879 if (identical(entry.getValue(), INIT_STATE.NOT_INIT)) {
16088 FieldElement fieldElement = entry.getKey(); 16880 FieldElement fieldElement = entry.getKey();
16089 if (fieldElement.isConst) { 16881 if (fieldElement.isConst) {
16090 _errorReporter.reportError3(CompileTimeErrorCode.CONST_NOT_INITIALIZED , node.returnType, [fieldElement.name]); 16882 _errorReporter.reportError3(CompileTimeErrorCode.CONST_NOT_INITIALIZED , node.returnType, [fieldElement.name]);
16091 foundError = true; 16883 foundError = true;
16092 } else if (fieldElement.isFinal) { 16884 } else if (fieldElement.isFinal) {
16093 _errorReporter.reportError3(StaticWarningCode.FINAL_NOT_INITIALIZED, n ode.returnType, [fieldElement.name]); 16885 _errorReporter.reportError3(StaticWarningCode.FINAL_NOT_INITIALIZED, n ode.returnType, [fieldElement.name]);
16094 foundError = true; 16886 foundError = true;
16095 } 16887 }
(...skipping 25 matching lines...) Expand all
16121 String executableElementName = executableElement.name; 16913 String executableElementName = executableElement.name;
16122 bool executableElementPrivate = Identifier.isPrivateName(executableElementNa me); 16914 bool executableElementPrivate = Identifier.isPrivateName(executableElementNa me);
16123 ExecutableElement overriddenExecutable = _inheritanceManager.lookupInheritan ce(_enclosingClass, executableElementName); 16915 ExecutableElement overriddenExecutable = _inheritanceManager.lookupInheritan ce(_enclosingClass, executableElementName);
16124 bool isGetter = false; 16916 bool isGetter = false;
16125 bool isSetter = false; 16917 bool isSetter = false;
16126 if (executableElement is PropertyAccessorElement) { 16918 if (executableElement is PropertyAccessorElement) {
16127 PropertyAccessorElement accessorElement = executableElement; 16919 PropertyAccessorElement accessorElement = executableElement;
16128 isGetter = accessorElement.isGetter; 16920 isGetter = accessorElement.isGetter;
16129 isSetter = accessorElement.isSetter; 16921 isSetter = accessorElement.isSetter;
16130 } 16922 }
16923 // SWC.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
16131 if (overriddenExecutable == null) { 16924 if (overriddenExecutable == null) {
16132 if (!isGetter && !isSetter && !executableElement.isOperator) { 16925 if (!isGetter && !isSetter && !executableElement.isOperator) {
16133 Set<ClassElement> visitedClasses = new Set<ClassElement>(); 16926 Set<ClassElement> visitedClasses = new Set<ClassElement>();
16134 InterfaceType superclassType = _enclosingClass.supertype; 16927 InterfaceType superclassType = _enclosingClass.supertype;
16135 ClassElement superclassElement = superclassType == null ? null : supercl assType.element; 16928 ClassElement superclassElement = superclassType == null ? null : supercl assType.element;
16136 while (superclassElement != null && !visitedClasses.contains(superclassE lement)) { 16929 while (superclassElement != null && !visitedClasses.contains(superclassE lement)) {
16137 visitedClasses.add(superclassElement); 16930 visitedClasses.add(superclassElement);
16138 LibraryElement superclassLibrary = superclassElement.library; 16931 LibraryElement superclassLibrary = superclassElement.library;
16932 // Check fields.
16139 List<FieldElement> fieldElts = superclassElement.fields; 16933 List<FieldElement> fieldElts = superclassElement.fields;
16140 for (FieldElement fieldElt in fieldElts) { 16934 for (FieldElement fieldElt in fieldElts) {
16935 // We need the same name.
16141 if (fieldElt.name != executableElementName) { 16936 if (fieldElt.name != executableElementName) {
16142 continue; 16937 continue;
16143 } 16938 }
16939 // Ignore if private in a different library - cannot collide.
16144 if (executableElementPrivate && _currentLibrary != superclassLibrary ) { 16940 if (executableElementPrivate && _currentLibrary != superclassLibrary ) {
16145 continue; 16941 continue;
16146 } 16942 }
16943 // instance vs. static
16147 if (fieldElt.isStatic) { 16944 if (fieldElt.isStatic) {
16148 _errorReporter.reportError3(StaticWarningCode.INSTANCE_METHOD_NAME _COLLIDES_WITH_SUPERCLASS_STATIC, errorNameTarget, [ 16945 _errorReporter.reportError3(StaticWarningCode.INSTANCE_METHOD_NAME _COLLIDES_WITH_SUPERCLASS_STATIC, errorNameTarget, [
16149 executableElementName, 16946 executableElementName,
16150 fieldElt.enclosingElement.displayName]); 16947 fieldElt.enclosingElement.displayName]);
16151 return true; 16948 return true;
16152 } 16949 }
16153 } 16950 }
16951 // Check methods.
16154 List<MethodElement> methodElements = superclassElement.methods; 16952 List<MethodElement> methodElements = superclassElement.methods;
16155 for (MethodElement methodElement in methodElements) { 16953 for (MethodElement methodElement in methodElements) {
16954 // We need the same name.
16156 if (methodElement.name != executableElementName) { 16955 if (methodElement.name != executableElementName) {
16157 continue; 16956 continue;
16158 } 16957 }
16958 // Ignore if private in a different library - cannot collide.
16159 if (executableElementPrivate && _currentLibrary != superclassLibrary ) { 16959 if (executableElementPrivate && _currentLibrary != superclassLibrary ) {
16160 continue; 16960 continue;
16161 } 16961 }
16962 // instance vs. static
16162 if (methodElement.isStatic) { 16963 if (methodElement.isStatic) {
16163 _errorReporter.reportError3(StaticWarningCode.INSTANCE_METHOD_NAME _COLLIDES_WITH_SUPERCLASS_STATIC, errorNameTarget, [ 16964 _errorReporter.reportError3(StaticWarningCode.INSTANCE_METHOD_NAME _COLLIDES_WITH_SUPERCLASS_STATIC, errorNameTarget, [
16164 executableElementName, 16965 executableElementName,
16165 methodElement.enclosingElement.displayName]); 16966 methodElement.enclosingElement.displayName]);
16166 return true; 16967 return true;
16167 } 16968 }
16168 } 16969 }
16169 superclassType = superclassElement.supertype; 16970 superclassType = superclassElement.supertype;
16170 superclassElement = superclassType == null ? null : superclassType.ele ment; 16971 superclassElement = superclassType == null ? null : superclassType.ele ment;
16171 } 16972 }
16172 } 16973 }
16173 return false; 16974 return false;
16174 } 16975 }
16175 FunctionType overridingFT = executableElement.type; 16976 FunctionType overridingFT = executableElement.type;
16176 FunctionType overriddenFT = overriddenExecutable.type; 16977 FunctionType overriddenFT = overriddenExecutable.type;
16177 InterfaceType enclosingType = _enclosingClass.type; 16978 InterfaceType enclosingType = _enclosingClass.type;
16178 overriddenFT = _inheritanceManager.substituteTypeArgumentsInMemberFromInheri tance(overriddenFT, executableElementName, enclosingType); 16979 overriddenFT = _inheritanceManager.substituteTypeArgumentsInMemberFromInheri tance(overriddenFT, executableElementName, enclosingType);
16179 if (overridingFT == null || overriddenFT == null) { 16980 if (overridingFT == null || overriddenFT == null) {
16180 return false; 16981 return false;
16181 } 16982 }
16182 Type2 overridingFTReturnType = overridingFT.returnType; 16983 Type2 overridingFTReturnType = overridingFT.returnType;
16183 Type2 overriddenFTReturnType = overriddenFT.returnType; 16984 Type2 overriddenFTReturnType = overriddenFT.returnType;
16184 List<Type2> overridingNormalPT = overridingFT.normalParameterTypes; 16985 List<Type2> overridingNormalPT = overridingFT.normalParameterTypes;
16185 List<Type2> overriddenNormalPT = overriddenFT.normalParameterTypes; 16986 List<Type2> overriddenNormalPT = overriddenFT.normalParameterTypes;
16186 List<Type2> overridingPositionalPT = overridingFT.optionalParameterTypes; 16987 List<Type2> overridingPositionalPT = overridingFT.optionalParameterTypes;
16187 List<Type2> overriddenPositionalPT = overriddenFT.optionalParameterTypes; 16988 List<Type2> overriddenPositionalPT = overriddenFT.optionalParameterTypes;
16188 Map<String, Type2> overridingNamedPT = overridingFT.namedParameterTypes; 16989 Map<String, Type2> overridingNamedPT = overridingFT.namedParameterTypes;
16189 Map<String, Type2> overriddenNamedPT = overriddenFT.namedParameterTypes; 16990 Map<String, Type2> overriddenNamedPT = overriddenFT.namedParameterTypes;
16991 // CTEC.INVALID_OVERRIDE_REQUIRED, CTEC.INVALID_OVERRIDE_POSITIONAL and CTEC .INVALID_OVERRIDE_NAMED
16190 if (overridingNormalPT.length > overriddenNormalPT.length) { 16992 if (overridingNormalPT.length > overriddenNormalPT.length) {
16191 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_REQUIRED, e rrorNameTarget, [ 16993 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_REQUIRED, e rrorNameTarget, [
16192 overriddenNormalPT.length, 16994 overriddenNormalPT.length,
16193 overriddenExecutable.enclosingElement.displayName]); 16995 overriddenExecutable.enclosingElement.displayName]);
16194 return true; 16996 return true;
16195 } 16997 }
16196 if (overridingNormalPT.length + overridingPositionalPT.length < overriddenPo sitionalPT.length + overriddenNormalPT.length) { 16998 if (overridingNormalPT.length + overridingPositionalPT.length < overriddenPo sitionalPT.length + overriddenNormalPT.length) {
16197 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_POSITIONAL, errorNameTarget, [ 16999 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_POSITIONAL, errorNameTarget, [
16198 overriddenPositionalPT.length + overriddenNormalPT.length, 17000 overriddenPositionalPT.length + overriddenNormalPT.length,
16199 overriddenExecutable.enclosingElement.displayName]); 17001 overriddenExecutable.enclosingElement.displayName]);
16200 return true; 17002 return true;
16201 } 17003 }
17004 // For each named parameter in the overridden method, verify that there is t he same name in
17005 // the overriding method, and in the same order.
16202 Set<String> overridingParameterNameSet = overridingNamedPT.keys.toSet(); 17006 Set<String> overridingParameterNameSet = overridingNamedPT.keys.toSet();
16203 JavaIterator<String> overriddenParameterNameIterator = new JavaIterator(over riddenNamedPT.keys.toSet()); 17007 JavaIterator<String> overriddenParameterNameIterator = new JavaIterator(over riddenNamedPT.keys.toSet());
16204 while (overriddenParameterNameIterator.hasNext) { 17008 while (overriddenParameterNameIterator.hasNext) {
16205 String overriddenParamName = overriddenParameterNameIterator.next(); 17009 String overriddenParamName = overriddenParameterNameIterator.next();
16206 if (!overridingParameterNameSet.contains(overriddenParamName)) { 17010 if (!overridingParameterNameSet.contains(overriddenParamName)) {
17011 // The overridden method expected the overriding method to have overridi ngParamName,
17012 // but it does not.
16207 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_NAMED, er rorNameTarget, [ 17013 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_NAMED, er rorNameTarget, [
16208 overriddenParamName, 17014 overriddenParamName,
16209 overriddenExecutable.enclosingElement.displayName]); 17015 overriddenExecutable.enclosingElement.displayName]);
16210 return true; 17016 return true;
16211 } 17017 }
16212 } 17018 }
17019 // SWC.INVALID_METHOD_OVERRIDE_RETURN_TYPE
16213 if (overriddenFTReturnType != VoidTypeImpl.instance && !overridingFTReturnTy pe.isAssignableTo(overriddenFTReturnType)) { 17020 if (overriddenFTReturnType != VoidTypeImpl.instance && !overridingFTReturnTy pe.isAssignableTo(overriddenFTReturnType)) {
16214 _errorReporter.reportError3(!isGetter ? StaticWarningCode.INVALID_METHOD_O VERRIDE_RETURN_TYPE : StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE, err orNameTarget, [ 17021 _errorReporter.reportError3(!isGetter ? StaticWarningCode.INVALID_METHOD_O VERRIDE_RETURN_TYPE : StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE, err orNameTarget, [
16215 overridingFTReturnType.displayName, 17022 overridingFTReturnType.displayName,
16216 overriddenFTReturnType.displayName, 17023 overriddenFTReturnType.displayName,
16217 overriddenExecutable.enclosingElement.displayName]); 17024 overriddenExecutable.enclosingElement.displayName]);
16218 return true; 17025 return true;
16219 } 17026 }
17027 // SWC.INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
16220 if (parameterLocations == null) { 17028 if (parameterLocations == null) {
16221 return false; 17029 return false;
16222 } 17030 }
16223 int parameterIndex = 0; 17031 int parameterIndex = 0;
16224 for (int i = 0; i < overridingNormalPT.length; i++) { 17032 for (int i = 0; i < overridingNormalPT.length; i++) {
16225 if (!overridingNormalPT[i].isAssignableTo(overriddenNormalPT[i])) { 17033 if (!overridingNormalPT[i].isAssignableTo(overriddenNormalPT[i])) {
16226 _errorReporter.reportError3(!isSetter ? StaticWarningCode.INVALID_METHOD _OVERRIDE_NORMAL_PARAM_TYPE : StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_P ARAM_TYPE, parameterLocations[parameterIndex], [ 17034 _errorReporter.reportError3(!isSetter ? StaticWarningCode.INVALID_METHOD _OVERRIDE_NORMAL_PARAM_TYPE : StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_P ARAM_TYPE, parameterLocations[parameterIndex], [
16227 overridingNormalPT[i].displayName, 17035 overridingNormalPT[i].displayName,
16228 overriddenNormalPT[i].displayName, 17036 overriddenNormalPT[i].displayName,
16229 overriddenExecutable.enclosingElement.displayName]); 17037 overriddenExecutable.enclosingElement.displayName]);
16230 return true; 17038 return true;
16231 } 17039 }
16232 parameterIndex++; 17040 parameterIndex++;
16233 } 17041 }
17042 // SWC.INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE
16234 for (int i = 0; i < overriddenPositionalPT.length; i++) { 17043 for (int i = 0; i < overriddenPositionalPT.length; i++) {
16235 if (!overridingPositionalPT[i].isAssignableTo(overriddenPositionalPT[i])) { 17044 if (!overridingPositionalPT[i].isAssignableTo(overriddenPositionalPT[i])) {
16236 _errorReporter.reportError3(StaticWarningCode.INVALID_METHOD_OVERRIDE_OP TIONAL_PARAM_TYPE, parameterLocations[parameterIndex], [ 17045 _errorReporter.reportError3(StaticWarningCode.INVALID_METHOD_OVERRIDE_OP TIONAL_PARAM_TYPE, parameterLocations[parameterIndex], [
16237 overridingPositionalPT[i].displayName, 17046 overridingPositionalPT[i].displayName,
16238 overriddenPositionalPT[i].displayName, 17047 overriddenPositionalPT[i].displayName,
16239 overriddenExecutable.enclosingElement.displayName]); 17048 overriddenExecutable.enclosingElement.displayName]);
16240 return true; 17049 return true;
16241 } 17050 }
16242 parameterIndex++; 17051 parameterIndex++;
16243 } 17052 }
17053 // SWC.INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE & SWC.INVALID_OVERRIDE_DIFFE RENT_DEFAULT_VALUES
16244 JavaIterator<MapEntry<String, Type2>> overriddenNamedPTIterator = new JavaIt erator(getMapEntrySet(overriddenNamedPT)); 17054 JavaIterator<MapEntry<String, Type2>> overriddenNamedPTIterator = new JavaIt erator(getMapEntrySet(overriddenNamedPT));
16245 while (overriddenNamedPTIterator.hasNext) { 17055 while (overriddenNamedPTIterator.hasNext) {
16246 MapEntry<String, Type2> overriddenNamedPTEntry = overriddenNamedPTIterator .next(); 17056 MapEntry<String, Type2> overriddenNamedPTEntry = overriddenNamedPTIterator .next();
16247 Type2 overridingType = overridingNamedPT[overriddenNamedPTEntry.getKey()]; 17057 Type2 overridingType = overridingNamedPT[overriddenNamedPTEntry.getKey()];
16248 if (overridingType == null) { 17058 if (overridingType == null) {
17059 // Error, this is never reached- INVALID_OVERRIDE_NAMED would have been created above if
17060 // this could be reached.
16249 continue; 17061 continue;
16250 } 17062 }
16251 if (!overriddenNamedPTEntry.getValue().isAssignableTo(overridingType)) { 17063 if (!overriddenNamedPTEntry.getValue().isAssignableTo(overridingType)) {
17064 // lookup the parameter for the error to select
16252 ParameterElement parameterToSelect = null; 17065 ParameterElement parameterToSelect = null;
16253 ASTNode parameterLocationToSelect = null; 17066 ASTNode parameterLocationToSelect = null;
16254 for (int i = 0; i < parameters.length; i++) { 17067 for (int i = 0; i < parameters.length; i++) {
16255 ParameterElement parameter = parameters[i]; 17068 ParameterElement parameter = parameters[i];
16256 if (identical(parameter.parameterKind, ParameterKind.NAMED) && overrid denNamedPTEntry.getKey() == parameter.name) { 17069 if (identical(parameter.parameterKind, ParameterKind.NAMED) && overrid denNamedPTEntry.getKey() == parameter.name) {
16257 parameterToSelect = parameter; 17070 parameterToSelect = parameter;
16258 parameterLocationToSelect = parameterLocations[i]; 17071 parameterLocationToSelect = parameterLocations[i];
16259 break; 17072 break;
16260 } 17073 }
16261 } 17074 }
16262 if (parameterToSelect != null) { 17075 if (parameterToSelect != null) {
16263 _errorReporter.reportError3(StaticWarningCode.INVALID_METHOD_OVERRIDE_ NAMED_PARAM_TYPE, parameterLocationToSelect, [ 17076 _errorReporter.reportError3(StaticWarningCode.INVALID_METHOD_OVERRIDE_ NAMED_PARAM_TYPE, parameterLocationToSelect, [
16264 overridingType.displayName, 17077 overridingType.displayName,
16265 overriddenNamedPTEntry.getValue().displayName, 17078 overriddenNamedPTEntry.getValue().displayName,
16266 overriddenExecutable.enclosingElement.displayName]); 17079 overriddenExecutable.enclosingElement.displayName]);
16267 return true; 17080 return true;
16268 } 17081 }
16269 } 17082 }
16270 } 17083 }
17084 // SWC.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES
17085 //
17086 // Create three arrays: an array of the optional parameter ASTs (FormalParam eters), an array of
17087 // the optional parameters elements from our method, and finally an array of the optional
17088 // parameter elements from the method we are overriding.
17089 //
16271 bool foundError = false; 17090 bool foundError = false;
16272 List<ASTNode> formalParameters = new List<ASTNode>(); 17091 List<ASTNode> formalParameters = new List<ASTNode>();
16273 List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>(); 17092 List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>();
16274 List<ParameterElementImpl> overriddenParameterElts = new List<ParameterEleme ntImpl>(); 17093 List<ParameterElementImpl> overriddenParameterElts = new List<ParameterEleme ntImpl>();
16275 List<ParameterElement> overriddenPEs = overriddenExecutable.parameters; 17094 List<ParameterElement> overriddenPEs = overriddenExecutable.parameters;
16276 for (int i = 0; i < parameters.length; i++) { 17095 for (int i = 0; i < parameters.length; i++) {
16277 ParameterElement parameter = parameters[i]; 17096 ParameterElement parameter = parameters[i];
16278 if (parameter.parameterKind.isOptional) { 17097 if (parameter.parameterKind.isOptional) {
16279 formalParameters.add(parameterLocations[i]); 17098 formalParameters.add(parameterLocations[i]);
16280 parameterElts.add(parameter as ParameterElementImpl); 17099 parameterElts.add(parameter as ParameterElementImpl);
16281 } 17100 }
16282 } 17101 }
16283 for (ParameterElement parameterElt in overriddenPEs) { 17102 for (ParameterElement parameterElt in overriddenPEs) {
16284 if (parameterElt.parameterKind.isOptional) { 17103 if (parameterElt.parameterKind.isOptional) {
16285 if (parameterElt is ParameterElementImpl) { 17104 if (parameterElt is ParameterElementImpl) {
16286 overriddenParameterElts.add(parameterElt); 17105 overriddenParameterElts.add(parameterElt);
16287 } 17106 }
16288 } 17107 }
16289 } 17108 }
17109 //
17110 // Next compare the list of optional parameter elements to the list of overr idden optional
17111 // parameter elements.
17112 //
16290 if (parameterElts.length > 0) { 17113 if (parameterElts.length > 0) {
16291 if (identical(parameterElts[0].parameterKind, ParameterKind.NAMED)) { 17114 if (identical(parameterElts[0].parameterKind, ParameterKind.NAMED)) {
17115 // Named parameters, consider the names when matching the parameterElts to the overriddenParameterElts
16292 for (int i = 0; i < parameterElts.length; i++) { 17116 for (int i = 0; i < parameterElts.length; i++) {
16293 ParameterElementImpl parameterElt = parameterElts[i]; 17117 ParameterElementImpl parameterElt = parameterElts[i];
16294 EvaluationResultImpl result = parameterElt.evaluationResult; 17118 EvaluationResultImpl result = parameterElt.evaluationResult;
17119 // TODO (jwren) Ignore Object types, see Dart bug 11287
16295 if (isUserDefinedObject(result)) { 17120 if (isUserDefinedObject(result)) {
16296 continue; 17121 continue;
16297 } 17122 }
16298 String parameterName = parameterElt.name; 17123 String parameterName = parameterElt.name;
16299 for (int j = 0; j < overriddenParameterElts.length; j++) { 17124 for (int j = 0; j < overriddenParameterElts.length; j++) {
16300 ParameterElementImpl overriddenParameterElt = overriddenParameterElt s[j]; 17125 ParameterElementImpl overriddenParameterElt = overriddenParameterElt s[j];
16301 String overriddenParameterName = overriddenParameterElt.name; 17126 String overriddenParameterName = overriddenParameterElt.name;
16302 if (parameterName != null && parameterName == overriddenParameterNam e) { 17127 if (parameterName != null && parameterName == overriddenParameterNam e) {
16303 EvaluationResultImpl overriddenResult = overriddenParameterElt.eva luationResult; 17128 EvaluationResultImpl overriddenResult = overriddenParameterElt.eva luationResult;
16304 if (isUserDefinedObject(overriddenResult)) { 17129 if (isUserDefinedObject(overriddenResult)) {
16305 break; 17130 break;
16306 } 17131 }
16307 if (!result.equalValues(_typeProvider, overriddenResult)) { 17132 if (!result.equalValues(_typeProvider, overriddenResult)) {
16308 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_D IFFERENT_DEFAULT_VALUES_NAMED, formalParameters[i], [ 17133 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_D IFFERENT_DEFAULT_VALUES_NAMED, formalParameters[i], [
16309 overriddenExecutable.enclosingElement.displayName, 17134 overriddenExecutable.enclosingElement.displayName,
16310 overriddenExecutable.displayName, 17135 overriddenExecutable.displayName,
16311 parameterName]); 17136 parameterName]);
16312 foundError = true; 17137 foundError = true;
16313 } 17138 }
16314 } 17139 }
16315 } 17140 }
16316 } 17141 }
16317 } else { 17142 } else {
17143 // Positional parameters, consider the positions when matching the param eterElts to the overriddenParameterElts
16318 for (int i = 0; i < parameterElts.length && i < overriddenParameterElts. length; i++) { 17144 for (int i = 0; i < parameterElts.length && i < overriddenParameterElts. length; i++) {
16319 ParameterElementImpl parameterElt = parameterElts[i]; 17145 ParameterElementImpl parameterElt = parameterElts[i];
16320 EvaluationResultImpl result = parameterElt.evaluationResult; 17146 EvaluationResultImpl result = parameterElt.evaluationResult;
17147 // TODO (jwren) Ignore Object types, see Dart bug 11287
16321 if (isUserDefinedObject(result)) { 17148 if (isUserDefinedObject(result)) {
16322 continue; 17149 continue;
16323 } 17150 }
16324 ParameterElementImpl overriddenParameterElt = overriddenParameterElts[ i]; 17151 ParameterElementImpl overriddenParameterElt = overriddenParameterElts[ i];
16325 EvaluationResultImpl overriddenResult = overriddenParameterElt.evaluat ionResult; 17152 EvaluationResultImpl overriddenResult = overriddenParameterElt.evaluat ionResult;
16326 if (isUserDefinedObject(overriddenResult)) { 17153 if (isUserDefinedObject(overriddenResult)) {
16327 continue; 17154 continue;
16328 } 17155 }
16329 if (!result.equalValues(_typeProvider, overriddenResult)) { 17156 if (!result.equalValues(_typeProvider, overriddenResult)) {
16330 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_DIFFE RENT_DEFAULT_VALUES_POSITIONAL, formalParameters[i], [ 17157 _errorReporter.reportError3(StaticWarningCode.INVALID_OVERRIDE_DIFFE RENT_DEFAULT_VALUES_POSITIONAL, formalParameters[i], [
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
16428 /** 17255 /**
16429 * This checks error related to the redirected constructors. 17256 * This checks error related to the redirected constructors.
16430 * 17257 *
16431 * @param node the constructor declaration to evaluate 17258 * @param node the constructor declaration to evaluate
16432 * @return `true` if and only if an error code is generated on the passed node 17259 * @return `true` if and only if an error code is generated on the passed node
16433 * @see StaticWarningCode#REDIRECT_TO_INVALID_RETURN_TYPE 17260 * @see StaticWarningCode#REDIRECT_TO_INVALID_RETURN_TYPE
16434 * @see StaticWarningCode#REDIRECT_TO_INVALID_FUNCTION_TYPE 17261 * @see StaticWarningCode#REDIRECT_TO_INVALID_FUNCTION_TYPE
16435 * @see StaticWarningCode#REDIRECT_TO_MISSING_CONSTRUCTOR 17262 * @see StaticWarningCode#REDIRECT_TO_MISSING_CONSTRUCTOR
16436 */ 17263 */
16437 bool checkForAllRedirectConstructorErrorCodes(ConstructorDeclaration node) { 17264 bool checkForAllRedirectConstructorErrorCodes(ConstructorDeclaration node) {
17265 //
17266 // Prepare redirected constructor node
17267 //
16438 ConstructorName redirectedConstructor = node.redirectedConstructor; 17268 ConstructorName redirectedConstructor = node.redirectedConstructor;
16439 if (redirectedConstructor == null) { 17269 if (redirectedConstructor == null) {
16440 return false; 17270 return false;
16441 } 17271 }
17272 //
17273 // Prepare redirected constructor type
17274 //
16442 ConstructorElement redirectedElement = redirectedConstructor.staticElement; 17275 ConstructorElement redirectedElement = redirectedConstructor.staticElement;
16443 if (redirectedElement == null) { 17276 if (redirectedElement == null) {
17277 //
17278 // If the element is null, we check for the REDIRECT_TO_MISSING_CONSTRUCTO R case
17279 //
16444 TypeName constructorTypeName = redirectedConstructor.type; 17280 TypeName constructorTypeName = redirectedConstructor.type;
16445 Type2 redirectedType = constructorTypeName.type; 17281 Type2 redirectedType = constructorTypeName.type;
16446 if (redirectedType != null && redirectedType.element != null && !redirecte dType.isDynamic) { 17282 if (redirectedType != null && redirectedType.element != null && !redirecte dType.isDynamic) {
17283 //
17284 // Prepare the constructor name
17285 //
16447 String constructorStrName = constructorTypeName.name.name; 17286 String constructorStrName = constructorTypeName.name.name;
16448 if (redirectedConstructor.name != null) { 17287 if (redirectedConstructor.name != null) {
16449 constructorStrName += ".${redirectedConstructor.name.name}"; 17288 constructorStrName += ".${redirectedConstructor.name.name}";
16450 } 17289 }
16451 ErrorCode errorCode = (node.constKeyword != null ? CompileTimeErrorCode. REDIRECT_TO_MISSING_CONSTRUCTOR : StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUC TOR) as ErrorCode; 17290 ErrorCode errorCode = (node.constKeyword != null ? CompileTimeErrorCode. REDIRECT_TO_MISSING_CONSTRUCTOR : StaticWarningCode.REDIRECT_TO_MISSING_CONSTRUC TOR) as ErrorCode;
16452 _errorReporter.reportError3(errorCode, redirectedConstructor, [construct orStrName, redirectedType.displayName]); 17291 _errorReporter.reportError3(errorCode, redirectedConstructor, [construct orStrName, redirectedType.displayName]);
16453 return true; 17292 return true;
16454 } 17293 }
16455 return false; 17294 return false;
16456 } 17295 }
16457 FunctionType redirectedType = redirectedElement.type; 17296 FunctionType redirectedType = redirectedElement.type;
16458 Type2 redirectedReturnType = redirectedType.returnType; 17297 Type2 redirectedReturnType = redirectedType.returnType;
17298 //
17299 // Report specific problem when return type is incompatible
17300 //
16459 FunctionType constructorType = node.element.type; 17301 FunctionType constructorType = node.element.type;
16460 Type2 constructorReturnType = constructorType.returnType; 17302 Type2 constructorReturnType = constructorType.returnType;
16461 if (!redirectedReturnType.isAssignableTo(constructorReturnType)) { 17303 if (!redirectedReturnType.isAssignableTo(constructorReturnType)) {
16462 _errorReporter.reportError3(StaticWarningCode.REDIRECT_TO_INVALID_RETURN_T YPE, redirectedConstructor, [redirectedReturnType, constructorReturnType]); 17304 _errorReporter.reportError3(StaticWarningCode.REDIRECT_TO_INVALID_RETURN_T YPE, redirectedConstructor, [redirectedReturnType, constructorReturnType]);
16463 return true; 17305 return true;
16464 } 17306 }
17307 //
17308 // Check parameters
17309 //
16465 if (!redirectedType.isSubtypeOf(constructorType)) { 17310 if (!redirectedType.isSubtypeOf(constructorType)) {
16466 _errorReporter.reportError3(StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION _TYPE, redirectedConstructor, [redirectedType, constructorType]); 17311 _errorReporter.reportError3(StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION _TYPE, redirectedConstructor, [redirectedType, constructorType]);
16467 return true; 17312 return true;
16468 } 17313 }
16469 return false; 17314 return false;
16470 } 17315 }
16471 17316
16472 /** 17317 /**
16473 * This checks that the return statement of the form <i>return e;</i> is not i n a generative 17318 * This checks that the return statement of the form <i>return e;</i> is not i n a generative
16474 * constructor. 17319 * constructor.
16475 * 17320 *
16476 * This checks that return statements without expressions are not in a generat ive constructor and 17321 * This checks that return statements without expressions are not in a generat ive constructor and
16477 * the return type is not assignable to `null`; that is, we don't have `return ;` if 17322 * the return type is not assignable to `null`; that is, we don't have `return ;` if
16478 * the enclosing method has a return type. 17323 * the enclosing method has a return type.
16479 * 17324 *
16480 * This checks that the return type matches the type of the declared return ty pe in the enclosing 17325 * This checks that the return type matches the type of the declared return ty pe in the enclosing
16481 * method or function. 17326 * method or function.
16482 * 17327 *
16483 * @param node the return statement to evaluate 17328 * @param node the return statement to evaluate
16484 * @return `true` if and only if an error code is generated on the passed node 17329 * @return `true` if and only if an error code is generated on the passed node
16485 * @see CompileTimeErrorCode#RETURN_IN_GENERATIVE_CONSTRUCTOR 17330 * @see CompileTimeErrorCode#RETURN_IN_GENERATIVE_CONSTRUCTOR
16486 * @see StaticWarningCode#RETURN_WITHOUT_VALUE 17331 * @see StaticWarningCode#RETURN_WITHOUT_VALUE
16487 * @see StaticTypeWarningCode#RETURN_OF_INVALID_TYPE 17332 * @see StaticTypeWarningCode#RETURN_OF_INVALID_TYPE
16488 */ 17333 */
16489 bool checkForAllReturnStatementErrorCodes(ReturnStatement node) { 17334 bool checkForAllReturnStatementErrorCodes(ReturnStatement node) {
16490 FunctionType functionType = _enclosingFunction == null ? null : _enclosingFu nction.type; 17335 FunctionType functionType = _enclosingFunction == null ? null : _enclosingFu nction.type;
16491 Type2 expectedReturnType = functionType == null ? DynamicTypeImpl.instance : functionType.returnType; 17336 Type2 expectedReturnType = functionType == null ? DynamicTypeImpl.instance : functionType.returnType;
16492 Expression returnExpression = node.expression; 17337 Expression returnExpression = node.expression;
17338 // RETURN_IN_GENERATIVE_CONSTRUCTOR
16493 bool isGenerativeConstructor = _enclosingFunction is ConstructorElement && ! (_enclosingFunction as ConstructorElement).isFactory; 17339 bool isGenerativeConstructor = _enclosingFunction is ConstructorElement && ! (_enclosingFunction as ConstructorElement).isFactory;
16494 if (isGenerativeConstructor) { 17340 if (isGenerativeConstructor) {
16495 if (returnExpression == null) { 17341 if (returnExpression == null) {
16496 return false; 17342 return false;
16497 } 17343 }
16498 _errorReporter.reportError3(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONS TRUCTOR, returnExpression, []); 17344 _errorReporter.reportError3(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONS TRUCTOR, returnExpression, []);
16499 return true; 17345 return true;
16500 } 17346 }
17347 // RETURN_WITHOUT_VALUE
16501 if (returnExpression == null) { 17348 if (returnExpression == null) {
16502 if (VoidTypeImpl.instance.isAssignableTo(expectedReturnType)) { 17349 if (VoidTypeImpl.instance.isAssignableTo(expectedReturnType)) {
16503 return false; 17350 return false;
16504 } 17351 }
16505 _errorReporter.reportError3(StaticWarningCode.RETURN_WITHOUT_VALUE, node, []); 17352 _errorReporter.reportError3(StaticWarningCode.RETURN_WITHOUT_VALUE, node, []);
16506 return true; 17353 return true;
16507 } 17354 }
17355 // RETURN_OF_INVALID_TYPE
16508 return checkForReturnOfInvalidType(returnExpression, expectedReturnType); 17356 return checkForReturnOfInvalidType(returnExpression, expectedReturnType);
16509 } 17357 }
16510 17358
16511 /** 17359 /**
16512 * This verifies that the export namespace of the passed export directive does not export any name 17360 * This verifies that the export namespace of the passed export directive does not export any name
16513 * already exported by other export directive. 17361 * already exported by other export directive.
16514 * 17362 *
16515 * @param node the export directive node to report problem on 17363 * @param node the export directive node to report problem on
16516 * @return `true` if and only if an error code is generated on the passed node 17364 * @return `true` if and only if an error code is generated on the passed node
16517 * @see CompileTimeErrorCode#AMBIGUOUS_EXPORT 17365 * @see CompileTimeErrorCode#AMBIGUOUS_EXPORT
16518 */ 17366 */
16519 bool checkForAmbiguousExport(ExportDirective node) { 17367 bool checkForAmbiguousExport(ExportDirective node) {
17368 // prepare ExportElement
16520 if (node.element is! ExportElement) { 17369 if (node.element is! ExportElement) {
16521 return false; 17370 return false;
16522 } 17371 }
16523 ExportElement exportElement = node.element as ExportElement; 17372 ExportElement exportElement = node.element as ExportElement;
17373 // prepare exported library
16524 LibraryElement exportedLibrary = exportElement.exportedLibrary; 17374 LibraryElement exportedLibrary = exportElement.exportedLibrary;
16525 if (exportedLibrary == null) { 17375 if (exportedLibrary == null) {
16526 return false; 17376 return false;
16527 } 17377 }
17378 // check exported names
16528 Namespace namespace = new NamespaceBuilder().createExportNamespace(exportEle ment); 17379 Namespace namespace = new NamespaceBuilder().createExportNamespace(exportEle ment);
16529 Map<String, Element> definedNames = namespace.definedNames; 17380 Map<String, Element> definedNames = namespace.definedNames;
16530 for (MapEntry<String, Element> definedEntry in getMapEntrySet(definedNames)) { 17381 for (MapEntry<String, Element> definedEntry in getMapEntrySet(definedNames)) {
16531 String name = definedEntry.getKey(); 17382 String name = definedEntry.getKey();
16532 Element element = definedEntry.getValue(); 17383 Element element = definedEntry.getValue();
16533 Element prevElement = _exportedElements[name]; 17384 Element prevElement = _exportedElements[name];
16534 if (element != null && prevElement != null && prevElement != element) { 17385 if (element != null && prevElement != null && prevElement != element) {
16535 _errorReporter.reportError3(CompileTimeErrorCode.AMBIGUOUS_EXPORT, node, [ 17386 _errorReporter.reportError3(CompileTimeErrorCode.AMBIGUOUS_EXPORT, node, [
16536 name, 17387 name,
16537 prevElement.library.definingCompilationUnit.displayName, 17388 prevElement.library.definingCompilationUnit.displayName,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
16569 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE 17420 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
16570 */ 17421 */
16571 bool checkForArgumentTypeNotAssignable(ArgumentList argumentList) { 17422 bool checkForArgumentTypeNotAssignable(ArgumentList argumentList) {
16572 if (argumentList == null) { 17423 if (argumentList == null) {
16573 return false; 17424 return false;
16574 } 17425 }
16575 bool problemReported = false; 17426 bool problemReported = false;
16576 for (Expression argument in argumentList.arguments) { 17427 for (Expression argument in argumentList.arguments) {
16577 problemReported = javaBooleanOr(problemReported, checkForArgumentTypeNotAs signable2(argument)); 17428 problemReported = javaBooleanOr(problemReported, checkForArgumentTypeNotAs signable2(argument));
16578 } 17429 }
17430 // done
16579 return problemReported; 17431 return problemReported;
16580 } 17432 }
16581 17433
16582 /** 17434 /**
16583 * This verifies that the passed argument can be assigned to its corresponding parameter. 17435 * This verifies that the passed argument can be assigned to its corresponding parameter.
16584 * 17436 *
16585 * @param argument the argument to evaluate 17437 * @param argument the argument to evaluate
16586 * @return `true` if and only if an error code is generated on the passed node 17438 * @return `true` if and only if an error code is generated on the passed node
16587 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE 17439 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
16588 */ 17440 */
(...skipping 25 matching lines...) Expand all
16614 * @param expression the expression to evaluate 17466 * @param expression the expression to evaluate
16615 * @param expectedStaticType the expected static type of the parameter 17467 * @param expectedStaticType the expected static type of the parameter
16616 * @param actualStaticType the actual static type of the argument 17468 * @param actualStaticType the actual static type of the argument
16617 * @param expectedPropagatedType the expected propagated type of the parameter , may be 17469 * @param expectedPropagatedType the expected propagated type of the parameter , may be
16618 * `null` 17470 * `null`
16619 * @param actualPropagatedType the expected propagated type of the parameter, may be `null` 17471 * @param actualPropagatedType the expected propagated type of the parameter, may be `null`
16620 * @return `true` if and only if an error code is generated on the passed node 17472 * @return `true` if and only if an error code is generated on the passed node
16621 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE 17473 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
16622 */ 17474 */
16623 bool checkForArgumentTypeNotAssignable4(Expression expression, Type2 expectedS taticType, Type2 actualStaticType, Type2 expectedPropagatedType, Type2 actualPro pagatedType, ErrorCode errorCode) { 17475 bool checkForArgumentTypeNotAssignable4(Expression expression, Type2 expectedS taticType, Type2 actualStaticType, Type2 expectedPropagatedType, Type2 actualPro pagatedType, ErrorCode errorCode) {
17476 //
17477 // Test static type information
17478 //
16624 if (actualStaticType == null || expectedStaticType == null) { 17479 if (actualStaticType == null || expectedStaticType == null) {
16625 return false; 17480 return false;
16626 } 17481 }
16627 if (actualStaticType.isAssignableTo(expectedStaticType)) { 17482 if (actualStaticType.isAssignableTo(expectedStaticType)) {
16628 return false; 17483 return false;
16629 } 17484 }
16630 _errorReporter.reportError3(errorCode, expression, [ 17485 _errorReporter.reportError3(errorCode, expression, [
16631 actualStaticType.displayName, 17486 actualStaticType.displayName,
16632 expectedStaticType.displayName]); 17487 expectedStaticType.displayName]);
16633 return true; 17488 return true;
(...skipping 14 matching lines...) Expand all
16648 /** 17503 /**
16649 * This verifies that the passed expression is not final. 17504 * This verifies that the passed expression is not final.
16650 * 17505 *
16651 * @param node the expression to evaluate 17506 * @param node the expression to evaluate
16652 * @return `true` if and only if an error code is generated on the passed node 17507 * @return `true` if and only if an error code is generated on the passed node
16653 * @see StaticWarningCode#ASSIGNMENT_TO_CONST 17508 * @see StaticWarningCode#ASSIGNMENT_TO_CONST
16654 * @see StaticWarningCode#ASSIGNMENT_TO_FINAL 17509 * @see StaticWarningCode#ASSIGNMENT_TO_FINAL
16655 * @see StaticWarningCode#ASSIGNMENT_TO_METHOD 17510 * @see StaticWarningCode#ASSIGNMENT_TO_METHOD
16656 */ 17511 */
16657 bool checkForAssignmentToFinal2(Expression expression) { 17512 bool checkForAssignmentToFinal2(Expression expression) {
17513 // prepare element
16658 Element element = null; 17514 Element element = null;
16659 if (expression is Identifier) { 17515 if (expression is Identifier) {
16660 element = expression.staticElement; 17516 element = expression.staticElement;
16661 } 17517 }
16662 if (expression is PropertyAccess) { 17518 if (expression is PropertyAccess) {
16663 element = expression.propertyName.staticElement; 17519 element = expression.propertyName.staticElement;
16664 } 17520 }
17521 // check if element is assignable
16665 if (element is PropertyAccessorElement) { 17522 if (element is PropertyAccessorElement) {
16666 PropertyAccessorElement accessor = element as PropertyAccessorElement; 17523 PropertyAccessorElement accessor = element as PropertyAccessorElement;
16667 element = accessor.variable; 17524 element = accessor.variable;
16668 } 17525 }
16669 if (element is VariableElement) { 17526 if (element is VariableElement) {
16670 VariableElement variable = element as VariableElement; 17527 VariableElement variable = element as VariableElement;
16671 if (variable.isConst) { 17528 if (variable.isConst) {
16672 _errorReporter.reportError3(StaticWarningCode.ASSIGNMENT_TO_CONST, expre ssion, []); 17529 _errorReporter.reportError3(StaticWarningCode.ASSIGNMENT_TO_CONST, expre ssion, []);
16673 return true; 17530 return true;
16674 } 17531 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
16713 * This verifies that the given switch case is terminated with 'break', 'conti nue', 'return' or 17570 * This verifies that the given switch case is terminated with 'break', 'conti nue', 'return' or
16714 * 'throw'. 17571 * 'throw'.
16715 * 17572 *
16716 * @param node the switch case to evaluate 17573 * @param node the switch case to evaluate
16717 * @return `true` if and only if an error code is generated on the passed node 17574 * @return `true` if and only if an error code is generated on the passed node
16718 * @see StaticWarningCode#CASE_BLOCK_NOT_TERMINATED 17575 * @see StaticWarningCode#CASE_BLOCK_NOT_TERMINATED
16719 */ 17576 */
16720 bool checkForCaseBlockNotTerminated(SwitchCase node) { 17577 bool checkForCaseBlockNotTerminated(SwitchCase node) {
16721 NodeList<Statement> statements = node.statements; 17578 NodeList<Statement> statements = node.statements;
16722 if (statements.isEmpty) { 17579 if (statements.isEmpty) {
17580 // fall-through without statements at all
16723 ASTNode parent = node.parent; 17581 ASTNode parent = node.parent;
16724 if (parent is SwitchStatement) { 17582 if (parent is SwitchStatement) {
16725 SwitchStatement switchStatement = parent; 17583 SwitchStatement switchStatement = parent;
16726 NodeList<SwitchMember> members = switchStatement.members; 17584 NodeList<SwitchMember> members = switchStatement.members;
16727 int index = members.indexOf(node); 17585 int index = members.indexOf(node);
16728 if (index != -1 && index < members.length - 1) { 17586 if (index != -1 && index < members.length - 1) {
16729 return false; 17587 return false;
16730 } 17588 }
16731 } 17589 }
16732 } else { 17590 } else {
16733 Statement statement = statements[statements.length - 1]; 17591 Statement statement = statements[statements.length - 1];
17592 // terminated with statement
16734 if (statement is BreakStatement || statement is ContinueStatement || state ment is ReturnStatement) { 17593 if (statement is BreakStatement || statement is ContinueStatement || state ment is ReturnStatement) {
16735 return false; 17594 return false;
16736 } 17595 }
17596 // terminated with 'throw' expression
16737 if (statement is ExpressionStatement) { 17597 if (statement is ExpressionStatement) {
16738 Expression expression = statement.expression; 17598 Expression expression = statement.expression;
16739 if (expression is ThrowExpression) { 17599 if (expression is ThrowExpression) {
16740 return false; 17600 return false;
16741 } 17601 }
16742 } 17602 }
16743 } 17603 }
17604 // report error
16744 _errorReporter.reportError6(StaticWarningCode.CASE_BLOCK_NOT_TERMINATED, nod e.keyword, []); 17605 _errorReporter.reportError6(StaticWarningCode.CASE_BLOCK_NOT_TERMINATED, nod e.keyword, []);
16745 return true; 17606 return true;
16746 } 17607 }
16747 17608
16748 /** 17609 /**
16749 * This verifies that the switch cases in the given switch statement is termin ated with 'break', 17610 * This verifies that the switch cases in the given switch statement is termin ated with 'break',
16750 * 'continue', 'return' or 'throw'. 17611 * 'continue', 'return' or 'throw'.
16751 * 17612 *
16752 * @param node the switch statement containing the cases to be checked 17613 * @param node the switch statement containing the cases to be checked
16753 * @return `true` if and only if an error code is generated on the passed node 17614 * @return `true` if and only if an error code is generated on the passed node
(...skipping 18 matching lines...) Expand all
16772 * 17633 *
16773 * @param node the switch statement to evaluate 17634 * @param node the switch statement to evaluate
16774 * @param type the common type of all 'case' expressions 17635 * @param type the common type of all 'case' expressions
16775 * @return `true` if and only if an error code is generated on the passed node 17636 * @return `true` if and only if an error code is generated on the passed node
16776 * @see CompileTimeErrorCode#CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS 17637 * @see CompileTimeErrorCode#CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
16777 */ 17638 */
16778 bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, Type2 ty pe) { 17639 bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, Type2 ty pe) {
16779 if (!implementsEqualsWhenNotAllowed(type)) { 17640 if (!implementsEqualsWhenNotAllowed(type)) {
16780 return false; 17641 return false;
16781 } 17642 }
17643 // report error
16782 _errorReporter.reportError6(CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEM ENTS_EQUALS, node.keyword, [type.displayName]); 17644 _errorReporter.reportError6(CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEM ENTS_EQUALS, node.keyword, [type.displayName]);
16783 return true; 17645 return true;
16784 } 17646 }
16785 17647
16786 /** 17648 /**
16787 * This verifies that the passed method declaration is abstract only if the en closing class is 17649 * This verifies that the passed method declaration is abstract only if the en closing class is
16788 * also abstract. 17650 * also abstract.
16789 * 17651 *
16790 * @param node the method declaration to evaluate 17652 * @param node the method declaration to evaluate
16791 * @return `true` if and only if an error code is generated on the passed node 17653 * @return `true` if and only if an error code is generated on the passed node
(...skipping 17 matching lines...) Expand all
16809 * @see CompileTimeErrorCode#DUPLICATE_CONSTRUCTOR_DEFAULT 17671 * @see CompileTimeErrorCode#DUPLICATE_CONSTRUCTOR_DEFAULT
16810 * @see CompileTimeErrorCode#DUPLICATE_CONSTRUCTOR_NAME 17672 * @see CompileTimeErrorCode#DUPLICATE_CONSTRUCTOR_NAME
16811 * @see CompileTimeErrorCode#CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD 17673 * @see CompileTimeErrorCode#CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD
16812 * @see CompileTimeErrorCode#CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD 17674 * @see CompileTimeErrorCode#CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD
16813 */ 17675 */
16814 bool checkForConflictingConstructorNameAndMember(ConstructorDeclaration node) { 17676 bool checkForConflictingConstructorNameAndMember(ConstructorDeclaration node) {
16815 ConstructorElement constructorElement = node.element; 17677 ConstructorElement constructorElement = node.element;
16816 SimpleIdentifier constructorName = node.name; 17678 SimpleIdentifier constructorName = node.name;
16817 String name = constructorElement.name; 17679 String name = constructorElement.name;
16818 ClassElement classElement = constructorElement.enclosingElement; 17680 ClassElement classElement = constructorElement.enclosingElement;
17681 // constructors
16819 List<ConstructorElement> constructors = classElement.constructors; 17682 List<ConstructorElement> constructors = classElement.constructors;
16820 for (ConstructorElement otherConstructor in constructors) { 17683 for (ConstructorElement otherConstructor in constructors) {
16821 if (identical(otherConstructor, constructorElement)) { 17684 if (identical(otherConstructor, constructorElement)) {
16822 continue; 17685 continue;
16823 } 17686 }
16824 if (name == otherConstructor.name) { 17687 if (name == otherConstructor.name) {
16825 if (name == null || name.length == 0) { 17688 if (name == null || name.length == 0) {
16826 _errorReporter.reportError3(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR _DEFAULT, node, []); 17689 _errorReporter.reportError3(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR _DEFAULT, node, []);
16827 } else { 17690 } else {
16828 _errorReporter.reportError3(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR _NAME, node, [name]); 17691 _errorReporter.reportError3(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR _NAME, node, [name]);
16829 } 17692 }
16830 return true; 17693 return true;
16831 } 17694 }
16832 } 17695 }
17696 // conflict with class member
16833 if (constructorName != null && constructorElement != null && !constructorNam e.isSynthetic) { 17697 if (constructorName != null && constructorElement != null && !constructorNam e.isSynthetic) {
17698 // fields
16834 FieldElement field = classElement.getField(name); 17699 FieldElement field = classElement.getField(name);
16835 if (field != null) { 17700 if (field != null) {
16836 _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR _NAME_AND_FIELD, node, [name]); 17701 _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR _NAME_AND_FIELD, node, [name]);
16837 return true; 17702 return true;
16838 } 17703 }
17704 // methods
16839 MethodElement method = classElement.getMethod(name); 17705 MethodElement method = classElement.getMethod(name);
16840 if (method != null) { 17706 if (method != null) {
16841 _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR _NAME_AND_METHOD, node, [name]); 17707 _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_CONSTRUCTOR _NAME_AND_METHOD, node, [name]);
16842 return true; 17708 return true;
16843 } 17709 }
16844 } 17710 }
16845 return false; 17711 return false;
16846 } 17712 }
16847 17713
16848 /** 17714 /**
16849 * This verifies that the [enclosingClass] does not have method and getter wit h the same 17715 * This verifies that the [enclosingClass] does not have method and getter wit h the same
16850 * names. 17716 * names.
16851 * 17717 *
16852 * @return `true` if and only if an error code is generated on the passed node 17718 * @return `true` if and only if an error code is generated on the passed node
16853 * @see CompileTimeErrorCode#CONFLICTING_GETTER_AND_METHOD 17719 * @see CompileTimeErrorCode#CONFLICTING_GETTER_AND_METHOD
16854 * @see CompileTimeErrorCode#CONFLICTING_METHOD_AND_GETTER 17720 * @see CompileTimeErrorCode#CONFLICTING_METHOD_AND_GETTER
16855 */ 17721 */
16856 bool checkForConflictingGetterAndMethod() { 17722 bool checkForConflictingGetterAndMethod() {
16857 if (_enclosingClass == null) { 17723 if (_enclosingClass == null) {
16858 return false; 17724 return false;
16859 } 17725 }
16860 bool hasProblem = false; 17726 bool hasProblem = false;
17727 // method declared in the enclosing class vs. inherited getter
16861 for (MethodElement method in _enclosingClass.methods) { 17728 for (MethodElement method in _enclosingClass.methods) {
16862 String name = method.name; 17729 String name = method.name;
17730 // find inherited property accessor (and can be only getter)
16863 ExecutableElement inherited = _inheritanceManager.lookupInheritance(_enclo singClass, name); 17731 ExecutableElement inherited = _inheritanceManager.lookupInheritance(_enclo singClass, name);
16864 if (inherited is! PropertyAccessorElement) { 17732 if (inherited is! PropertyAccessorElement) {
16865 continue; 17733 continue;
16866 } 17734 }
17735 // report problem
16867 hasProblem = true; 17736 hasProblem = true;
16868 _errorReporter.reportError5(CompileTimeErrorCode.CONFLICTING_GETTER_AND_ME THOD, method.nameOffset, name.length, [ 17737 _errorReporter.reportError5(CompileTimeErrorCode.CONFLICTING_GETTER_AND_ME THOD, method.nameOffset, name.length, [
16869 _enclosingClass.displayName, 17738 _enclosingClass.displayName,
16870 inherited.enclosingElement.displayName, 17739 inherited.enclosingElement.displayName,
16871 name]); 17740 name]);
16872 } 17741 }
17742 // getter declared in the enclosing class vs. inherited method
16873 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { 17743 for (PropertyAccessorElement accessor in _enclosingClass.accessors) {
16874 if (!accessor.isGetter) { 17744 if (!accessor.isGetter) {
16875 continue; 17745 continue;
16876 } 17746 }
16877 String name = accessor.name; 17747 String name = accessor.name;
17748 // find inherited method
16878 ExecutableElement inherited = _inheritanceManager.lookupInheritance(_enclo singClass, name); 17749 ExecutableElement inherited = _inheritanceManager.lookupInheritance(_enclo singClass, name);
16879 if (inherited is! MethodElement) { 17750 if (inherited is! MethodElement) {
16880 continue; 17751 continue;
16881 } 17752 }
17753 // report problem
16882 hasProblem = true; 17754 hasProblem = true;
16883 _errorReporter.reportError5(CompileTimeErrorCode.CONFLICTING_METHOD_AND_GE TTER, accessor.nameOffset, name.length, [ 17755 _errorReporter.reportError5(CompileTimeErrorCode.CONFLICTING_METHOD_AND_GE TTER, accessor.nameOffset, name.length, [
16884 _enclosingClass.displayName, 17756 _enclosingClass.displayName,
16885 inherited.enclosingElement.displayName, 17757 inherited.enclosingElement.displayName,
16886 name]); 17758 name]);
16887 } 17759 }
17760 // done
16888 return hasProblem; 17761 return hasProblem;
16889 } 17762 }
16890 17763
16891 /** 17764 /**
16892 * This verifies that the superclass of the [enclosingClass] does not declare accessible 17765 * This verifies that the superclass of the [enclosingClass] does not declare accessible
16893 * static members with the same name as the instance getters/setters declared in 17766 * static members with the same name as the instance getters/setters declared in
16894 * [enclosingClass]. 17767 * [enclosingClass].
16895 * 17768 *
16896 * @param node the method declaration to evaluate 17769 * @param node the method declaration to evaluate
16897 * @return `true` if and only if an error code is generated on the passed node 17770 * @return `true` if and only if an error code is generated on the passed node
16898 * @see StaticWarningCode#CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER 17771 * @see StaticWarningCode#CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER
16899 * @see StaticWarningCode#CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER 17772 * @see StaticWarningCode#CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER
16900 */ 17773 */
16901 bool checkForConflictingInstanceGetterAndSuperclassMember() { 17774 bool checkForConflictingInstanceGetterAndSuperclassMember() {
16902 if (_enclosingClass == null) { 17775 if (_enclosingClass == null) {
16903 return false; 17776 return false;
16904 } 17777 }
16905 InterfaceType enclosingType = _enclosingClass.type; 17778 InterfaceType enclosingType = _enclosingClass.type;
17779 // check every accessor
16906 bool hasProblem = false; 17780 bool hasProblem = false;
16907 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { 17781 for (PropertyAccessorElement accessor in _enclosingClass.accessors) {
17782 // we analyze instance accessors here
16908 if (accessor.isStatic) { 17783 if (accessor.isStatic) {
16909 continue; 17784 continue;
16910 } 17785 }
17786 // prepare accessor properties
16911 String name = accessor.displayName; 17787 String name = accessor.displayName;
16912 bool getter = accessor.isGetter; 17788 bool getter = accessor.isGetter;
17789 // if non-final variable, ignore setter - we alreay reported problem for g etter
16913 if (accessor.isSetter && accessor.isSynthetic) { 17790 if (accessor.isSetter && accessor.isSynthetic) {
16914 continue; 17791 continue;
16915 } 17792 }
17793 // try to find super element
16916 ExecutableElement superElement; 17794 ExecutableElement superElement;
16917 superElement = enclosingType.lookUpGetterInSuperclass(name, _currentLibrar y); 17795 superElement = enclosingType.lookUpGetterInSuperclass(name, _currentLibrar y);
16918 if (superElement == null) { 17796 if (superElement == null) {
16919 superElement = enclosingType.lookUpSetterInSuperclass(name, _currentLibr ary); 17797 superElement = enclosingType.lookUpSetterInSuperclass(name, _currentLibr ary);
16920 } 17798 }
16921 if (superElement == null) { 17799 if (superElement == null) {
16922 superElement = enclosingType.lookUpMethodInSuperclass(name, _currentLibr ary); 17800 superElement = enclosingType.lookUpMethodInSuperclass(name, _currentLibr ary);
16923 } 17801 }
16924 if (superElement == null) { 17802 if (superElement == null) {
16925 continue; 17803 continue;
16926 } 17804 }
17805 // OK, not static
16927 if (!superElement.isStatic) { 17806 if (!superElement.isStatic) {
16928 continue; 17807 continue;
16929 } 17808 }
17809 // prepare "super" type to report its name
16930 ClassElement superElementClass = superElement.enclosingElement as ClassEle ment; 17810 ClassElement superElementClass = superElement.enclosingElement as ClassEle ment;
16931 InterfaceType superElementType = superElementClass.type; 17811 InterfaceType superElementType = superElementClass.type;
17812 // report problem
16932 hasProblem = true; 17813 hasProblem = true;
16933 if (getter) { 17814 if (getter) {
16934 _errorReporter.reportError4(StaticWarningCode.CONFLICTING_INSTANCE_GETTE R_AND_SUPERCLASS_MEMBER, accessor, [superElementType.displayName]); 17815 _errorReporter.reportError4(StaticWarningCode.CONFLICTING_INSTANCE_GETTE R_AND_SUPERCLASS_MEMBER, accessor, [superElementType.displayName]);
16935 } else { 17816 } else {
16936 _errorReporter.reportError4(StaticWarningCode.CONFLICTING_INSTANCE_SETTE R_AND_SUPERCLASS_MEMBER, accessor, [superElementType.displayName]); 17817 _errorReporter.reportError4(StaticWarningCode.CONFLICTING_INSTANCE_SETTE R_AND_SUPERCLASS_MEMBER, accessor, [superElementType.displayName]);
16937 } 17818 }
16938 } 17819 }
17820 // done
16939 return hasProblem; 17821 return hasProblem;
16940 } 17822 }
16941 17823
16942 /** 17824 /**
16943 * This verifies that the enclosing class does not have a setter with the same name as the passed 17825 * This verifies that the enclosing class does not have a setter with the same name as the passed
16944 * instance method declaration. 17826 * instance method declaration.
16945 * 17827 *
16946 * @param node the method declaration to evaluate 17828 * @param node the method declaration to evaluate
16947 * @return `true` if and only if an error code is generated on the passed node 17829 * @return `true` if and only if an error code is generated on the passed node
16948 * @see StaticWarningCode#CONFLICTING_INSTANCE_METHOD_SETTER 17830 * @see StaticWarningCode#CONFLICTING_INSTANCE_METHOD_SETTER
16949 */ 17831 */
16950 bool checkForConflictingInstanceMethodSetter(MethodDeclaration node) { 17832 bool checkForConflictingInstanceMethodSetter(MethodDeclaration node) {
16951 if (node.isStatic) { 17833 if (node.isStatic) {
16952 return false; 17834 return false;
16953 } 17835 }
17836 // prepare name
16954 SimpleIdentifier nameNode = node.name; 17837 SimpleIdentifier nameNode = node.name;
16955 if (nameNode == null) { 17838 if (nameNode == null) {
16956 return false; 17839 return false;
16957 } 17840 }
16958 String name = nameNode.name; 17841 String name = nameNode.name;
17842 // ensure that we have enclosing class
16959 if (_enclosingClass == null) { 17843 if (_enclosingClass == null) {
16960 return false; 17844 return false;
16961 } 17845 }
17846 // try to find setter
16962 ExecutableElement setter = _inheritanceManager.lookupMember(_enclosingClass, "${name}="); 17847 ExecutableElement setter = _inheritanceManager.lookupMember(_enclosingClass, "${name}=");
16963 if (setter == null) { 17848 if (setter == null) {
16964 return false; 17849 return false;
16965 } 17850 }
17851 // report problem
16966 _errorReporter.reportError3(StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SE TTER, nameNode, [ 17852 _errorReporter.reportError3(StaticWarningCode.CONFLICTING_INSTANCE_METHOD_SE TTER, nameNode, [
16967 _enclosingClass.displayName, 17853 _enclosingClass.displayName,
16968 name, 17854 name,
16969 setter.enclosingElement.displayName]); 17855 setter.enclosingElement.displayName]);
16970 return true; 17856 return true;
16971 } 17857 }
16972 17858
16973 /** 17859 /**
16974 * This verifies that the enclosing class does not have an instance member wit h the same name as 17860 * This verifies that the enclosing class does not have an instance member wit h the same name as
16975 * the passed static getter method declaration. 17861 * the passed static getter method declaration.
16976 * 17862 *
16977 * @param node the method declaration to evaluate 17863 * @param node the method declaration to evaluate
16978 * @return `true` if and only if an error code is generated on the passed node 17864 * @return `true` if and only if an error code is generated on the passed node
16979 * @see StaticWarningCode#CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER 17865 * @see StaticWarningCode#CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER
16980 */ 17866 */
16981 bool checkForConflictingStaticGetterAndInstanceSetter(MethodDeclaration node) { 17867 bool checkForConflictingStaticGetterAndInstanceSetter(MethodDeclaration node) {
16982 if (!node.isStatic) { 17868 if (!node.isStatic) {
16983 return false; 17869 return false;
16984 } 17870 }
17871 // prepare name
16985 SimpleIdentifier nameNode = node.name; 17872 SimpleIdentifier nameNode = node.name;
16986 if (nameNode == null) { 17873 if (nameNode == null) {
16987 return false; 17874 return false;
16988 } 17875 }
16989 String name = nameNode.name; 17876 String name = nameNode.name;
17877 // prepare enclosing type
16990 if (_enclosingClass == null) { 17878 if (_enclosingClass == null) {
16991 return false; 17879 return false;
16992 } 17880 }
16993 InterfaceType enclosingType = _enclosingClass.type; 17881 InterfaceType enclosingType = _enclosingClass.type;
17882 // try to find setter
16994 ExecutableElement setter = enclosingType.lookUpSetter(name, _currentLibrary) ; 17883 ExecutableElement setter = enclosingType.lookUpSetter(name, _currentLibrary) ;
16995 if (setter == null) { 17884 if (setter == null) {
16996 return false; 17885 return false;
16997 } 17886 }
17887 // OK, also static
16998 if (setter.isStatic) { 17888 if (setter.isStatic) {
16999 return false; 17889 return false;
17000 } 17890 }
17891 // prepare "setter" type to report its name
17001 ClassElement setterClass = setter.enclosingElement as ClassElement; 17892 ClassElement setterClass = setter.enclosingElement as ClassElement;
17002 InterfaceType setterType = setterClass.type; 17893 InterfaceType setterType = setterClass.type;
17894 // report problem
17003 _errorReporter.reportError3(StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_ INSTANCE_SETTER, nameNode, [setterType.displayName]); 17895 _errorReporter.reportError3(StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_ INSTANCE_SETTER, nameNode, [setterType.displayName]);
17004 return true; 17896 return true;
17005 } 17897 }
17006 17898
17007 /** 17899 /**
17008 * This verifies that the enclosing class does not have an instance member wit h the same name as 17900 * This verifies that the enclosing class does not have an instance member wit h the same name as
17009 * the passed static getter method declaration. 17901 * the passed static getter method declaration.
17010 * 17902 *
17011 * @param node the method declaration to evaluate 17903 * @param node the method declaration to evaluate
17012 * @return `true` if and only if an error code is generated on the passed node 17904 * @return `true` if and only if an error code is generated on the passed node
17013 * @see StaticWarningCode#CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER 17905 * @see StaticWarningCode#CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER
17014 */ 17906 */
17015 bool checkForConflictingStaticSetterAndInstanceMember(MethodDeclaration node) { 17907 bool checkForConflictingStaticSetterAndInstanceMember(MethodDeclaration node) {
17016 if (!node.isStatic) { 17908 if (!node.isStatic) {
17017 return false; 17909 return false;
17018 } 17910 }
17911 // prepare name
17019 SimpleIdentifier nameNode = node.name; 17912 SimpleIdentifier nameNode = node.name;
17020 if (nameNode == null) { 17913 if (nameNode == null) {
17021 return false; 17914 return false;
17022 } 17915 }
17023 String name = nameNode.name; 17916 String name = nameNode.name;
17917 // prepare enclosing type
17024 if (_enclosingClass == null) { 17918 if (_enclosingClass == null) {
17025 return false; 17919 return false;
17026 } 17920 }
17027 InterfaceType enclosingType = _enclosingClass.type; 17921 InterfaceType enclosingType = _enclosingClass.type;
17922 // try to find member
17028 ExecutableElement member; 17923 ExecutableElement member;
17029 member = enclosingType.lookUpMethod(name, _currentLibrary); 17924 member = enclosingType.lookUpMethod(name, _currentLibrary);
17030 if (member == null) { 17925 if (member == null) {
17031 member = enclosingType.lookUpGetter(name, _currentLibrary); 17926 member = enclosingType.lookUpGetter(name, _currentLibrary);
17032 } 17927 }
17033 if (member == null) { 17928 if (member == null) {
17034 member = enclosingType.lookUpSetter(name, _currentLibrary); 17929 member = enclosingType.lookUpSetter(name, _currentLibrary);
17035 } 17930 }
17036 if (member == null) { 17931 if (member == null) {
17037 return false; 17932 return false;
17038 } 17933 }
17934 // OK, also static
17039 if (member.isStatic) { 17935 if (member.isStatic) {
17040 return false; 17936 return false;
17041 } 17937 }
17938 // prepare "member" type to report its name
17042 ClassElement memberClass = member.enclosingElement as ClassElement; 17939 ClassElement memberClass = member.enclosingElement as ClassElement;
17043 InterfaceType memberType = memberClass.type; 17940 InterfaceType memberType = memberClass.type;
17941 // report problem
17044 _errorReporter.reportError3(StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_ INSTANCE_MEMBER, nameNode, [memberType.displayName]); 17942 _errorReporter.reportError3(StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_ INSTANCE_MEMBER, nameNode, [memberType.displayName]);
17045 return true; 17943 return true;
17046 } 17944 }
17047 17945
17048 /** 17946 /**
17049 * This verifies all conflicts between type variable and enclosing class. TODO (scheglov) 17947 * This verifies all conflicts between type variable and enclosing class. TODO (scheglov)
17050 * 17948 *
17051 * @param node the class declaration to evaluate 17949 * @param node the class declaration to evaluate
17052 * @return `true` if and only if an error code is generated on the passed node 17950 * @return `true` if and only if an error code is generated on the passed node
17053 * @see CompileTimeErrorCode#CONFLICTING_TYPE_VARIABLE_AND_CLASS 17951 * @see CompileTimeErrorCode#CONFLICTING_TYPE_VARIABLE_AND_CLASS
17054 * @see CompileTimeErrorCode#CONFLICTING_TYPE_VARIABLE_AND_MEMBER 17952 * @see CompileTimeErrorCode#CONFLICTING_TYPE_VARIABLE_AND_MEMBER
17055 */ 17953 */
17056 bool checkForConflictingTypeVariableErrorCodes(ClassDeclaration node) { 17954 bool checkForConflictingTypeVariableErrorCodes(ClassDeclaration node) {
17057 bool problemReported = false; 17955 bool problemReported = false;
17058 for (TypeParameterElement typeParameter in _enclosingClass.typeParameters) { 17956 for (TypeParameterElement typeParameter in _enclosingClass.typeParameters) {
17059 String name = typeParameter.name; 17957 String name = typeParameter.name;
17958 // name is same as the name of the enclosing class
17060 if (_enclosingClass.name == name) { 17959 if (_enclosingClass.name == name) {
17061 _errorReporter.reportError5(CompileTimeErrorCode.CONFLICTING_TYPE_VARIAB LE_AND_CLASS, typeParameter.nameOffset, name.length, [name]); 17960 _errorReporter.reportError5(CompileTimeErrorCode.CONFLICTING_TYPE_VARIAB LE_AND_CLASS, typeParameter.nameOffset, name.length, [name]);
17062 problemReported = true; 17961 problemReported = true;
17063 } 17962 }
17963 // check members
17064 if (_enclosingClass.getMethod(name) != null || _enclosingClass.getGetter(n ame) != null || _enclosingClass.getSetter(name) != null) { 17964 if (_enclosingClass.getMethod(name) != null || _enclosingClass.getGetter(n ame) != null || _enclosingClass.getSetter(name) != null) {
17065 _errorReporter.reportError5(CompileTimeErrorCode.CONFLICTING_TYPE_VARIAB LE_AND_MEMBER, typeParameter.nameOffset, name.length, [name]); 17965 _errorReporter.reportError5(CompileTimeErrorCode.CONFLICTING_TYPE_VARIAB LE_AND_MEMBER, typeParameter.nameOffset, name.length, [name]);
17066 problemReported = true; 17966 problemReported = true;
17067 } 17967 }
17068 } 17968 }
17069 return problemReported; 17969 return problemReported;
17070 } 17970 }
17071 17971
17072 /** 17972 /**
17073 * This verifies that if the passed constructor declaration is 'const' then th ere are no 17973 * This verifies that if the passed constructor declaration is 'const' then th ere are no
17074 * invocations of non-'const' super constructors. 17974 * invocations of non-'const' super constructors.
17075 * 17975 *
17076 * @param node the constructor declaration to evaluate 17976 * @param node the constructor declaration to evaluate
17077 * @return `true` if and only if an error code is generated on the passed node 17977 * @return `true` if and only if an error code is generated on the passed node
17078 * @see CompileTimeErrorCode#CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER 17978 * @see CompileTimeErrorCode#CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER
17079 */ 17979 */
17080 bool checkForConstConstructorWithNonConstSuper(ConstructorDeclaration node) { 17980 bool checkForConstConstructorWithNonConstSuper(ConstructorDeclaration node) {
17081 if (!_isEnclosingConstructorConst) { 17981 if (!_isEnclosingConstructorConst) {
17082 return false; 17982 return false;
17083 } 17983 }
17984 // OK, const factory, checked elsewhere
17084 if (node.factoryKeyword != null) { 17985 if (node.factoryKeyword != null) {
17085 return false; 17986 return false;
17086 } 17987 }
17988 // try to find and check super constructor invocation
17087 for (ConstructorInitializer initializer in node.initializers) { 17989 for (ConstructorInitializer initializer in node.initializers) {
17088 if (initializer is SuperConstructorInvocation) { 17990 if (initializer is SuperConstructorInvocation) {
17089 SuperConstructorInvocation superInvocation = initializer; 17991 SuperConstructorInvocation superInvocation = initializer;
17090 ConstructorElement element = superInvocation.staticElement; 17992 ConstructorElement element = superInvocation.staticElement;
17091 if (element == null || element.isConst) { 17993 if (element == null || element.isConst) {
17092 return false; 17994 return false;
17093 } 17995 }
17094 _errorReporter.reportError3(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_ NON_CONST_SUPER, superInvocation, []); 17996 _errorReporter.reportError3(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_ NON_CONST_SUPER, superInvocation, []);
17095 return true; 17997 return true;
17096 } 17998 }
17097 } 17999 }
18000 // no explicit super constructor invocation, check default constructor
17098 InterfaceType supertype = _enclosingClass.supertype; 18001 InterfaceType supertype = _enclosingClass.supertype;
17099 if (supertype == null) { 18002 if (supertype == null) {
17100 return false; 18003 return false;
17101 } 18004 }
17102 if (supertype.isObject) { 18005 if (supertype.isObject) {
17103 return false; 18006 return false;
17104 } 18007 }
17105 ConstructorElement unnamedConstructor = supertype.element.unnamedConstructor ; 18008 ConstructorElement unnamedConstructor = supertype.element.unnamedConstructor ;
17106 if (unnamedConstructor == null) { 18009 if (unnamedConstructor == null) {
17107 return false; 18010 return false;
17108 } 18011 }
17109 if (unnamedConstructor.isConst) { 18012 if (unnamedConstructor.isConst) {
17110 return false; 18013 return false;
17111 } 18014 }
18015 // default constructor is not 'const', report problem
17112 _errorReporter.reportError3(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_ CONST_SUPER, node, []); 18016 _errorReporter.reportError3(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_ CONST_SUPER, node, []);
17113 return true; 18017 return true;
17114 } 18018 }
17115 18019
17116 /** 18020 /**
17117 * This verifies that if the passed constructor declaration is 'const' then th ere are no non-final 18021 * This verifies that if the passed constructor declaration is 'const' then th ere are no non-final
17118 * instance variable. 18022 * instance variable.
17119 * 18023 *
17120 * @param node the constructor declaration to evaluate 18024 * @param node the constructor declaration to evaluate
17121 * @return `true` if and only if an error code is generated on the passed node 18025 * @return `true` if and only if an error code is generated on the passed node
17122 * @see CompileTimeErrorCode#CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD 18026 * @see CompileTimeErrorCode#CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
17123 */ 18027 */
17124 bool checkForConstConstructorWithNonFinalField(ConstructorDeclaration node) { 18028 bool checkForConstConstructorWithNonFinalField(ConstructorDeclaration node) {
17125 if (!_isEnclosingConstructorConst) { 18029 if (!_isEnclosingConstructorConst) {
17126 return false; 18030 return false;
17127 } 18031 }
18032 // check if there is non-final field
17128 ConstructorElement constructorElement = node.element; 18033 ConstructorElement constructorElement = node.element;
17129 ClassElement classElement = constructorElement.enclosingElement; 18034 ClassElement classElement = constructorElement.enclosingElement;
17130 if (!classElement.hasNonFinalField()) { 18035 if (!classElement.hasNonFinalField()) {
17131 return false; 18036 return false;
17132 } 18037 }
18038 // report problem
17133 _errorReporter.reportError3(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_ FINAL_FIELD, node, []); 18039 _errorReporter.reportError3(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_ FINAL_FIELD, node, []);
17134 return true; 18040 return true;
17135 } 18041 }
17136 18042
17137 /** 18043 /**
17138 * This verifies that the passed throw expression is not enclosed in a 'const' constructor 18044 * This verifies that the passed throw expression is not enclosed in a 'const' constructor
17139 * declaration. 18045 * declaration.
17140 * 18046 *
17141 * @param node the throw expression expression to evaluate 18047 * @param node the throw expression expression to evaluate
17142 * @return `true` if and only if an error code is generated on the passed node 18048 * @return `true` if and only if an error code is generated on the passed node
(...skipping 28 matching lines...) Expand all
17171 * 18077 *
17172 * @param key the expression to evaluate 18078 * @param key the expression to evaluate
17173 * @return `true` if and only if an error code is generated on the passed node 18079 * @return `true` if and only if an error code is generated on the passed node
17174 * @see CompileTimeErrorCode#CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS 18080 * @see CompileTimeErrorCode#CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
17175 */ 18081 */
17176 bool checkForConstMapKeyExpressionTypeImplementsEquals(Expression key) { 18082 bool checkForConstMapKeyExpressionTypeImplementsEquals(Expression key) {
17177 Type2 type = key.staticType; 18083 Type2 type = key.staticType;
17178 if (!implementsEqualsWhenNotAllowed(type)) { 18084 if (!implementsEqualsWhenNotAllowed(type)) {
17179 return false; 18085 return false;
17180 } 18086 }
18087 // report error
17181 _errorReporter.reportError3(CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TY PE_IMPLEMENTS_EQUALS, key, [type.displayName]); 18088 _errorReporter.reportError3(CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TY PE_IMPLEMENTS_EQUALS, key, [type.displayName]);
17182 return true; 18089 return true;
17183 } 18090 }
17184 18091
17185 /** 18092 /**
17186 * This verifies that the all keys of the passed map literal have class type t hat does not declare 18093 * This verifies that the all keys of the passed map literal have class type t hat does not declare
17187 * operator <i>==<i>. 18094 * operator <i>==<i>.
17188 * 18095 *
17189 * @param key the map literal to evaluate 18096 * @param key the map literal to evaluate
17190 * @return `true` if and only if an error code is generated on the passed node 18097 * @return `true` if and only if an error code is generated on the passed node
17191 * @see CompileTimeErrorCode#CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS 18098 * @see CompileTimeErrorCode#CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
17192 */ 18099 */
17193 bool checkForConstMapKeyExpressionTypeImplementsEquals2(MapLiteral node) { 18100 bool checkForConstMapKeyExpressionTypeImplementsEquals2(MapLiteral node) {
18101 // OK, not const.
17194 if (node.constKeyword == null) { 18102 if (node.constKeyword == null) {
17195 return false; 18103 return false;
17196 } 18104 }
18105 // Check every map entry.
17197 bool hasProblems = false; 18106 bool hasProblems = false;
17198 for (MapLiteralEntry entry in node.entries) { 18107 for (MapLiteralEntry entry in node.entries) {
17199 Expression key = entry.key; 18108 Expression key = entry.key;
17200 hasProblems = javaBooleanOr(hasProblems, checkForConstMapKeyExpressionType ImplementsEquals(key)); 18109 hasProblems = javaBooleanOr(hasProblems, checkForConstMapKeyExpressionType ImplementsEquals(key));
17201 } 18110 }
17202 return hasProblems; 18111 return hasProblems;
17203 } 18112 }
17204 18113
17205 /** 18114 /**
17206 * This verifies that the passed instance creation expression is not being inv oked on an abstract 18115 * This verifies that the passed instance creation expression is not being inv oked on an abstract
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
17268 } 18177 }
17269 18178
17270 /** 18179 /**
17271 * This verifies that the passed type name does not reference any type paramet ers. 18180 * This verifies that the passed type name does not reference any type paramet ers.
17272 * 18181 *
17273 * @param typeName the type name to evaluate 18182 * @param typeName the type name to evaluate
17274 * @return `true` if and only if an error code is generated on the passed node 18183 * @return `true` if and only if an error code is generated on the passed node
17275 * @see CompileTimeErrorCode#CONST_WITH_TYPE_PARAMETERS 18184 * @see CompileTimeErrorCode#CONST_WITH_TYPE_PARAMETERS
17276 */ 18185 */
17277 bool checkForConstWithTypeParameters2(TypeName typeName) { 18186 bool checkForConstWithTypeParameters2(TypeName typeName) {
18187 // something wrong with AST
17278 if (typeName == null) { 18188 if (typeName == null) {
17279 return false; 18189 return false;
17280 } 18190 }
17281 Identifier name = typeName.name; 18191 Identifier name = typeName.name;
17282 if (name == null) { 18192 if (name == null) {
17283 return false; 18193 return false;
17284 } 18194 }
18195 // should not be a type parameter
17285 if (name.staticElement is TypeParameterElement) { 18196 if (name.staticElement is TypeParameterElement) {
17286 _errorReporter.reportError3(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETER S, name, []); 18197 _errorReporter.reportError3(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETER S, name, []);
17287 } 18198 }
18199 // check type arguments
17288 TypeArgumentList typeArguments = typeName.typeArguments; 18200 TypeArgumentList typeArguments = typeName.typeArguments;
17289 if (typeArguments != null) { 18201 if (typeArguments != null) {
17290 bool hasError = false; 18202 bool hasError = false;
17291 for (TypeName argument in typeArguments.arguments) { 18203 for (TypeName argument in typeArguments.arguments) {
17292 hasError = javaBooleanOr(hasError, checkForConstWithTypeParameters2(argu ment)); 18204 hasError = javaBooleanOr(hasError, checkForConstWithTypeParameters2(argu ment));
17293 } 18205 }
17294 return hasError; 18206 return hasError;
17295 } 18207 }
18208 // OK
17296 return false; 18209 return false;
17297 } 18210 }
17298 18211
17299 /** 18212 /**
17300 * This verifies that if the passed 'const' instance creation expression is be ing invoked on the 18213 * This verifies that if the passed 'const' instance creation expression is be ing invoked on the
17301 * resolved constructor. 18214 * resolved constructor.
17302 * 18215 *
17303 * This method assumes that the instance creation was tested to be 'const' bef ore being called. 18216 * This method assumes that the instance creation was tested to be 'const' bef ore being called.
17304 * 18217 *
17305 * @param node the instance creation expression to evaluate 18218 * @param node the instance creation expression to evaluate
17306 * @return `true` if and only if an error code is generated on the passed node 18219 * @return `true` if and only if an error code is generated on the passed node
17307 * @see CompileTimeErrorCode#CONST_WITH_UNDEFINED_CONSTRUCTOR 18220 * @see CompileTimeErrorCode#CONST_WITH_UNDEFINED_CONSTRUCTOR
17308 * @see CompileTimeErrorCode#CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT 18221 * @see CompileTimeErrorCode#CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
17309 */ 18222 */
17310 bool checkForConstWithUndefinedConstructor(InstanceCreationExpression node) { 18223 bool checkForConstWithUndefinedConstructor(InstanceCreationExpression node) {
18224 // OK if resolved
17311 if (node.staticElement != null) { 18225 if (node.staticElement != null) {
17312 return false; 18226 return false;
17313 } 18227 }
18228 // prepare constructor name
17314 ConstructorName constructorName = node.constructorName; 18229 ConstructorName constructorName = node.constructorName;
17315 if (constructorName == null) { 18230 if (constructorName == null) {
17316 return false; 18231 return false;
17317 } 18232 }
18233 // prepare class name
17318 TypeName type = constructorName.type; 18234 TypeName type = constructorName.type;
17319 if (type == null) { 18235 if (type == null) {
17320 return false; 18236 return false;
17321 } 18237 }
17322 Identifier className = type.name; 18238 Identifier className = type.name;
18239 // report as named or default constructor absence
17323 SimpleIdentifier name = constructorName.name; 18240 SimpleIdentifier name = constructorName.name;
17324 if (name != null) { 18241 if (name != null) {
17325 _errorReporter.reportError3(CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONS TRUCTOR, name, [className, name]); 18242 _errorReporter.reportError3(CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONS TRUCTOR, name, [className, name]);
17326 } else { 18243 } else {
17327 _errorReporter.reportError3(CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONS TRUCTOR_DEFAULT, constructorName, [className]); 18244 _errorReporter.reportError3(CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONS TRUCTOR_DEFAULT, constructorName, [className]);
17328 } 18245 }
17329 return true; 18246 return true;
17330 } 18247 }
17331 18248
17332 /** 18249 /**
(...skipping 21 matching lines...) Expand all
17354 18271
17355 /** 18272 /**
17356 * This verifies that the given default formal parameter is not part of a func tion typed 18273 * This verifies that the given default formal parameter is not part of a func tion typed
17357 * parameter. 18274 * parameter.
17358 * 18275 *
17359 * @param node the default formal parameter to evaluate 18276 * @param node the default formal parameter to evaluate
17360 * @return `true` if and only if an error code is generated on the passed node 18277 * @return `true` if and only if an error code is generated on the passed node
17361 * @see CompileTimeErrorCode#DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER 18278 * @see CompileTimeErrorCode#DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER
17362 */ 18279 */
17363 bool checkForDefaultValueInFunctionTypedParameter(DefaultFormalParameter node) { 18280 bool checkForDefaultValueInFunctionTypedParameter(DefaultFormalParameter node) {
18281 // OK, not in a function typed parameter.
17364 if (!_isInFunctionTypedFormalParameter) { 18282 if (!_isInFunctionTypedFormalParameter) {
17365 return false; 18283 return false;
17366 } 18284 }
18285 // OK, no default value.
17367 if (node.defaultValue == null) { 18286 if (node.defaultValue == null) {
17368 return false; 18287 return false;
17369 } 18288 }
18289 // Report problem.
17370 _errorReporter.reportError3(CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_T YPED_PARAMETER, node, []); 18290 _errorReporter.reportError3(CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_T YPED_PARAMETER, node, []);
17371 return true; 18291 return true;
17372 } 18292 }
17373 18293
17374 /** 18294 /**
17375 * This verifies that the enclosing class does not have an instance member wit h the given name of 18295 * This verifies that the enclosing class does not have an instance member wit h the given name of
17376 * the static member. 18296 * the static member.
17377 * 18297 *
17378 * @return `true` if and only if an error code is generated on the passed node 18298 * @return `true` if and only if an error code is generated on the passed node
17379 * @see CompileTimeErrorCode#DUPLICATE_DEFINITION_INHERITANCE 18299 * @see CompileTimeErrorCode#DUPLICATE_DEFINITION_INHERITANCE
(...skipping 20 matching lines...) Expand all
17400 18320
17401 /** 18321 /**
17402 * This verifies that the enclosing class does not have an instance member wit h the given name of 18322 * This verifies that the enclosing class does not have an instance member wit h the given name of
17403 * the static member. 18323 * the static member.
17404 * 18324 *
17405 * @param staticMember the static member to check conflict for 18325 * @param staticMember the static member to check conflict for
17406 * @return `true` if and only if an error code is generated on the passed node 18326 * @return `true` if and only if an error code is generated on the passed node
17407 * @see CompileTimeErrorCode#DUPLICATE_DEFINITION_INHERITANCE 18327 * @see CompileTimeErrorCode#DUPLICATE_DEFINITION_INHERITANCE
17408 */ 18328 */
17409 bool checkForDuplicateDefinitionInheritance2(ExecutableElement staticMember) { 18329 bool checkForDuplicateDefinitionInheritance2(ExecutableElement staticMember) {
18330 // prepare name
17410 String name = staticMember.name; 18331 String name = staticMember.name;
17411 if (name == null) { 18332 if (name == null) {
17412 return false; 18333 return false;
17413 } 18334 }
18335 // try to find member
17414 ExecutableElement inheritedMember = _inheritanceManager.lookupInheritance(_e nclosingClass, name); 18336 ExecutableElement inheritedMember = _inheritanceManager.lookupInheritance(_e nclosingClass, name);
17415 if (inheritedMember == null) { 18337 if (inheritedMember == null) {
17416 return false; 18338 return false;
17417 } 18339 }
18340 // OK, also static
17418 if (inheritedMember.isStatic) { 18341 if (inheritedMember.isStatic) {
17419 return false; 18342 return false;
17420 } 18343 }
18344 // report problem
17421 _errorReporter.reportError5(CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERI TANCE, staticMember.nameOffset, name.length, [name, inheritedMember.enclosingEle ment.displayName]); 18345 _errorReporter.reportError5(CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERI TANCE, staticMember.nameOffset, name.length, [name, inheritedMember.enclosingEle ment.displayName]);
17422 return true; 18346 return true;
17423 } 18347 }
17424 18348
17425 /** 18349 /**
17426 * This verifies if the passed list literal has type arguments then there is e xactly one. 18350 * This verifies if the passed list literal has type arguments then there is e xactly one.
17427 * 18351 *
17428 * @param node the list literal to evaluate 18352 * @param node the list literal to evaluate
17429 * @return `true` if and only if an error code is generated on the passed node 18353 * @return `true` if and only if an error code is generated on the passed node
17430 * @see StaticTypeWarningCode#EXPECTED_ONE_LIST_TYPE_ARGUMENTS 18354 * @see StaticTypeWarningCode#EXPECTED_ONE_LIST_TYPE_ARGUMENTS
17431 */ 18355 */
17432 bool checkForExpectedOneListTypeArgument(ListLiteral node) { 18356 bool checkForExpectedOneListTypeArgument(ListLiteral node) {
18357 // prepare type arguments
17433 TypeArgumentList typeArguments = node.typeArguments; 18358 TypeArgumentList typeArguments = node.typeArguments;
17434 if (typeArguments == null) { 18359 if (typeArguments == null) {
17435 return false; 18360 return false;
17436 } 18361 }
18362 // check number of type arguments
17437 int num = typeArguments.arguments.length; 18363 int num = typeArguments.arguments.length;
17438 if (num == 1) { 18364 if (num == 1) {
17439 return false; 18365 return false;
17440 } 18366 }
18367 // report problem
17441 _errorReporter.reportError3(StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARG UMENTS, typeArguments, [num]); 18368 _errorReporter.reportError3(StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARG UMENTS, typeArguments, [num]);
17442 return true; 18369 return true;
17443 } 18370 }
17444 18371
17445 /** 18372 /**
17446 * This verifies the passed import has unique name among other exported librar ies. 18373 * This verifies the passed import has unique name among other exported librar ies.
17447 * 18374 *
17448 * @param node the export directive to evaluate 18375 * @param node the export directive to evaluate
17449 * @return `true` if and only if an error code is generated on the passed node 18376 * @return `true` if and only if an error code is generated on the passed node
17450 * @see CompileTimeErrorCode#EXPORT_DUPLICATED_LIBRARY_NAME 18377 * @see CompileTimeErrorCode#EXPORT_DUPLICATED_LIBRARY_NAME
17451 */ 18378 */
17452 bool checkForExportDuplicateLibraryName(ExportDirective node) { 18379 bool checkForExportDuplicateLibraryName(ExportDirective node) {
18380 // prepare import element
17453 Element nodeElement = node.element; 18381 Element nodeElement = node.element;
17454 if (nodeElement is! ExportElement) { 18382 if (nodeElement is! ExportElement) {
17455 return false; 18383 return false;
17456 } 18384 }
17457 ExportElement nodeExportElement = nodeElement as ExportElement; 18385 ExportElement nodeExportElement = nodeElement as ExportElement;
18386 // prepare exported library
17458 LibraryElement nodeLibrary = nodeExportElement.exportedLibrary; 18387 LibraryElement nodeLibrary = nodeExportElement.exportedLibrary;
17459 if (nodeLibrary == null) { 18388 if (nodeLibrary == null) {
17460 return false; 18389 return false;
17461 } 18390 }
17462 String name = nodeLibrary.name; 18391 String name = nodeLibrary.name;
18392 // check if there is other exported library with the same name
17463 LibraryElement prevLibrary = _nameToExportElement[name]; 18393 LibraryElement prevLibrary = _nameToExportElement[name];
17464 if (prevLibrary != null) { 18394 if (prevLibrary != null) {
17465 if (prevLibrary != nodeLibrary) { 18395 if (prevLibrary != nodeLibrary) {
17466 _errorReporter.reportError3(StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_ NAME, node, [ 18396 _errorReporter.reportError3(StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_ NAME, node, [
17467 prevLibrary.definingCompilationUnit.displayName, 18397 prevLibrary.definingCompilationUnit.displayName,
17468 nodeLibrary.definingCompilationUnit.displayName, 18398 nodeLibrary.definingCompilationUnit.displayName,
17469 name]); 18399 name]);
17470 return true; 18400 return true;
17471 } 18401 }
17472 } else { 18402 } else {
17473 _nameToExportElement[name] = nodeLibrary; 18403 _nameToExportElement[name] = nodeLibrary;
17474 } 18404 }
18405 // OK
17475 return false; 18406 return false;
17476 } 18407 }
17477 18408
17478 /** 18409 /**
17479 * Check that if the visiting library is not system, then any passed library s hould not be SDK 18410 * Check that if the visiting library is not system, then any passed library s hould not be SDK
17480 * internal library. 18411 * internal library.
17481 * 18412 *
17482 * @param node the export directive to evaluate 18413 * @param node the export directive to evaluate
17483 * @return `true` if and only if an error code is generated on the passed node 18414 * @return `true` if and only if an error code is generated on the passed node
17484 * @see CompileTimeErrorCode#EXPORT_INTERNAL_LIBRARY 18415 * @see CompileTimeErrorCode#EXPORT_INTERNAL_LIBRARY
17485 */ 18416 */
17486 bool checkForExportInternalLibrary(ExportDirective node) { 18417 bool checkForExportInternalLibrary(ExportDirective node) {
17487 if (_isInSystemLibrary) { 18418 if (_isInSystemLibrary) {
17488 return false; 18419 return false;
17489 } 18420 }
18421 // prepare export element
17490 Element element = node.element; 18422 Element element = node.element;
17491 if (element is! ExportElement) { 18423 if (element is! ExportElement) {
17492 return false; 18424 return false;
17493 } 18425 }
17494 ExportElement exportElement = element as ExportElement; 18426 ExportElement exportElement = element as ExportElement;
18427 // should be private
17495 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk; 18428 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk;
17496 String uri = exportElement.uri; 18429 String uri = exportElement.uri;
17497 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri); 18430 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri);
17498 if (sdkLibrary == null) { 18431 if (sdkLibrary == null) {
17499 return false; 18432 return false;
17500 } 18433 }
17501 if (!sdkLibrary.isInternal) { 18434 if (!sdkLibrary.isInternal) {
17502 return false; 18435 return false;
17503 } 18436 }
18437 // report problem
17504 _errorReporter.reportError3(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, no de, [node.uri]); 18438 _errorReporter.reportError3(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, no de, [node.uri]);
17505 return true; 18439 return true;
17506 } 18440 }
17507 18441
17508 /** 18442 /**
17509 * This verifies that the passed extends clause does not extend classes such a s num or String. 18443 * This verifies that the passed extends clause does not extend classes such a s num or String.
17510 * 18444 *
17511 * @param node the extends clause to test 18445 * @param node the extends clause to test
17512 * @return `true` if and only if an error code is generated on the passed node 18446 * @return `true` if and only if an error code is generated on the passed node
17513 * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS 18447 * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
(...skipping 16 matching lines...) Expand all
17530 * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS 18464 * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
17531 * @see CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS 18465 * @see CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS
17532 */ 18466 */
17533 bool checkForExtendsOrImplementsDisallowedClass(TypeName typeName, ErrorCode e rrorCode) { 18467 bool checkForExtendsOrImplementsDisallowedClass(TypeName typeName, ErrorCode e rrorCode) {
17534 if (typeName.isSynthetic) { 18468 if (typeName.isSynthetic) {
17535 return false; 18469 return false;
17536 } 18470 }
17537 Type2 superType = typeName.type; 18471 Type2 superType = typeName.type;
17538 for (InterfaceType disallowedType in _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMEN T) { 18472 for (InterfaceType disallowedType in _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMEN T) {
17539 if (superType != null && superType == disallowedType) { 18473 if (superType != null && superType == disallowedType) {
18474 // if the violating type happens to be 'num', we need to rule out the ca se where the
18475 // enclosing class is 'int' or 'double'
17540 if (superType == _typeProvider.numType) { 18476 if (superType == _typeProvider.numType) {
17541 ASTNode grandParent = typeName.parent.parent; 18477 ASTNode grandParent = typeName.parent.parent;
18478 // Note: this is a corner case that won't happen often, so adding a fi eld currentClass
18479 // (see currentFunction) to ErrorVerifier isn't worth if for this case , but if the field
18480 // currentClass is added, then this message should become a todo to no t lookup the
18481 // grandparent node
17542 if (grandParent is ClassDeclaration) { 18482 if (grandParent is ClassDeclaration) {
17543 ClassElement classElement = grandParent.element; 18483 ClassElement classElement = grandParent.element;
17544 Type2 classType = classElement.type; 18484 Type2 classType = classElement.type;
17545 if (classType != null && (classType == _typeProvider.intType || clas sType == _typeProvider.doubleType)) { 18485 if (classType != null && (classType == _typeProvider.intType || clas sType == _typeProvider.doubleType)) {
17546 return false; 18486 return false;
17547 } 18487 }
17548 } 18488 }
17549 } 18489 }
18490 // otherwise, report the error
17550 _errorReporter.reportError3(errorCode, typeName, [disallowedType.display Name]); 18491 _errorReporter.reportError3(errorCode, typeName, [disallowedType.display Name]);
17551 return true; 18492 return true;
17552 } 18493 }
17553 } 18494 }
17554 return false; 18495 return false;
17555 } 18496 }
17556 18497
17557 /** 18498 /**
17558 * This verifies that the passed constructor field initializer has compatible field and 18499 * This verifies that the passed constructor field initializer has compatible field and
17559 * initializer expression types. 18500 * initializer expression types.
17560 * 18501 *
17561 * @param node the constructor field initializer to test 18502 * @param node the constructor field initializer to test
17562 * @return `true` if and only if an error code is generated on the passed node 18503 * @return `true` if and only if an error code is generated on the passed node
17563 * @see CompileTimeErrorCode#CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE 18504 * @see CompileTimeErrorCode#CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE
17564 * @see StaticWarningCode#FIELD_INITIALIZER_NOT_ASSIGNABLE 18505 * @see StaticWarningCode#FIELD_INITIALIZER_NOT_ASSIGNABLE
17565 */ 18506 */
17566 bool checkForFieldInitializerNotAssignable(ConstructorFieldInitializer node) { 18507 bool checkForFieldInitializerNotAssignable(ConstructorFieldInitializer node) {
18508 // prepare field element
17567 Element fieldNameElement = node.fieldName.staticElement; 18509 Element fieldNameElement = node.fieldName.staticElement;
17568 if (fieldNameElement is! FieldElement) { 18510 if (fieldNameElement is! FieldElement) {
17569 return false; 18511 return false;
17570 } 18512 }
17571 FieldElement fieldElement = fieldNameElement as FieldElement; 18513 FieldElement fieldElement = fieldNameElement as FieldElement;
18514 // prepare field type
17572 Type2 fieldType = fieldElement.type; 18515 Type2 fieldType = fieldElement.type;
18516 // prepare expression type
17573 Expression expression = node.expression; 18517 Expression expression = node.expression;
17574 if (expression == null) { 18518 if (expression == null) {
17575 return false; 18519 return false;
17576 } 18520 }
18521 // test the static type of the expression
17577 Type2 staticType = getStaticType(expression); 18522 Type2 staticType = getStaticType(expression);
17578 if (staticType == null) { 18523 if (staticType == null) {
17579 return false; 18524 return false;
17580 } 18525 }
17581 if (staticType.isAssignableTo(fieldType)) { 18526 if (staticType.isAssignableTo(fieldType)) {
17582 return false; 18527 return false;
17583 } 18528 }
18529 // report problem
17584 if (_isEnclosingConstructorConst) { 18530 if (_isEnclosingConstructorConst) {
17585 _errorReporter.reportError3(CompileTimeErrorCode.CONST_FIELD_INITIALIZER_N OT_ASSIGNABLE, expression, [staticType.displayName, fieldType.displayName]); 18531 _errorReporter.reportError3(CompileTimeErrorCode.CONST_FIELD_INITIALIZER_N OT_ASSIGNABLE, expression, [staticType.displayName, fieldType.displayName]);
17586 } else { 18532 } else {
17587 _errorReporter.reportError3(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGN ABLE, expression, [staticType.displayName, fieldType.displayName]); 18533 _errorReporter.reportError3(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGN ABLE, expression, [staticType.displayName, fieldType.displayName]);
17588 } 18534 }
17589 return true; 18535 return true;
17590 } 18536 }
17591 18537
17592 /** 18538 /**
17593 * This verifies that the passed field formal parameter is in a constructor de claration. 18539 * This verifies that the passed field formal parameter is in a constructor de claration.
17594 * 18540 *
17595 * @param node the field formal parameter to test 18541 * @param node the field formal parameter to test
17596 * @return `true` if and only if an error code is generated on the passed node 18542 * @return `true` if and only if an error code is generated on the passed node
17597 * @see CompileTimeErrorCode#FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR 18543 * @see CompileTimeErrorCode#FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
17598 */ 18544 */
17599 bool checkForFieldInitializingFormalRedirectingConstructor(FieldFormalParamete r node) { 18545 bool checkForFieldInitializingFormalRedirectingConstructor(FieldFormalParamete r node) {
17600 ConstructorDeclaration constructor = node.getAncestor(ConstructorDeclaration ); 18546 ConstructorDeclaration constructor = node.getAncestor(ConstructorDeclaration );
17601 if (constructor == null) { 18547 if (constructor == null) {
17602 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE _CONSTRUCTOR, node, []); 18548 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE _CONSTRUCTOR, node, []);
17603 return true; 18549 return true;
17604 } 18550 }
18551 // constructor cannot be a factory
17605 if (constructor.factoryKeyword != null) { 18552 if (constructor.factoryKeyword != null) {
17606 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY _CONSTRUCTOR, node, []); 18553 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY _CONSTRUCTOR, node, []);
17607 return true; 18554 return true;
17608 } 18555 }
18556 // constructor cannot have a redirection
17609 for (ConstructorInitializer initializer in constructor.initializers) { 18557 for (ConstructorInitializer initializer in constructor.initializers) {
17610 if (initializer is RedirectingConstructorInvocation) { 18558 if (initializer is RedirectingConstructorInvocation) {
17611 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZER_REDIR ECTING_CONSTRUCTOR, node, []); 18559 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZER_REDIR ECTING_CONSTRUCTOR, node, []);
17612 return true; 18560 return true;
17613 } 18561 }
17614 } 18562 }
18563 // OK
17615 return false; 18564 return false;
17616 } 18565 }
17617 18566
17618 /** 18567 /**
17619 * This verifies that final fields that are declared, without any constructors in the enclosing 18568 * This verifies that final fields that are declared, without any constructors in the enclosing
17620 * class, are initialized. Cases in which there is at least one constructor ar e handled at the end 18569 * class, are initialized. Cases in which there is at least one constructor ar e handled at the end
17621 * of [checkForAllFinalInitializedErrorCodes]. 18570 * of [checkForAllFinalInitializedErrorCodes].
17622 * 18571 *
17623 * @param node the class declaration to test 18572 * @param node the class declaration to test
17624 * @return `true` if and only if an error code is generated on the passed node 18573 * @return `true` if and only if an error code is generated on the passed node
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
17700 * 18649 *
17701 * @param node the simple identifier to test 18650 * @param node the simple identifier to test
17702 * @return `true` if and only if an error code is generated on the passed node 18651 * @return `true` if and only if an error code is generated on the passed node
17703 * @see CompileTimeErrorCode#IMPLICIT_THIS_REFERENCE_IN_INITIALIZER 18652 * @see CompileTimeErrorCode#IMPLICIT_THIS_REFERENCE_IN_INITIALIZER
17704 * @see CompileTimeErrorCode#INSTANCE_MEMBER_ACCESS_FROM_STATIC TODO(scheglov) rename thid method 18653 * @see CompileTimeErrorCode#INSTANCE_MEMBER_ACCESS_FROM_STATIC TODO(scheglov) rename thid method
17705 */ 18654 */
17706 bool checkForImplicitThisReferenceInInitializer(SimpleIdentifier node) { 18655 bool checkForImplicitThisReferenceInInitializer(SimpleIdentifier node) {
17707 if (!_isInConstructorInitializer && !_isInStaticMethod && !_isInInstanceVari ableInitializer && !_isInStaticVariableDeclaration) { 18656 if (!_isInConstructorInitializer && !_isInStaticMethod && !_isInInstanceVari ableInitializer && !_isInStaticVariableDeclaration) {
17708 return false; 18657 return false;
17709 } 18658 }
18659 // prepare element
17710 Element element = node.staticElement; 18660 Element element = node.staticElement;
17711 if (!(element is MethodElement || element is PropertyAccessorElement)) { 18661 if (!(element is MethodElement || element is PropertyAccessorElement)) {
17712 return false; 18662 return false;
17713 } 18663 }
18664 // static element
17714 ExecutableElement executableElement = element as ExecutableElement; 18665 ExecutableElement executableElement = element as ExecutableElement;
17715 if (executableElement.isStatic) { 18666 if (executableElement.isStatic) {
17716 return false; 18667 return false;
17717 } 18668 }
18669 // not a class member
17718 Element enclosingElement = element.enclosingElement; 18670 Element enclosingElement = element.enclosingElement;
17719 if (enclosingElement is! ClassElement) { 18671 if (enclosingElement is! ClassElement) {
17720 return false; 18672 return false;
17721 } 18673 }
18674 // comment
17722 ASTNode parent = node.parent; 18675 ASTNode parent = node.parent;
17723 if (parent is CommentReference) { 18676 if (parent is CommentReference) {
17724 return false; 18677 return false;
17725 } 18678 }
18679 // qualified method invocation
17726 if (parent is MethodInvocation) { 18680 if (parent is MethodInvocation) {
17727 MethodInvocation invocation = parent; 18681 MethodInvocation invocation = parent;
17728 if (identical(invocation.methodName, node) && invocation.realTarget != nul l) { 18682 if (identical(invocation.methodName, node) && invocation.realTarget != nul l) {
17729 return false; 18683 return false;
17730 } 18684 }
17731 } 18685 }
18686 // qualified property access
17732 if (parent is PropertyAccess) { 18687 if (parent is PropertyAccess) {
17733 PropertyAccess access = parent; 18688 PropertyAccess access = parent;
17734 if (identical(access.propertyName, node) && access.realTarget != null) { 18689 if (identical(access.propertyName, node) && access.realTarget != null) {
17735 return false; 18690 return false;
17736 } 18691 }
17737 } 18692 }
17738 if (parent is PrefixedIdentifier) { 18693 if (parent is PrefixedIdentifier) {
17739 PrefixedIdentifier prefixed = parent; 18694 PrefixedIdentifier prefixed = parent;
17740 if (identical(prefixed.identifier, node)) { 18695 if (identical(prefixed.identifier, node)) {
17741 return false; 18696 return false;
17742 } 18697 }
17743 } 18698 }
18699 // report problem
17744 if (_isInStaticMethod) { 18700 if (_isInStaticMethod) {
17745 _errorReporter.reportError3(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FR OM_STATIC, node, []); 18701 _errorReporter.reportError3(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FR OM_STATIC, node, []);
17746 } else { 18702 } else {
17747 _errorReporter.reportError3(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_I N_INITIALIZER, node, []); 18703 _errorReporter.reportError3(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_I N_INITIALIZER, node, []);
17748 } 18704 }
17749 return true; 18705 return true;
17750 } 18706 }
17751 18707
17752 /** 18708 /**
17753 * This verifies the passed import has unique name among other imported librar ies. 18709 * This verifies the passed import has unique name among other imported librar ies.
17754 * 18710 *
17755 * @param node the import directive to evaluate 18711 * @param node the import directive to evaluate
17756 * @return `true` if and only if an error code is generated on the passed node 18712 * @return `true` if and only if an error code is generated on the passed node
17757 * @see CompileTimeErrorCode#IMPORT_DUPLICATED_LIBRARY_NAME 18713 * @see CompileTimeErrorCode#IMPORT_DUPLICATED_LIBRARY_NAME
17758 */ 18714 */
17759 bool checkForImportDuplicateLibraryName(ImportDirective node) { 18715 bool checkForImportDuplicateLibraryName(ImportDirective node) {
18716 // prepare import element
17760 ImportElement nodeImportElement = node.element; 18717 ImportElement nodeImportElement = node.element;
17761 if (nodeImportElement == null) { 18718 if (nodeImportElement == null) {
17762 return false; 18719 return false;
17763 } 18720 }
18721 // prepare imported library
17764 LibraryElement nodeLibrary = nodeImportElement.importedLibrary; 18722 LibraryElement nodeLibrary = nodeImportElement.importedLibrary;
17765 if (nodeLibrary == null) { 18723 if (nodeLibrary == null) {
17766 return false; 18724 return false;
17767 } 18725 }
17768 String name = nodeLibrary.name; 18726 String name = nodeLibrary.name;
18727 // check if there is other imported library with the same name
17769 LibraryElement prevLibrary = _nameToImportElement[name]; 18728 LibraryElement prevLibrary = _nameToImportElement[name];
17770 if (prevLibrary != null) { 18729 if (prevLibrary != null) {
17771 if (prevLibrary != nodeLibrary) { 18730 if (prevLibrary != nodeLibrary) {
17772 _errorReporter.reportError3(StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_ NAME, node, [ 18731 _errorReporter.reportError3(StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_ NAME, node, [
17773 prevLibrary.definingCompilationUnit.displayName, 18732 prevLibrary.definingCompilationUnit.displayName,
17774 nodeLibrary.definingCompilationUnit.displayName, 18733 nodeLibrary.definingCompilationUnit.displayName,
17775 name]); 18734 name]);
17776 return true; 18735 return true;
17777 } 18736 }
17778 } else { 18737 } else {
17779 _nameToImportElement[name] = nodeLibrary; 18738 _nameToImportElement[name] = nodeLibrary;
17780 } 18739 }
18740 // OK
17781 return false; 18741 return false;
17782 } 18742 }
17783 18743
17784 /** 18744 /**
17785 * Check that if the visiting library is not system, then any passed library s hould not be SDK 18745 * Check that if the visiting library is not system, then any passed library s hould not be SDK
17786 * internal library. 18746 * internal library.
17787 * 18747 *
17788 * @param node the import directive to evaluate 18748 * @param node the import directive to evaluate
17789 * @return `true` if and only if an error code is generated on the passed node 18749 * @return `true` if and only if an error code is generated on the passed node
17790 * @see CompileTimeErrorCode#IMPORT_INTERNAL_LIBRARY 18750 * @see CompileTimeErrorCode#IMPORT_INTERNAL_LIBRARY
17791 */ 18751 */
17792 bool checkForImportInternalLibrary(ImportDirective node) { 18752 bool checkForImportInternalLibrary(ImportDirective node) {
17793 if (_isInSystemLibrary) { 18753 if (_isInSystemLibrary) {
17794 return false; 18754 return false;
17795 } 18755 }
18756 // prepare import element
17796 ImportElement importElement = node.element; 18757 ImportElement importElement = node.element;
17797 if (importElement == null) { 18758 if (importElement == null) {
17798 return false; 18759 return false;
17799 } 18760 }
18761 // should be private
17800 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk; 18762 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk;
17801 String uri = importElement.uri; 18763 String uri = importElement.uri;
17802 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri); 18764 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri);
17803 if (sdkLibrary == null) { 18765 if (sdkLibrary == null) {
17804 return false; 18766 return false;
17805 } 18767 }
17806 if (!sdkLibrary.isInternal) { 18768 if (!sdkLibrary.isInternal) {
17807 return false; 18769 return false;
17808 } 18770 }
18771 // report problem
17809 _errorReporter.reportError3(CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, no de, [node.uri]); 18772 _errorReporter.reportError3(CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, no de, [node.uri]);
17810 return true; 18773 return true;
17811 } 18774 }
17812 18775
17813 /** 18776 /**
17814 * This verifies that the passed switch statement case expressions all have th e same type. 18777 * This verifies that the passed switch statement case expressions all have th e same type.
17815 * 18778 *
17816 * @param node the switch statement to evaluate 18779 * @param node the switch statement to evaluate
17817 * @return `true` if and only if an error code is generated on the passed node 18780 * @return `true` if and only if an error code is generated on the passed node
17818 * @see CompileTimeErrorCode#INCONSISTENT_CASE_EXPRESSION_TYPES 18781 * @see CompileTimeErrorCode#INCONSISTENT_CASE_EXPRESSION_TYPES
17819 */ 18782 */
17820 bool checkForInconsistentCaseExpressionTypes(SwitchStatement node) { 18783 bool checkForInconsistentCaseExpressionTypes(SwitchStatement node) {
18784 // TODO(jwren) Revisit this algorithm, should there up to n-1 errors?
17821 NodeList<SwitchMember> switchMembers = node.members; 18785 NodeList<SwitchMember> switchMembers = node.members;
17822 bool foundError = false; 18786 bool foundError = false;
17823 Type2 firstType = null; 18787 Type2 firstType = null;
17824 for (SwitchMember switchMember in switchMembers) { 18788 for (SwitchMember switchMember in switchMembers) {
17825 if (switchMember is SwitchCase) { 18789 if (switchMember is SwitchCase) {
17826 SwitchCase switchCase = switchMember; 18790 SwitchCase switchCase = switchMember;
17827 Expression expression = switchCase.expression; 18791 Expression expression = switchCase.expression;
17828 if (firstType == null) { 18792 if (firstType == null) {
18793 // TODO(brianwilkerson) This is failing with const variables whose dec lared type is
18794 // dynamic. The problem is that we don't have any way to propagate typ e information for
18795 // the variable.
17829 firstType = expression.bestType; 18796 firstType = expression.bestType;
17830 } else { 18797 } else {
17831 Type2 nType = expression.bestType; 18798 Type2 nType = expression.bestType;
17832 if (firstType != nType) { 18799 if (firstType != nType) {
17833 _errorReporter.reportError3(CompileTimeErrorCode.INCONSISTENT_CASE_E XPRESSION_TYPES, expression, [expression.toSource(), firstType.displayName]); 18800 _errorReporter.reportError3(CompileTimeErrorCode.INCONSISTENT_CASE_E XPRESSION_TYPES, expression, [expression.toSource(), firstType.displayName]);
17834 foundError = true; 18801 foundError = true;
17835 } 18802 }
17836 } 18803 }
17837 } 18804 }
17838 } 18805 }
17839 if (!foundError) { 18806 if (!foundError) {
17840 checkForCaseExpressionTypeImplementsEquals(node, firstType); 18807 checkForCaseExpressionTypeImplementsEquals(node, firstType);
17841 } 18808 }
17842 return foundError; 18809 return foundError;
17843 } 18810 }
17844 18811
17845 /** 18812 /**
17846 * For each class declaration, this method is called which verifies that all i nherited members are 18813 * For each class declaration, this method is called which verifies that all i nherited members are
17847 * inherited consistently. 18814 * inherited consistently.
17848 * 18815 *
17849 * @return `true` if and only if an error code is generated on the passed node 18816 * @return `true` if and only if an error code is generated on the passed node
17850 * @see StaticTypeWarningCode#INCONSISTENT_METHOD_INHERITANCE 18817 * @see StaticTypeWarningCode#INCONSISTENT_METHOD_INHERITANCE
17851 */ 18818 */
17852 bool checkForInconsistentMethodInheritance() { 18819 bool checkForInconsistentMethodInheritance() {
18820 // Ensure that the inheritance manager has a chance to generate all errors w e may care about,
18821 // note that we ensure that the interfaces data since there are no errors.
17853 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(_enclosingClass); 18822 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(_enclosingClass);
17854 Set<AnalysisError> errors = _inheritanceManager.getErrors(_enclosingClass); 18823 Set<AnalysisError> errors = _inheritanceManager.getErrors(_enclosingClass);
17855 if (errors == null || errors.isEmpty) { 18824 if (errors == null || errors.isEmpty) {
17856 return false; 18825 return false;
17857 } 18826 }
17858 for (AnalysisError error in errors) { 18827 for (AnalysisError error in errors) {
17859 _errorReporter.reportError(error); 18828 _errorReporter.reportError(error);
17860 } 18829 }
17861 return true; 18830 return true;
17862 } 18831 }
17863 18832
17864 /** 18833 /**
17865 * This checks the given "typeReference" is not a type reference and that then the "name" is 18834 * This checks the given "typeReference" is not a type reference and that then the "name" is
17866 * reference to an instance member. 18835 * reference to an instance member.
17867 * 18836 *
17868 * @param typeReference the resolved [ClassElement] of the left hand side of t he expression, 18837 * @param typeReference the resolved [ClassElement] of the left hand side of t he expression,
17869 * or `null`, aka, the class element of 'C' in 'C.x', see 18838 * or `null`, aka, the class element of 'C' in 'C.x', see
17870 * [getTypeReference] 18839 * [getTypeReference]
17871 * @param name the accessed name to evaluate 18840 * @param name the accessed name to evaluate
17872 * @return `true` if and only if an error code is generated on the passed node 18841 * @return `true` if and only if an error code is generated on the passed node
17873 * @see StaticTypeWarningCode#INSTANCE_ACCESS_TO_STATIC_MEMBER 18842 * @see StaticTypeWarningCode#INSTANCE_ACCESS_TO_STATIC_MEMBER
17874 */ 18843 */
17875 bool checkForInstanceAccessToStaticMember(ClassElement typeReference, SimpleId entifier name) { 18844 bool checkForInstanceAccessToStaticMember(ClassElement typeReference, SimpleId entifier name) {
18845 // OK, in comment
17876 if (_isInComment) { 18846 if (_isInComment) {
17877 return false; 18847 return false;
17878 } 18848 }
18849 // OK, target is a type
17879 if (typeReference != null) { 18850 if (typeReference != null) {
17880 return false; 18851 return false;
17881 } 18852 }
18853 // prepare member Element
17882 Element element = name.staticElement; 18854 Element element = name.staticElement;
17883 if (element is! ExecutableElement) { 18855 if (element is! ExecutableElement) {
17884 return false; 18856 return false;
17885 } 18857 }
17886 ExecutableElement executableElement = element as ExecutableElement; 18858 ExecutableElement executableElement = element as ExecutableElement;
18859 // OK, top-level element
17887 if (executableElement.enclosingElement is! ClassElement) { 18860 if (executableElement.enclosingElement is! ClassElement) {
17888 return false; 18861 return false;
17889 } 18862 }
18863 // OK, instance member
17890 if (!executableElement.isStatic) { 18864 if (!executableElement.isStatic) {
17891 return false; 18865 return false;
17892 } 18866 }
18867 // report problem
17893 _errorReporter.reportError3(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_ MEMBER, name, [name.name]); 18868 _errorReporter.reportError3(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_ MEMBER, name, [name.name]);
17894 return true; 18869 return true;
17895 } 18870 }
17896 18871
17897 /** 18872 /**
17898 * This verifies that an 'int' can be assigned to the parameter corresponding to the given 18873 * This verifies that an 'int' can be assigned to the parameter corresponding to the given
17899 * expression. This is used for prefix and postfix expressions where the argum ent value is 18874 * expression. This is used for prefix and postfix expressions where the argum ent value is
17900 * implicit. 18875 * implicit.
17901 * 18876 *
17902 * @param argument the expression to which the operator is being applied 18877 * @param argument the expression to which the operator is being applied
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
17957 return false; 18932 return false;
17958 } 18933 }
17959 VariableElement leftElement = getVariableElement(lhs); 18934 VariableElement leftElement = getVariableElement(lhs);
17960 Type2 leftType = (leftElement == null) ? getStaticType(lhs) : leftElement.ty pe; 18935 Type2 leftType = (leftElement == null) ? getStaticType(lhs) : leftElement.ty pe;
17961 Type2 staticRightType = getStaticType(rhs); 18936 Type2 staticRightType = getStaticType(rhs);
17962 bool isStaticAssignable = staticRightType.isAssignableTo(leftType); 18937 bool isStaticAssignable = staticRightType.isAssignableTo(leftType);
17963 if (!isStaticAssignable) { 18938 if (!isStaticAssignable) {
17964 _errorReporter.reportError3(StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [staticRightType.displayName, leftType.displayName]); 18939 _errorReporter.reportError3(StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [staticRightType.displayName, leftType.displayName]);
17965 return true; 18940 return true;
17966 } 18941 }
18942 // TODO(brianwilkerson) Define a hint corresponding to the warning and repor t it if appropriate.
18943 // Type propagatedRightType = rhs.getPropagatedType();
18944 // boolean isPropagatedAssignable = propagatedRightType.isAssignableTo(le ftType);
18945 // if (!isStaticAssignable && !isPropagatedAssignable) {
18946 // errorReporter.reportError(
18947 // StaticTypeWarningCode.INVALID_ASSIGNMENT,
18948 // rhs,
18949 // staticRightType.getDisplayName(),
18950 // leftType.getDisplayName());
18951 // return true;
18952 // }
17967 return false; 18953 return false;
17968 } 18954 }
17969 18955
17970 /** 18956 /**
17971 * This verifies that the usage of the passed 'this' is valid. 18957 * This verifies that the usage of the passed 'this' is valid.
17972 * 18958 *
17973 * @param node the 'this' expression to evaluate 18959 * @param node the 'this' expression to evaluate
17974 * @return `true` if and only if an error code is generated on the passed node 18960 * @return `true` if and only if an error code is generated on the passed node
17975 * @see CompileTimeErrorCode#INVALID_REFERENCE_TO_THIS 18961 * @see CompileTimeErrorCode#INVALID_REFERENCE_TO_THIS
17976 */ 18962 */
(...skipping 29 matching lines...) Expand all
18006 /** 18992 /**
18007 * This verifies that the elements given [ListLiteral] are subtypes of the spe cified element 18993 * This verifies that the elements given [ListLiteral] are subtypes of the spe cified element
18008 * type. 18994 * type.
18009 * 18995 *
18010 * @param node the list literal to evaluate 18996 * @param node the list literal to evaluate
18011 * @return `true` if and only if an error code is generated on the passed node 18997 * @return `true` if and only if an error code is generated on the passed node
18012 * @see CompileTimeErrorCode#LIST_ELEMENT_TYPE_NOT_ASSIGNABLE 18998 * @see CompileTimeErrorCode#LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
18013 * @see StaticWarningCode#LIST_ELEMENT_TYPE_NOT_ASSIGNABLE 18999 * @see StaticWarningCode#LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
18014 */ 19000 */
18015 bool checkForListElementTypeNotAssignable(ListLiteral node) { 19001 bool checkForListElementTypeNotAssignable(ListLiteral node) {
19002 // Prepare list element type.
18016 TypeArgumentList typeArgumentList = node.typeArguments; 19003 TypeArgumentList typeArgumentList = node.typeArguments;
18017 if (typeArgumentList == null) { 19004 if (typeArgumentList == null) {
18018 return false; 19005 return false;
18019 } 19006 }
18020 NodeList<TypeName> typeArguments = typeArgumentList.arguments; 19007 NodeList<TypeName> typeArguments = typeArgumentList.arguments;
18021 if (typeArguments.length < 1) { 19008 if (typeArguments.length < 1) {
18022 return false; 19009 return false;
18023 } 19010 }
18024 Type2 listElementType = typeArguments[0].type; 19011 Type2 listElementType = typeArguments[0].type;
19012 // Prepare problem to report.
18025 ErrorCode errorCode; 19013 ErrorCode errorCode;
18026 if (node.constKeyword != null) { 19014 if (node.constKeyword != null) {
18027 errorCode = CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE; 19015 errorCode = CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE;
18028 } else { 19016 } else {
18029 errorCode = StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE; 19017 errorCode = StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE;
18030 } 19018 }
19019 // Check every list element.
18031 bool hasProblems = false; 19020 bool hasProblems = false;
18032 for (Expression element in node.elements) { 19021 for (Expression element in node.elements) {
18033 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(element, listElementType, null, errorCode)); 19022 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(element, listElementType, null, errorCode));
18034 } 19023 }
18035 return hasProblems; 19024 return hasProblems;
18036 } 19025 }
18037 19026
18038 /** 19027 /**
18039 * This verifies that the key/value of entries of the given [MapLiteral] are s ubtypes of the 19028 * This verifies that the key/value of entries of the given [MapLiteral] are s ubtypes of the
18040 * key/value types specified in the type arguments. 19029 * key/value types specified in the type arguments.
18041 * 19030 *
18042 * @param node the map literal to evaluate 19031 * @param node the map literal to evaluate
18043 * @return `true` if and only if an error code is generated on the passed node 19032 * @return `true` if and only if an error code is generated on the passed node
18044 * @see CompileTimeErrorCode#MAP_KEY_TYPE_NOT_ASSIGNABLE 19033 * @see CompileTimeErrorCode#MAP_KEY_TYPE_NOT_ASSIGNABLE
18045 * @see CompileTimeErrorCode#MAP_VALUE_TYPE_NOT_ASSIGNABLE 19034 * @see CompileTimeErrorCode#MAP_VALUE_TYPE_NOT_ASSIGNABLE
18046 * @see StaticWarningCode#MAP_KEY_TYPE_NOT_ASSIGNABLE 19035 * @see StaticWarningCode#MAP_KEY_TYPE_NOT_ASSIGNABLE
18047 * @see StaticWarningCode#MAP_VALUE_TYPE_NOT_ASSIGNABLE 19036 * @see StaticWarningCode#MAP_VALUE_TYPE_NOT_ASSIGNABLE
18048 */ 19037 */
18049 bool checkForMapTypeNotAssignable(MapLiteral node) { 19038 bool checkForMapTypeNotAssignable(MapLiteral node) {
19039 // Prepare maps key/value types.
18050 TypeArgumentList typeArgumentList = node.typeArguments; 19040 TypeArgumentList typeArgumentList = node.typeArguments;
18051 if (typeArgumentList == null) { 19041 if (typeArgumentList == null) {
18052 return false; 19042 return false;
18053 } 19043 }
18054 NodeList<TypeName> typeArguments = typeArgumentList.arguments; 19044 NodeList<TypeName> typeArguments = typeArgumentList.arguments;
18055 if (typeArguments.length < 2) { 19045 if (typeArguments.length < 2) {
18056 return false; 19046 return false;
18057 } 19047 }
18058 Type2 keyType = typeArguments[0].type; 19048 Type2 keyType = typeArguments[0].type;
18059 Type2 valueType = typeArguments[1].type; 19049 Type2 valueType = typeArguments[1].type;
19050 // Prepare problem to report.
18060 ErrorCode keyErrorCode; 19051 ErrorCode keyErrorCode;
18061 ErrorCode valueErrorCode; 19052 ErrorCode valueErrorCode;
18062 if (node.constKeyword != null) { 19053 if (node.constKeyword != null) {
18063 keyErrorCode = CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE; 19054 keyErrorCode = CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE;
18064 valueErrorCode = CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE; 19055 valueErrorCode = CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE;
18065 } else { 19056 } else {
18066 keyErrorCode = StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE; 19057 keyErrorCode = StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE;
18067 valueErrorCode = StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE; 19058 valueErrorCode = StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE;
18068 } 19059 }
19060 // Check every map entry.
18069 bool hasProblems = false; 19061 bool hasProblems = false;
18070 NodeList<MapLiteralEntry> entries = node.entries; 19062 NodeList<MapLiteralEntry> entries = node.entries;
18071 for (MapLiteralEntry entry in entries) { 19063 for (MapLiteralEntry entry in entries) {
18072 Expression key = entry.key; 19064 Expression key = entry.key;
18073 Expression value = entry.value; 19065 Expression value = entry.value;
18074 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(key, keyType, null, keyErrorCode)); 19066 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(key, keyType, null, keyErrorCode));
18075 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(value, valueType, null, valueErrorCode)); 19067 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(value, valueType, null, valueErrorCode));
18076 } 19068 }
18077 return hasProblems; 19069 return hasProblems;
18078 } 19070 }
18079 19071
18080 /** 19072 /**
18081 * This verifies that the [enclosingClass] does not define members with the sa me name as 19073 * This verifies that the [enclosingClass] does not define members with the sa me name as
18082 * the enclosing class. 19074 * the enclosing class.
18083 * 19075 *
18084 * @return `true` if and only if an error code is generated on the passed node 19076 * @return `true` if and only if an error code is generated on the passed node
18085 * @see CompileTimeErrorCode#MEMBER_WITH_CLASS_NAME 19077 * @see CompileTimeErrorCode#MEMBER_WITH_CLASS_NAME
18086 */ 19078 */
18087 bool checkForMemberWithClassName() { 19079 bool checkForMemberWithClassName() {
18088 if (_enclosingClass == null) { 19080 if (_enclosingClass == null) {
18089 return false; 19081 return false;
18090 } 19082 }
18091 String className = _enclosingClass.name; 19083 String className = _enclosingClass.name;
18092 if (className == null) { 19084 if (className == null) {
18093 return false; 19085 return false;
18094 } 19086 }
18095 bool problemReported = false; 19087 bool problemReported = false;
19088 // check accessors
18096 for (PropertyAccessorElement accessor in _enclosingClass.accessors) { 19089 for (PropertyAccessorElement accessor in _enclosingClass.accessors) {
18097 if (className == accessor.name) { 19090 if (className == accessor.name) {
18098 _errorReporter.reportError5(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, accessor.nameOffset, className.length, []); 19091 _errorReporter.reportError5(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, accessor.nameOffset, className.length, []);
18099 problemReported = true; 19092 problemReported = true;
18100 } 19093 }
18101 } 19094 }
19095 // don't check methods, they would be constructors
19096 // done
18102 return problemReported; 19097 return problemReported;
18103 } 19098 }
18104 19099
18105 /** 19100 /**
18106 * Check to make sure that all similarly typed accessors are of the same type (including inherited 19101 * Check to make sure that all similarly typed accessors are of the same type (including inherited
18107 * accessors). 19102 * accessors).
18108 * 19103 *
18109 * @param node the accessor currently being visited 19104 * @param node the accessor currently being visited
18110 * @return `true` if and only if an error code is generated on the passed node 19105 * @return `true` if and only if an error code is generated on the passed node
18111 * @see StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES 19106 * @see StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES
18112 * @see StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE 19107 * @see StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE
18113 */ 19108 */
18114 bool checkForMismatchedAccessorTypes(Declaration accessorDeclaration, String a ccessorTextName) { 19109 bool checkForMismatchedAccessorTypes(Declaration accessorDeclaration, String a ccessorTextName) {
18115 ExecutableElement accessorElement = accessorDeclaration.element as Executabl eElement; 19110 ExecutableElement accessorElement = accessorDeclaration.element as Executabl eElement;
18116 if (accessorElement is! PropertyAccessorElement) { 19111 if (accessorElement is! PropertyAccessorElement) {
18117 return false; 19112 return false;
18118 } 19113 }
18119 PropertyAccessorElement propertyAccessorElement = accessorElement as Propert yAccessorElement; 19114 PropertyAccessorElement propertyAccessorElement = accessorElement as Propert yAccessorElement;
18120 PropertyAccessorElement counterpartAccessor = null; 19115 PropertyAccessorElement counterpartAccessor = null;
18121 ClassElement enclosingClassForCounterpart = null; 19116 ClassElement enclosingClassForCounterpart = null;
18122 if (propertyAccessorElement.isGetter) { 19117 if (propertyAccessorElement.isGetter) {
18123 counterpartAccessor = propertyAccessorElement.correspondingSetter; 19118 counterpartAccessor = propertyAccessorElement.correspondingSetter;
18124 } else { 19119 } else {
18125 counterpartAccessor = propertyAccessorElement.correspondingGetter; 19120 counterpartAccessor = propertyAccessorElement.correspondingGetter;
19121 // If the setter and getter are in the same enclosing element, return, thi s prevents having
19122 // MISMATCHED_GETTER_AND_SETTER_TYPES reported twice.
18126 if (counterpartAccessor != null && identical(counterpartAccessor.enclosing Element, propertyAccessorElement.enclosingElement)) { 19123 if (counterpartAccessor != null && identical(counterpartAccessor.enclosing Element, propertyAccessorElement.enclosingElement)) {
18127 return false; 19124 return false;
18128 } 19125 }
18129 } 19126 }
18130 if (counterpartAccessor == null) { 19127 if (counterpartAccessor == null) {
19128 // If the accessor is declared in a class, check the superclasses.
18131 if (_enclosingClass != null) { 19129 if (_enclosingClass != null) {
19130 // Figure out the correct identifier to lookup in the inheritance graph, if 'x', then 'x=',
19131 // or if 'x=', then 'x'.
18132 String lookupIdentifier = propertyAccessorElement.name; 19132 String lookupIdentifier = propertyAccessorElement.name;
18133 if (lookupIdentifier.endsWith("=")) { 19133 if (lookupIdentifier.endsWith("=")) {
18134 lookupIdentifier = lookupIdentifier.substring(0, lookupIdentifier.leng th - 1); 19134 lookupIdentifier = lookupIdentifier.substring(0, lookupIdentifier.leng th - 1);
18135 } else { 19135 } else {
18136 lookupIdentifier += "="; 19136 lookupIdentifier += "=";
18137 } 19137 }
19138 // lookup with the identifier.
18138 ExecutableElement elementFromInheritance = _inheritanceManager.lookupInh eritance(_enclosingClass, lookupIdentifier); 19139 ExecutableElement elementFromInheritance = _inheritanceManager.lookupInh eritance(_enclosingClass, lookupIdentifier);
19140 // Verify that we found something, and that it is an accessor
18139 if (elementFromInheritance != null && elementFromInheritance is Property AccessorElement) { 19141 if (elementFromInheritance != null && elementFromInheritance is Property AccessorElement) {
18140 enclosingClassForCounterpart = elementFromInheritance.enclosingElement as ClassElement; 19142 enclosingClassForCounterpart = elementFromInheritance.enclosingElement as ClassElement;
18141 counterpartAccessor = elementFromInheritance; 19143 counterpartAccessor = elementFromInheritance;
18142 } 19144 }
18143 } 19145 }
18144 if (counterpartAccessor == null) { 19146 if (counterpartAccessor == null) {
18145 return false; 19147 return false;
18146 } 19148 }
18147 } 19149 }
19150 // Default of null == no accessor or no type (dynamic)
18148 Type2 getterType = null; 19151 Type2 getterType = null;
18149 Type2 setterType = null; 19152 Type2 setterType = null;
19153 // Get an existing counterpart accessor if any.
18150 if (propertyAccessorElement.isGetter) { 19154 if (propertyAccessorElement.isGetter) {
18151 getterType = getGetterType(propertyAccessorElement); 19155 getterType = getGetterType(propertyAccessorElement);
18152 setterType = getSetterType(counterpartAccessor); 19156 setterType = getSetterType(counterpartAccessor);
18153 } else if (propertyAccessorElement.isSetter) { 19157 } else if (propertyAccessorElement.isSetter) {
18154 setterType = getSetterType(propertyAccessorElement); 19158 setterType = getSetterType(propertyAccessorElement);
18155 getterType = getGetterType(counterpartAccessor); 19159 getterType = getGetterType(counterpartAccessor);
18156 } 19160 }
19161 // If either types are not assignable to each other, report an error (if the getter is null,
19162 // it is dynamic which is assignable to everything).
18157 if (setterType != null && getterType != null && !getterType.isAssignableTo(s etterType)) { 19163 if (setterType != null && getterType != null && !getterType.isAssignableTo(s etterType)) {
18158 if (enclosingClassForCounterpart == null) { 19164 if (enclosingClassForCounterpart == null) {
18159 _errorReporter.reportError3(StaticWarningCode.MISMATCHED_GETTER_AND_SETT ER_TYPES, accessorDeclaration, [ 19165 _errorReporter.reportError3(StaticWarningCode.MISMATCHED_GETTER_AND_SETT ER_TYPES, accessorDeclaration, [
18160 accessorTextName, 19166 accessorTextName,
18161 setterType.displayName, 19167 setterType.displayName,
18162 getterType.displayName]); 19168 getterType.displayName]);
18163 return true; 19169 return true;
18164 } else { 19170 } else {
18165 _errorReporter.reportError3(StaticWarningCode.MISMATCHED_GETTER_AND_SETT ER_TYPES_FROM_SUPERTYPE, accessorDeclaration, [ 19171 _errorReporter.reportError3(StaticWarningCode.MISMATCHED_GETTER_AND_SETT ER_TYPES_FROM_SUPERTYPE, accessorDeclaration, [
18166 accessorTextName, 19172 accessorTextName,
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
18261 } 19267 }
18262 19268
18263 /** 19269 /**
18264 * Checks to ensure that native function bodies can only in SDK code. 19270 * Checks to ensure that native function bodies can only in SDK code.
18265 * 19271 *
18266 * @param node the native function body to test 19272 * @param node the native function body to test
18267 * @return `true` if and only if an error code is generated on the passed node 19273 * @return `true` if and only if an error code is generated on the passed node
18268 * @see ParserErrorCode#NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE 19274 * @see ParserErrorCode#NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
18269 */ 19275 */
18270 bool checkForNativeFunctionBodyInNonSDKCode(NativeFunctionBody node) { 19276 bool checkForNativeFunctionBodyInNonSDKCode(NativeFunctionBody node) {
19277 // TODO(brianwilkerson) Figure out the right rule for when 'native' is allow ed.
18271 if (!_isInSystemLibrary) { 19278 if (!_isInSystemLibrary) {
18272 _errorReporter.reportError3(ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SD K_CODE, node, []); 19279 _errorReporter.reportError3(ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SD K_CODE, node, []);
18273 return true; 19280 return true;
18274 } 19281 }
18275 return false; 19282 return false;
18276 } 19283 }
18277 19284
18278 /** 19285 /**
18279 * This verifies that the passed 'new' instance creation expression invokes ex isting constructor. 19286 * This verifies that the passed 'new' instance creation expression invokes ex isting constructor.
18280 * 19287 *
18281 * This method assumes that the instance creation was tested to be 'new' befor e being called. 19288 * This method assumes that the instance creation was tested to be 'new' befor e being called.
18282 * 19289 *
18283 * @param node the instance creation expression to evaluate 19290 * @param node the instance creation expression to evaluate
18284 * @return `true` if and only if an error code is generated on the passed node 19291 * @return `true` if and only if an error code is generated on the passed node
18285 * @see StaticWarningCode#NEW_WITH_UNDEFINED_CONSTRUCTOR 19292 * @see StaticWarningCode#NEW_WITH_UNDEFINED_CONSTRUCTOR
18286 */ 19293 */
18287 bool checkForNewWithUndefinedConstructor(InstanceCreationExpression node) { 19294 bool checkForNewWithUndefinedConstructor(InstanceCreationExpression node) {
19295 // OK if resolved
18288 if (node.staticElement != null) { 19296 if (node.staticElement != null) {
18289 return false; 19297 return false;
18290 } 19298 }
19299 // prepare constructor name
18291 ConstructorName constructorName = node.constructorName; 19300 ConstructorName constructorName = node.constructorName;
18292 if (constructorName == null) { 19301 if (constructorName == null) {
18293 return false; 19302 return false;
18294 } 19303 }
19304 // prepare class name
18295 TypeName type = constructorName.type; 19305 TypeName type = constructorName.type;
18296 if (type == null) { 19306 if (type == null) {
18297 return false; 19307 return false;
18298 } 19308 }
18299 Identifier className = type.name; 19309 Identifier className = type.name;
19310 // report as named or default constructor absence
18300 SimpleIdentifier name = constructorName.name; 19311 SimpleIdentifier name = constructorName.name;
18301 if (name != null) { 19312 if (name != null) {
18302 _errorReporter.reportError3(StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCT OR, name, [className, name]); 19313 _errorReporter.reportError3(StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCT OR, name, [className, name]);
18303 } else { 19314 } else {
18304 _errorReporter.reportError3(StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCT OR_DEFAULT, constructorName, [className]); 19315 _errorReporter.reportError3(StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCT OR_DEFAULT, constructorName, [className]);
18305 } 19316 }
18306 return true; 19317 return true;
18307 } 19318 }
18308 19319
18309 /** 19320 /**
18310 * This checks that if the passed class declaration implicitly calls default c onstructor of its 19321 * This checks that if the passed class declaration implicitly calls default c onstructor of its
18311 * superclass, there should be such default constructor - implicit or explicit . 19322 * superclass, there should be such default constructor - implicit or explicit .
18312 * 19323 *
18313 * @param node the [ClassDeclaration] to evaluate 19324 * @param node the [ClassDeclaration] to evaluate
18314 * @return `true` if and only if an error code is generated on the passed node 19325 * @return `true` if and only if an error code is generated on the passed node
18315 * @see CompileTimeErrorCode#NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT 19326 * @see CompileTimeErrorCode#NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
18316 */ 19327 */
18317 bool checkForNoDefaultSuperConstructorImplicit(ClassDeclaration node) { 19328 bool checkForNoDefaultSuperConstructorImplicit(ClassDeclaration node) {
19329 // do nothing if there is explicit constructor
18318 List<ConstructorElement> constructors = _enclosingClass.constructors; 19330 List<ConstructorElement> constructors = _enclosingClass.constructors;
18319 if (!constructors[0].isSynthetic) { 19331 if (!constructors[0].isSynthetic) {
18320 return false; 19332 return false;
18321 } 19333 }
19334 // prepare super
18322 InterfaceType superType = _enclosingClass.supertype; 19335 InterfaceType superType = _enclosingClass.supertype;
18323 if (superType == null) { 19336 if (superType == null) {
18324 return false; 19337 return false;
18325 } 19338 }
18326 ClassElement superElement = superType.element; 19339 ClassElement superElement = superType.element;
19340 // try to find default generative super constructor
18327 ConstructorElement superUnnamedConstructor = superElement.unnamedConstructor ; 19341 ConstructorElement superUnnamedConstructor = superElement.unnamedConstructor ;
18328 if (superUnnamedConstructor != null) { 19342 if (superUnnamedConstructor != null) {
18329 if (superUnnamedConstructor.isFactory) { 19343 if (superUnnamedConstructor.isFactory) {
18330 _errorReporter.reportError3(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUC TOR, node.name, [superUnnamedConstructor]); 19344 _errorReporter.reportError3(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUC TOR, node.name, [superUnnamedConstructor]);
18331 return true; 19345 return true;
18332 } 19346 }
18333 if (superUnnamedConstructor.isDefaultConstructor) { 19347 if (superUnnamedConstructor.isDefaultConstructor) {
18334 return true; 19348 return true;
18335 } 19349 }
18336 } 19350 }
19351 // report problem
18337 _errorReporter.reportError3(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTO R_IMPLICIT, node.name, [superType.displayName]); 19352 _errorReporter.reportError3(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTO R_IMPLICIT, node.name, [superType.displayName]);
18338 return true; 19353 return true;
18339 } 19354 }
18340 19355
18341 /** 19356 /**
18342 * This checks that passed class declaration overrides all members required by its superclasses 19357 * This checks that passed class declaration overrides all members required by its superclasses
18343 * and interfaces. 19358 * and interfaces.
18344 * 19359 *
18345 * @param node the [ClassDeclaration] to evaluate 19360 * @param node the [ClassDeclaration] to evaluate
18346 * @return `true` if and only if an error code is generated on the passed node 19361 * @return `true` if and only if an error code is generated on the passed node
18347 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE 19362 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE
18348 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO 19363 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO
18349 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE 19364 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE
18350 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR 19365 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR
18351 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLU S 19366 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLU S
18352 */ 19367 */
18353 bool checkForNonAbstractClassInheritsAbstractMember(ClassDeclaration node) { 19368 bool checkForNonAbstractClassInheritsAbstractMember(ClassDeclaration node) {
18354 if (_enclosingClass.isAbstract) { 19369 if (_enclosingClass.isAbstract) {
18355 return false; 19370 return false;
18356 } 19371 }
19372 //
19373 // Store in local sets the set of all method and accessor names
19374 //
18357 List<MethodElement> methods = _enclosingClass.methods; 19375 List<MethodElement> methods = _enclosingClass.methods;
18358 List<PropertyAccessorElement> accessors = _enclosingClass.accessors; 19376 List<PropertyAccessorElement> accessors = _enclosingClass.accessors;
18359 Set<String> methodsInEnclosingClass = new Set<String>(); 19377 Set<String> methodsInEnclosingClass = new Set<String>();
18360 for (MethodElement method in methods) { 19378 for (MethodElement method in methods) {
18361 String methodName = method.name; 19379 String methodName = method.name;
19380 // If the enclosing class declares the method noSuchMethod(), then return.
19381 // From Spec: It is a static warning if a concrete class does not have an implementation for
19382 // a method in any of its superinterfaces unless it declares its own noSuc hMethod
19383 // method (7.10).
18362 if (methodName == ElementResolver.NO_SUCH_METHOD_METHOD_NAME) { 19384 if (methodName == ElementResolver.NO_SUCH_METHOD_METHOD_NAME) {
18363 return false; 19385 return false;
18364 } 19386 }
18365 methodsInEnclosingClass.add(methodName); 19387 methodsInEnclosingClass.add(methodName);
18366 } 19388 }
18367 Set<String> accessorsInEnclosingClass = new Set<String>(); 19389 Set<String> accessorsInEnclosingClass = new Set<String>();
18368 for (PropertyAccessorElement accessor in accessors) { 19390 for (PropertyAccessorElement accessor in accessors) {
18369 accessorsInEnclosingClass.add(accessor.name); 19391 accessorsInEnclosingClass.add(accessor.name);
18370 } 19392 }
18371 Set<ExecutableElement> missingOverrides = new Set<ExecutableElement>(); 19393 Set<ExecutableElement> missingOverrides = new Set<ExecutableElement>();
19394 //
19395 // Loop through the set of all executable elements declared in the implicit interface.
19396 //
18372 MemberMap membersInheritedFromInterfaces = _inheritanceManager.getMapOfMembe rsInheritedFromInterfaces(_enclosingClass); 19397 MemberMap membersInheritedFromInterfaces = _inheritanceManager.getMapOfMembe rsInheritedFromInterfaces(_enclosingClass);
18373 MemberMap membersInheritedFromSuperclasses = _inheritanceManager.getMapOfMem bersInheritedFromClasses(_enclosingClass); 19398 MemberMap membersInheritedFromSuperclasses = _inheritanceManager.getMapOfMem bersInheritedFromClasses(_enclosingClass);
18374 for (int i = 0; i < membersInheritedFromInterfaces.size; i++) { 19399 for (int i = 0; i < membersInheritedFromInterfaces.size; i++) {
18375 String memberName = membersInheritedFromInterfaces.getKey(i); 19400 String memberName = membersInheritedFromInterfaces.getKey(i);
18376 ExecutableElement executableElt = membersInheritedFromInterfaces.getValue( i); 19401 ExecutableElement executableElt = membersInheritedFromInterfaces.getValue( i);
18377 if (memberName == null) { 19402 if (memberName == null) {
18378 break; 19403 break;
18379 } 19404 }
19405 // If the element is defined in Object, skip it.
18380 if ((executableElt.enclosingElement as ClassElement).type.isObject) { 19406 if ((executableElt.enclosingElement as ClassElement).type.isObject) {
18381 continue; 19407 continue;
18382 } 19408 }
19409 // Reference the type of the enclosing class
18383 InterfaceType enclosingType = _enclosingClass.type; 19410 InterfaceType enclosingType = _enclosingClass.type;
19411 // Check to see if some element is in local enclosing class that matches t he name of the
19412 // required member.
18384 if (isMemberInClassOrMixin(executableElt, _enclosingClass)) { 19413 if (isMemberInClassOrMixin(executableElt, _enclosingClass)) {
19414 // We do not have to verify that this implementation of the found method matches the
19415 // required function type: the set of StaticWarningCode.INVALID_METHOD_O VERRIDE_* warnings
19416 // break out the different specific situations.
18385 continue; 19417 continue;
18386 } 19418 }
19419 // First check to see if this element was declared in the superclass chain , in which case
19420 // there is already a concrete implementation.
18387 ExecutableElement elt = membersInheritedFromSuperclasses.get(executableElt .name); 19421 ExecutableElement elt = membersInheritedFromSuperclasses.get(executableElt .name);
19422 // Check to see if an element was found in the superclass chain with the c orrect name.
18388 if (elt != null) { 19423 if (elt != null) {
19424 // Some element was found in the superclass chain that matches the name of the required
19425 // member.
19426 // If it is not abstract and it is the correct one (types match- the ver sion of this method
19427 // that we have has the correct number of parameters, etc), then this cl ass has a valid
19428 // implementation of this method, so skip it.
18389 if ((elt is MethodElement && !elt.isAbstract) || (elt is PropertyAccesso rElement && !elt.isAbstract)) { 19429 if ((elt is MethodElement && !elt.isAbstract) || (elt is PropertyAccesso rElement && !elt.isAbstract)) {
19430 // Since we are comparing two function types, we need to do the approp riate type
19431 // substitutions first ().
18390 FunctionType foundConcreteFT = _inheritanceManager.substituteTypeArgum entsInMemberFromInheritance(elt.type, executableElt.name, enclosingType); 19432 FunctionType foundConcreteFT = _inheritanceManager.substituteTypeArgum entsInMemberFromInheritance(elt.type, executableElt.name, enclosingType);
18391 FunctionType requiredMemberFT = _inheritanceManager.substituteTypeArgu mentsInMemberFromInheritance(executableElt.type, executableElt.name, enclosingTy pe); 19433 FunctionType requiredMemberFT = _inheritanceManager.substituteTypeArgu mentsInMemberFromInheritance(executableElt.type, executableElt.name, enclosingTy pe);
18392 if (foundConcreteFT.isSubtypeOf(requiredMemberFT)) { 19434 if (foundConcreteFT.isSubtypeOf(requiredMemberFT)) {
18393 continue; 19435 continue;
18394 } 19436 }
18395 } 19437 }
18396 } 19438 }
19439 // The not qualifying concrete executable element was found, add it to the list.
18397 missingOverrides.add(executableElt); 19440 missingOverrides.add(executableElt);
18398 } 19441 }
19442 // Now that we have the set of missing overrides, generate a warning on this class
18399 int missingOverridesSize = missingOverrides.length; 19443 int missingOverridesSize = missingOverrides.length;
18400 if (missingOverridesSize == 0) { 19444 if (missingOverridesSize == 0) {
18401 return false; 19445 return false;
18402 } 19446 }
18403 List<ExecutableElement> missingOverridesArray = new List.from(missingOverrid es); 19447 List<ExecutableElement> missingOverridesArray = new List.from(missingOverrid es);
18404 List<String> stringMembersArrayListSet = new List<String>(); 19448 List<String> stringMembersArrayListSet = new List<String>();
18405 for (int i = 0; i < missingOverridesArray.length; i++) { 19449 for (int i = 0; i < missingOverridesArray.length; i++) {
18406 String newStrMember = "${missingOverridesArray[i].enclosingElement.display Name}.${missingOverridesArray[i].displayName}"; 19450 String newStrMember = "${missingOverridesArray[i].enclosingElement.display Name}.${missingOverridesArray[i].displayName}";
18407 if (!stringMembersArrayListSet.contains(newStrMember)) { 19451 if (!stringMembersArrayListSet.contains(newStrMember)) {
18408 stringMembersArrayListSet.add(newStrMember); 19452 stringMembersArrayListSet.add(newStrMember);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
18502 * * has `const modifier` 19546 * * has `const modifier`
18503 * * has explicit type arguments 19547 * * has explicit type arguments
18504 * * is not start of the statement 19548 * * is not start of the statement
18505 * 19549 *
18506 * 19550 *
18507 * @param node the map literal to evaluate 19551 * @param node the map literal to evaluate
18508 * @return `true` if and only if an error code is generated on the passed node 19552 * @return `true` if and only if an error code is generated on the passed node
18509 * @see CompileTimeErrorCode#NON_CONST_MAP_AS_EXPRESSION_STATEMENT 19553 * @see CompileTimeErrorCode#NON_CONST_MAP_AS_EXPRESSION_STATEMENT
18510 */ 19554 */
18511 bool checkForNonConstMapAsExpressionStatement(MapLiteral node) { 19555 bool checkForNonConstMapAsExpressionStatement(MapLiteral node) {
19556 // "const"
18512 if (node.constKeyword != null) { 19557 if (node.constKeyword != null) {
18513 return false; 19558 return false;
18514 } 19559 }
19560 // has type arguments
18515 if (node.typeArguments != null) { 19561 if (node.typeArguments != null) {
18516 return false; 19562 return false;
18517 } 19563 }
19564 // prepare statement
18518 Statement statement = node.getAncestor(ExpressionStatement); 19565 Statement statement = node.getAncestor(ExpressionStatement);
18519 if (statement == null) { 19566 if (statement == null) {
18520 return false; 19567 return false;
18521 } 19568 }
19569 // OK, statement does not start with map
18522 if (statement.beginToken != node.beginToken) { 19570 if (statement.beginToken != node.beginToken) {
18523 return false; 19571 return false;
18524 } 19572 }
19573 // report problem
18525 _errorReporter.reportError3(CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION _STATEMENT, node, []); 19574 _errorReporter.reportError3(CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION _STATEMENT, node, []);
18526 return true; 19575 return true;
18527 } 19576 }
18528 19577
18529 /** 19578 /**
18530 * This verifies the passed method declaration of operator `[]=`, has `void` r eturn 19579 * This verifies the passed method declaration of operator `[]=`, has `void` r eturn
18531 * type. 19580 * type.
18532 * 19581 *
18533 * @param node the method declaration to evaluate 19582 * @param node the method declaration to evaluate
18534 * @return `true` if and only if an error code is generated on the passed node 19583 * @return `true` if and only if an error code is generated on the passed node
18535 * @see StaticWarningCode#NON_VOID_RETURN_FOR_OPERATOR 19584 * @see StaticWarningCode#NON_VOID_RETURN_FOR_OPERATOR
18536 */ 19585 */
18537 bool checkForNonVoidReturnTypeForOperator(MethodDeclaration node) { 19586 bool checkForNonVoidReturnTypeForOperator(MethodDeclaration node) {
19587 // check that []= operator
18538 SimpleIdentifier name = node.name; 19588 SimpleIdentifier name = node.name;
18539 if (name.name != "[]=") { 19589 if (name.name != "[]=") {
18540 return false; 19590 return false;
18541 } 19591 }
19592 // check return type
18542 TypeName typeName = node.returnType; 19593 TypeName typeName = node.returnType;
18543 if (typeName != null) { 19594 if (typeName != null) {
18544 Type2 type = typeName.type; 19595 Type2 type = typeName.type;
18545 if (type != null && !type.isVoid) { 19596 if (type != null && !type.isVoid) {
18546 _errorReporter.reportError3(StaticWarningCode.NON_VOID_RETURN_FOR_OPERAT OR, typeName, []); 19597 _errorReporter.reportError3(StaticWarningCode.NON_VOID_RETURN_FOR_OPERAT OR, typeName, []);
18547 } 19598 }
18548 } 19599 }
19600 // no warning
18549 return false; 19601 return false;
18550 } 19602 }
18551 19603
18552 /** 19604 /**
18553 * This verifies the passed setter has no return type or the `void` return typ e. 19605 * This verifies the passed setter has no return type or the `void` return typ e.
18554 * 19606 *
18555 * @param typeName the type name to evaluate 19607 * @param typeName the type name to evaluate
18556 * @return `true` if and only if an error code is generated on the passed node 19608 * @return `true` if and only if an error code is generated on the passed node
18557 * @see StaticWarningCode#NON_VOID_RETURN_FOR_SETTER 19609 * @see StaticWarningCode#NON_VOID_RETURN_FOR_SETTER
18558 */ 19610 */
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
18593 } 19645 }
18594 19646
18595 /** 19647 /**
18596 * This checks for named optional parameters that begin with '_'. 19648 * This checks for named optional parameters that begin with '_'.
18597 * 19649 *
18598 * @param node the default formal parameter to evaluate 19650 * @param node the default formal parameter to evaluate
18599 * @return `true` if and only if an error code is generated on the passed node 19651 * @return `true` if and only if an error code is generated on the passed node
18600 * @see CompileTimeErrorCode#PRIVATE_OPTIONAL_PARAMETER 19652 * @see CompileTimeErrorCode#PRIVATE_OPTIONAL_PARAMETER
18601 */ 19653 */
18602 bool checkForPrivateOptionalParameter(FormalParameter node) { 19654 bool checkForPrivateOptionalParameter(FormalParameter node) {
19655 // should be named parameter
18603 if (node.kind != ParameterKind.NAMED) { 19656 if (node.kind != ParameterKind.NAMED) {
18604 return false; 19657 return false;
18605 } 19658 }
19659 // name should start with '_'
18606 SimpleIdentifier name = node.identifier; 19660 SimpleIdentifier name = node.identifier;
18607 if (name.isSynthetic || !name.name.startsWith("_")) { 19661 if (name.isSynthetic || !name.name.startsWith("_")) {
18608 return false; 19662 return false;
18609 } 19663 }
19664 // report problem
18610 _errorReporter.reportError3(CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, node, []); 19665 _errorReporter.reportError3(CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, node, []);
18611 return true; 19666 return true;
18612 } 19667 }
18613 19668
18614 /** 19669 /**
18615 * This checks if the passed constructor declaration is the redirecting genera tive constructor and 19670 * This checks if the passed constructor declaration is the redirecting genera tive constructor and
18616 * references itself directly or indirectly. 19671 * references itself directly or indirectly.
18617 * 19672 *
18618 * @param node the constructor declaration to evaluate 19673 * @param node the constructor declaration to evaluate
18619 * @return `true` if and only if an error code is generated on the passed node 19674 * @return `true` if and only if an error code is generated on the passed node
18620 * @see CompileTimeErrorCode#RECURSIVE_CONSTRUCTOR_REDIRECT 19675 * @see CompileTimeErrorCode#RECURSIVE_CONSTRUCTOR_REDIRECT
18621 */ 19676 */
18622 bool checkForRecursiveConstructorRedirect(ConstructorDeclaration node) { 19677 bool checkForRecursiveConstructorRedirect(ConstructorDeclaration node) {
19678 // we check generative constructor here
18623 if (node.factoryKeyword != null) { 19679 if (node.factoryKeyword != null) {
18624 return false; 19680 return false;
18625 } 19681 }
19682 // try to find redirecting constructor invocation and analyzer it for recurs ion
18626 for (ConstructorInitializer initializer in node.initializers) { 19683 for (ConstructorInitializer initializer in node.initializers) {
18627 if (initializer is RedirectingConstructorInvocation) { 19684 if (initializer is RedirectingConstructorInvocation) {
19685 // OK if no cycle
18628 ConstructorElement element = node.element; 19686 ConstructorElement element = node.element;
18629 if (!hasRedirectingFactoryConstructorCycle(element)) { 19687 if (!hasRedirectingFactoryConstructorCycle(element)) {
18630 return false; 19688 return false;
18631 } 19689 }
19690 // report error
18632 _errorReporter.reportError3(CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_R EDIRECT, initializer, []); 19691 _errorReporter.reportError3(CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_R EDIRECT, initializer, []);
18633 return true; 19692 return true;
18634 } 19693 }
18635 } 19694 }
19695 // OK, no redirecting constructor invocation
18636 return false; 19696 return false;
18637 } 19697 }
18638 19698
18639 /** 19699 /**
18640 * This checks if the passed constructor declaration has redirected constructo r and references 19700 * This checks if the passed constructor declaration has redirected constructo r and references
18641 * itself directly or indirectly. 19701 * itself directly or indirectly.
18642 * 19702 *
18643 * @param node the constructor declaration to evaluate 19703 * @param node the constructor declaration to evaluate
18644 * @return `true` if and only if an error code is generated on the passed node 19704 * @return `true` if and only if an error code is generated on the passed node
18645 * @see CompileTimeErrorCode#RECURSIVE_FACTORY_REDIRECT 19705 * @see CompileTimeErrorCode#RECURSIVE_FACTORY_REDIRECT
18646 */ 19706 */
18647 bool checkForRecursiveFactoryRedirect(ConstructorDeclaration node) { 19707 bool checkForRecursiveFactoryRedirect(ConstructorDeclaration node) {
19708 // prepare redirected constructor
18648 ConstructorName redirectedConstructorNode = node.redirectedConstructor; 19709 ConstructorName redirectedConstructorNode = node.redirectedConstructor;
18649 if (redirectedConstructorNode == null) { 19710 if (redirectedConstructorNode == null) {
18650 return false; 19711 return false;
18651 } 19712 }
19713 // OK if no cycle
18652 ConstructorElement element = node.element; 19714 ConstructorElement element = node.element;
18653 if (!hasRedirectingFactoryConstructorCycle(element)) { 19715 if (!hasRedirectingFactoryConstructorCycle(element)) {
18654 return false; 19716 return false;
18655 } 19717 }
19718 // report error
18656 _errorReporter.reportError3(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, redirectedConstructorNode, []); 19719 _errorReporter.reportError3(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, redirectedConstructorNode, []);
18657 return true; 19720 return true;
18658 } 19721 }
18659 19722
18660 /** 19723 /**
18661 * This checks the class declaration is not a superinterface to itself. 19724 * This checks the class declaration is not a superinterface to itself.
18662 * 19725 *
18663 * @param classElt the class element to test 19726 * @param classElt the class element to test
18664 * @return `true` if and only if an error code is generated on the passed elem ent 19727 * @return `true` if and only if an error code is generated on the passed elem ent
18665 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE 19728 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE
(...skipping 11 matching lines...) Expand all
18677 * This checks the class declaration is not a superinterface to itself. 19740 * This checks the class declaration is not a superinterface to itself.
18678 * 19741 *
18679 * @param classElt the class element to test 19742 * @param classElt the class element to test
18680 * @param path a list containing the potentially cyclic implements path 19743 * @param path a list containing the potentially cyclic implements path
18681 * @return `true` if and only if an error code is generated on the passed elem ent 19744 * @return `true` if and only if an error code is generated on the passed elem ent
18682 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE 19745 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE
18683 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS 19746 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS
18684 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEME NTS 19747 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEME NTS
18685 */ 19748 */
18686 bool checkForRecursiveInterfaceInheritance2(ClassElement classElt, List<ClassE lement> path) { 19749 bool checkForRecursiveInterfaceInheritance2(ClassElement classElt, List<ClassE lement> path) {
19750 // Detect error condition.
18687 int size = path.length; 19751 int size = path.length;
19752 // If this is not the base case (size > 0), and the enclosing class is the p assed class
19753 // element then an error an error.
18688 if (size > 0 && _enclosingClass == classElt) { 19754 if (size > 0 && _enclosingClass == classElt) {
18689 String enclosingClassName = _enclosingClass.displayName; 19755 String enclosingClassName = _enclosingClass.displayName;
18690 if (size > 1) { 19756 if (size > 1) {
19757 // Construct a string showing the cyclic implements path: "A, B, C, D, A "
18691 String separator = ", "; 19758 String separator = ", ";
18692 JavaStringBuilder builder = new JavaStringBuilder(); 19759 JavaStringBuilder builder = new JavaStringBuilder();
18693 for (int i = 0; i < size; i++) { 19760 for (int i = 0; i < size; i++) {
18694 builder.append(path[i].displayName); 19761 builder.append(path[i].displayName);
18695 builder.append(separator); 19762 builder.append(separator);
18696 } 19763 }
18697 builder.append(classElt.displayName); 19764 builder.append(classElt.displayName);
18698 _errorReporter.reportError5(CompileTimeErrorCode.RECURSIVE_INTERFACE_INH ERITANCE, _enclosingClass.nameOffset, enclosingClassName.length, [enclosingClass Name, builder.toString()]); 19765 _errorReporter.reportError5(CompileTimeErrorCode.RECURSIVE_INTERFACE_INH ERITANCE, _enclosingClass.nameOffset, enclosingClassName.length, [enclosingClass Name, builder.toString()]);
18699 return true; 19766 return true;
18700 } else { 19767 } else {
19768 // RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS or RECURSIVE_INT ERFACE_INHERITANCE_BASE_CASE_EXTENDS
18701 InterfaceType supertype = classElt.supertype; 19769 InterfaceType supertype = classElt.supertype;
18702 ErrorCode errorCode = (supertype != null && _enclosingClass == supertype .element ? CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTEND S : CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS); 19770 ErrorCode errorCode = (supertype != null && _enclosingClass == supertype .element ? CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTEND S : CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS);
18703 _errorReporter.reportError5(errorCode, _enclosingClass.nameOffset, enclo singClassName.length, [enclosingClassName]); 19771 _errorReporter.reportError5(errorCode, _enclosingClass.nameOffset, enclo singClassName.length, [enclosingClassName]);
18704 return true; 19772 return true;
18705 } 19773 }
18706 } 19774 }
18707 if (path.indexOf(classElt) > 0) { 19775 if (path.indexOf(classElt) > 0) {
18708 return false; 19776 return false;
18709 } 19777 }
18710 path.add(classElt); 19778 path.add(classElt);
19779 // n-case
18711 InterfaceType supertype = classElt.supertype; 19780 InterfaceType supertype = classElt.supertype;
18712 if (supertype != null && checkForRecursiveInterfaceInheritance2(supertype.el ement, path)) { 19781 if (supertype != null && checkForRecursiveInterfaceInheritance2(supertype.el ement, path)) {
18713 return true; 19782 return true;
18714 } 19783 }
18715 List<InterfaceType> interfaceTypes = classElt.interfaces; 19784 List<InterfaceType> interfaceTypes = classElt.interfaces;
18716 for (InterfaceType interfaceType in interfaceTypes) { 19785 for (InterfaceType interfaceType in interfaceTypes) {
18717 if (checkForRecursiveInterfaceInheritance2(interfaceType.element, path)) { 19786 if (checkForRecursiveInterfaceInheritance2(interfaceType.element, path)) {
18718 return true; 19787 return true;
18719 } 19788 }
18720 } 19789 }
18721 path.removeAt(path.length - 1); 19790 path.removeAt(path.length - 1);
18722 return false; 19791 return false;
18723 } 19792 }
18724 19793
18725 /** 19794 /**
18726 * This checks the passed constructor declaration has a valid combination of r edirected 19795 * This checks the passed constructor declaration has a valid combination of r edirected
18727 * constructor invocation(s), super constructor invocations and field initiali zers. 19796 * constructor invocation(s), super constructor invocations and field initiali zers.
18728 * 19797 *
18729 * @param node the constructor declaration to evaluate 19798 * @param node the constructor declaration to evaluate
18730 * @return `true` if and only if an error code is generated on the passed node 19799 * @return `true` if and only if an error code is generated on the passed node
18731 * @see CompileTimeErrorCode#DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR 19800 * @see CompileTimeErrorCode#DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR
18732 * @see CompileTimeErrorCode#FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR 19801 * @see CompileTimeErrorCode#FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR
18733 * @see CompileTimeErrorCode#MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS 19802 * @see CompileTimeErrorCode#MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS
18734 * @see CompileTimeErrorCode#SUPER_IN_REDIRECTING_CONSTRUCTOR 19803 * @see CompileTimeErrorCode#SUPER_IN_REDIRECTING_CONSTRUCTOR
18735 */ 19804 */
18736 bool checkForRedirectingConstructorErrorCodes(ConstructorDeclaration node) { 19805 bool checkForRedirectingConstructorErrorCodes(ConstructorDeclaration node) {
18737 bool errorReported = false; 19806 bool errorReported = false;
19807 //
19808 // Check for default values in the parameters
19809 //
18738 ConstructorName redirectedConstructor = node.redirectedConstructor; 19810 ConstructorName redirectedConstructor = node.redirectedConstructor;
18739 if (redirectedConstructor != null) { 19811 if (redirectedConstructor != null) {
18740 for (FormalParameter parameter in node.parameters.parameters) { 19812 for (FormalParameter parameter in node.parameters.parameters) {
18741 if (parameter is DefaultFormalParameter && parameter.defaultValue != nul l) { 19813 if (parameter is DefaultFormalParameter && parameter.defaultValue != nul l) {
18742 _errorReporter.reportError3(CompileTimeErrorCode.DEFAULT_VALUE_IN_REDI RECTING_FACTORY_CONSTRUCTOR, parameter.identifier, []); 19814 _errorReporter.reportError3(CompileTimeErrorCode.DEFAULT_VALUE_IN_REDI RECTING_FACTORY_CONSTRUCTOR, parameter.identifier, []);
18743 errorReported = true; 19815 errorReported = true;
18744 } 19816 }
18745 } 19817 }
18746 } 19818 }
19819 // check if there are redirected invocations
18747 int numRedirections = 0; 19820 int numRedirections = 0;
18748 for (ConstructorInitializer initializer in node.initializers) { 19821 for (ConstructorInitializer initializer in node.initializers) {
18749 if (initializer is RedirectingConstructorInvocation) { 19822 if (initializer is RedirectingConstructorInvocation) {
18750 if (numRedirections > 0) { 19823 if (numRedirections > 0) {
18751 _errorReporter.reportError3(CompileTimeErrorCode.MULTIPLE_REDIRECTING_ CONSTRUCTOR_INVOCATIONS, initializer, []); 19824 _errorReporter.reportError3(CompileTimeErrorCode.MULTIPLE_REDIRECTING_ CONSTRUCTOR_INVOCATIONS, initializer, []);
18752 errorReported = true; 19825 errorReported = true;
18753 } 19826 }
18754 numRedirections++; 19827 numRedirections++;
18755 } 19828 }
18756 } 19829 }
19830 // check for other initializers
18757 if (numRedirections > 0) { 19831 if (numRedirections > 0) {
18758 for (ConstructorInitializer initializer in node.initializers) { 19832 for (ConstructorInitializer initializer in node.initializers) {
18759 if (initializer is SuperConstructorInvocation) { 19833 if (initializer is SuperConstructorInvocation) {
18760 _errorReporter.reportError3(CompileTimeErrorCode.SUPER_IN_REDIRECTING_ CONSTRUCTOR, initializer, []); 19834 _errorReporter.reportError3(CompileTimeErrorCode.SUPER_IN_REDIRECTING_ CONSTRUCTOR, initializer, []);
18761 errorReported = true; 19835 errorReported = true;
18762 } 19836 }
18763 if (initializer is ConstructorFieldInitializer) { 19837 if (initializer is ConstructorFieldInitializer) {
18764 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZER_RED IRECTING_CONSTRUCTOR, initializer, []); 19838 _errorReporter.reportError3(CompileTimeErrorCode.FIELD_INITIALIZER_RED IRECTING_CONSTRUCTOR, initializer, []);
18765 errorReported = true; 19839 errorReported = true;
18766 } 19840 }
18767 } 19841 }
18768 } 19842 }
19843 // done
18769 return errorReported; 19844 return errorReported;
18770 } 19845 }
18771 19846
18772 /** 19847 /**
18773 * This checks if the passed constructor declaration has redirected constructo r and references 19848 * This checks if the passed constructor declaration has redirected constructo r and references
18774 * itself directly or indirectly. 19849 * itself directly or indirectly.
18775 * 19850 *
18776 * @param node the constructor declaration to evaluate 19851 * @param node the constructor declaration to evaluate
18777 * @return `true` if and only if an error code is generated on the passed node 19852 * @return `true` if and only if an error code is generated on the passed node
18778 * @see CompileTimeErrorCode#REDIRECT_TO_NON_CONST_CONSTRUCTOR 19853 * @see CompileTimeErrorCode#REDIRECT_TO_NON_CONST_CONSTRUCTOR
18779 */ 19854 */
18780 bool checkForRedirectToNonConstConstructor(ConstructorDeclaration node) { 19855 bool checkForRedirectToNonConstConstructor(ConstructorDeclaration node) {
19856 // prepare redirected constructor
18781 ConstructorName redirectedConstructorNode = node.redirectedConstructor; 19857 ConstructorName redirectedConstructorNode = node.redirectedConstructor;
18782 if (redirectedConstructorNode == null) { 19858 if (redirectedConstructorNode == null) {
18783 return false; 19859 return false;
18784 } 19860 }
19861 // prepare element
18785 ConstructorElement element = node.element; 19862 ConstructorElement element = node.element;
18786 if (element == null) { 19863 if (element == null) {
18787 return false; 19864 return false;
18788 } 19865 }
19866 // OK, it is not 'const'
18789 if (!element.isConst) { 19867 if (!element.isConst) {
18790 return false; 19868 return false;
18791 } 19869 }
19870 // prepare redirected constructor
18792 ConstructorElement redirectedConstructor = element.redirectedConstructor; 19871 ConstructorElement redirectedConstructor = element.redirectedConstructor;
18793 if (redirectedConstructor == null) { 19872 if (redirectedConstructor == null) {
18794 return false; 19873 return false;
18795 } 19874 }
19875 // OK, it is also 'const'
18796 if (redirectedConstructor.isConst) { 19876 if (redirectedConstructor.isConst) {
18797 return false; 19877 return false;
18798 } 19878 }
19879 // report error
18799 _errorReporter.reportError3(CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONST RUCTOR, redirectedConstructorNode, []); 19880 _errorReporter.reportError3(CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONST RUCTOR, redirectedConstructorNode, []);
18800 return true; 19881 return true;
18801 } 19882 }
18802 19883
18803 /** 19884 /**
18804 * This checks that the rethrow is inside of a catch clause. 19885 * This checks that the rethrow is inside of a catch clause.
18805 * 19886 *
18806 * @param node the rethrow expression to evaluate 19887 * @param node the rethrow expression to evaluate
18807 * @return `true` if and only if an error code is generated on the passed node 19888 * @return `true` if and only if an error code is generated on the passed node
18808 * @see CompileTimeErrorCode#RETHROW_OUTSIDE_CATCH 19889 * @see CompileTimeErrorCode#RETHROW_OUTSIDE_CATCH
18809 */ 19890 */
18810 bool checkForRethrowOutsideCatch(RethrowExpression node) { 19891 bool checkForRethrowOutsideCatch(RethrowExpression node) {
18811 if (!_isInCatchClause) { 19892 if (!_isInCatchClause) {
18812 _errorReporter.reportError3(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, no de, []); 19893 _errorReporter.reportError3(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, no de, []);
18813 return true; 19894 return true;
18814 } 19895 }
18815 return false; 19896 return false;
18816 } 19897 }
18817 19898
18818 /** 19899 /**
18819 * This checks that if the the given constructor declaration is generative, th en it does not have 19900 * This checks that if the the given constructor declaration is generative, th en it does not have
18820 * an expression function body. 19901 * an expression function body.
18821 * 19902 *
18822 * @param node the constructor to evaluate 19903 * @param node the constructor to evaluate
18823 * @return `true` if and only if an error code is generated on the passed node 19904 * @return `true` if and only if an error code is generated on the passed node
18824 * @see CompileTimeErrorCode#RETURN_IN_GENERATIVE_CONSTRUCTOR 19905 * @see CompileTimeErrorCode#RETURN_IN_GENERATIVE_CONSTRUCTOR
18825 */ 19906 */
18826 bool checkForReturnInGenerativeConstructor(ConstructorDeclaration node) { 19907 bool checkForReturnInGenerativeConstructor(ConstructorDeclaration node) {
19908 // ignore factory
18827 if (node.factoryKeyword != null) { 19909 if (node.factoryKeyword != null) {
18828 return false; 19910 return false;
18829 } 19911 }
19912 // block body (with possible return statement) is checked elsewhere
18830 FunctionBody body = node.body; 19913 FunctionBody body = node.body;
18831 if (body is! ExpressionFunctionBody) { 19914 if (body is! ExpressionFunctionBody) {
18832 return false; 19915 return false;
18833 } 19916 }
19917 // report error
18834 _errorReporter.reportError3(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTR UCTOR, body, []); 19918 _errorReporter.reportError3(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTR UCTOR, body, []);
18835 return true; 19919 return true;
18836 } 19920 }
18837 19921
18838 /** 19922 /**
18839 * This checks that a type mis-match between the return type and the expressed return type by the 19923 * This checks that a type mis-match between the return type and the expressed return type by the
18840 * enclosing method or function. 19924 * enclosing method or function.
18841 * 19925 *
18842 * This method is called both by [checkForAllReturnStatementErrorCodes] 19926 * This method is called both by [checkForAllReturnStatementErrorCodes]
18843 * and [visitExpressionFunctionBody]. 19927 * and [visitExpressionFunctionBody].
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
18875 * member. 19959 * member.
18876 * 19960 *
18877 * @param typeReference the resolved [ClassElement] of the left hand side of t he expression, 19961 * @param typeReference the resolved [ClassElement] of the left hand side of t he expression,
18878 * or `null`, aka, the class element of 'C' in 'C.x', see 19962 * or `null`, aka, the class element of 'C' in 'C.x', see
18879 * [getTypeReference] 19963 * [getTypeReference]
18880 * @param name the accessed name to evaluate 19964 * @param name the accessed name to evaluate
18881 * @return `true` if and only if an error code is generated on the passed node 19965 * @return `true` if and only if an error code is generated on the passed node
18882 * @see StaticWarningCode#STATIC_ACCESS_TO_INSTANCE_MEMBER 19966 * @see StaticWarningCode#STATIC_ACCESS_TO_INSTANCE_MEMBER
18883 */ 19967 */
18884 bool checkForStaticAccessToInstanceMember(ClassElement typeReference, SimpleId entifier name) { 19968 bool checkForStaticAccessToInstanceMember(ClassElement typeReference, SimpleId entifier name) {
19969 // OK, target is not a type
18885 if (typeReference == null) { 19970 if (typeReference == null) {
18886 return false; 19971 return false;
18887 } 19972 }
19973 // prepare member Element
18888 Element element = name.staticElement; 19974 Element element = name.staticElement;
18889 if (element is! ExecutableElement) { 19975 if (element is! ExecutableElement) {
18890 return false; 19976 return false;
18891 } 19977 }
18892 ExecutableElement memberElement = element as ExecutableElement; 19978 ExecutableElement memberElement = element as ExecutableElement;
19979 // OK, static
18893 if (memberElement.isStatic) { 19980 if (memberElement.isStatic) {
18894 return false; 19981 return false;
18895 } 19982 }
19983 // report problem
18896 _errorReporter.reportError3(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMB ER, name, [name.name]); 19984 _errorReporter.reportError3(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMB ER, name, [name.name]);
18897 return true; 19985 return true;
18898 } 19986 }
18899 19987
18900 /** 19988 /**
18901 * This checks that the type of the passed 'switch' expression is assignable t o the type of the 19989 * This checks that the type of the passed 'switch' expression is assignable t o the type of the
18902 * 'case' members. 19990 * 'case' members.
18903 * 19991 *
18904 * @param node the 'switch' statement to evaluate 19992 * @param node the 'switch' statement to evaluate
18905 * @return `true` if and only if an error code is generated on the passed node 19993 * @return `true` if and only if an error code is generated on the passed node
18906 * @see StaticWarningCode#SWITCH_EXPRESSION_NOT_ASSIGNABLE 19994 * @see StaticWarningCode#SWITCH_EXPRESSION_NOT_ASSIGNABLE
18907 */ 19995 */
18908 bool checkForSwitchExpressionNotAssignable(SwitchStatement node) { 19996 bool checkForSwitchExpressionNotAssignable(SwitchStatement node) {
19997 // prepare 'switch' expression type
18909 Expression expression = node.expression; 19998 Expression expression = node.expression;
18910 Type2 expressionType = getStaticType(expression); 19999 Type2 expressionType = getStaticType(expression);
18911 if (expressionType == null) { 20000 if (expressionType == null) {
18912 return false; 20001 return false;
18913 } 20002 }
20003 // compare with type of the first 'case'
18914 NodeList<SwitchMember> members = node.members; 20004 NodeList<SwitchMember> members = node.members;
18915 for (SwitchMember switchMember in members) { 20005 for (SwitchMember switchMember in members) {
18916 if (switchMember is! SwitchCase) { 20006 if (switchMember is! SwitchCase) {
18917 continue; 20007 continue;
18918 } 20008 }
18919 SwitchCase switchCase = switchMember as SwitchCase; 20009 SwitchCase switchCase = switchMember as SwitchCase;
20010 // prepare 'case' type
18920 Expression caseExpression = switchCase.expression; 20011 Expression caseExpression = switchCase.expression;
18921 Type2 caseType = getStaticType(caseExpression); 20012 Type2 caseType = getStaticType(caseExpression);
20013 // check types
18922 if (expressionType.isAssignableTo(caseType)) { 20014 if (expressionType.isAssignableTo(caseType)) {
18923 return false; 20015 return false;
18924 } 20016 }
20017 // report problem
18925 _errorReporter.reportError3(StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGN ABLE, expression, [expressionType, caseType]); 20018 _errorReporter.reportError3(StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGN ABLE, expression, [expressionType, caseType]);
18926 return true; 20019 return true;
18927 } 20020 }
18928 return false; 20021 return false;
18929 } 20022 }
18930 20023
18931 /** 20024 /**
18932 * This verifies that the passed function type alias does not reference itself directly. 20025 * This verifies that the passed function type alias does not reference itself directly.
18933 * 20026 *
18934 * @param node the function type alias to evaluate 20027 * @param node the function type alias to evaluate
(...skipping 28 matching lines...) Expand all
18963 * This verifies that the type arguments in the passed type name are all withi n their bounds. 20056 * This verifies that the type arguments in the passed type name are all withi n their bounds.
18964 * 20057 *
18965 * @param node the [TypeName] to evaluate 20058 * @param node the [TypeName] to evaluate
18966 * @return `true` if and only if an error code is generated on the passed node 20059 * @return `true` if and only if an error code is generated on the passed node
18967 * @see StaticTypeWarningCode#TYPE_ARGUMENT_NOT_MATCHING_BOUNDS 20060 * @see StaticTypeWarningCode#TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
18968 */ 20061 */
18969 bool checkForTypeArgumentNotMatchingBounds(TypeName node) { 20062 bool checkForTypeArgumentNotMatchingBounds(TypeName node) {
18970 if (node.typeArguments == null) { 20063 if (node.typeArguments == null) {
18971 return false; 20064 return false;
18972 } 20065 }
20066 // prepare Type
18973 Type2 type = node.type; 20067 Type2 type = node.type;
18974 if (type == null) { 20068 if (type == null) {
18975 return false; 20069 return false;
18976 } 20070 }
20071 // prepare ClassElement
18977 Element element = type.element; 20072 Element element = type.element;
18978 if (element is! ClassElement) { 20073 if (element is! ClassElement) {
18979 return false; 20074 return false;
18980 } 20075 }
18981 ClassElement classElement = element as ClassElement; 20076 ClassElement classElement = element as ClassElement;
20077 // prepare type parameters
18982 List<Type2> typeParameters = classElement.type.typeArguments; 20078 List<Type2> typeParameters = classElement.type.typeArguments;
18983 List<TypeParameterElement> boundingElts = classElement.typeParameters; 20079 List<TypeParameterElement> boundingElts = classElement.typeParameters;
20080 // iterate over each bounded type parameter and corresponding argument
18984 NodeList<TypeName> typeNameArgList = node.typeArguments.arguments; 20081 NodeList<TypeName> typeNameArgList = node.typeArguments.arguments;
18985 List<Type2> typeArguments = (type as InterfaceType).typeArguments; 20082 List<Type2> typeArguments = (type as InterfaceType).typeArguments;
18986 int loopThroughIndex = Math.min(typeNameArgList.length, boundingElts.length) ; 20083 int loopThroughIndex = Math.min(typeNameArgList.length, boundingElts.length) ;
18987 bool foundError = false; 20084 bool foundError = false;
18988 for (int i = 0; i < loopThroughIndex; i++) { 20085 for (int i = 0; i < loopThroughIndex; i++) {
18989 TypeName argTypeName = typeNameArgList[i]; 20086 TypeName argTypeName = typeNameArgList[i];
18990 Type2 argType = argTypeName.type; 20087 Type2 argType = argTypeName.type;
18991 Type2 boundType = boundingElts[i].bound; 20088 Type2 boundType = boundingElts[i].bound;
18992 if (argType != null && boundType != null) { 20089 if (argType != null && boundType != null) {
18993 boundType = boundType.substitute2(typeArguments, typeParameters); 20090 boundType = boundType.substitute2(typeArguments, typeParameters);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
19027 20124
19028 /** 20125 /**
19029 * This checks that if the passed type parameter is a supertype of its bound. 20126 * This checks that if the passed type parameter is a supertype of its bound.
19030 * 20127 *
19031 * @param node the type parameter to evaluate 20128 * @param node the type parameter to evaluate
19032 * @return `true` if and only if an error code is generated on the passed node 20129 * @return `true` if and only if an error code is generated on the passed node
19033 * @see StaticTypeWarningCode#TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND 20130 * @see StaticTypeWarningCode#TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND
19034 */ 20131 */
19035 bool checkForTypeParameterSupertypeOfItsBound(TypeParameter node) { 20132 bool checkForTypeParameterSupertypeOfItsBound(TypeParameter node) {
19036 TypeParameterElement element = node.element; 20133 TypeParameterElement element = node.element;
20134 // prepare bound
19037 Type2 bound = element.bound; 20135 Type2 bound = element.bound;
19038 if (bound == null) { 20136 if (bound == null) {
19039 return false; 20137 return false;
19040 } 20138 }
20139 // OK, type parameter is not supertype of its bound
19041 if (!bound.isMoreSpecificThan(element.type)) { 20140 if (!bound.isMoreSpecificThan(element.type)) {
19042 return false; 20141 return false;
19043 } 20142 }
20143 // report problem
19044 _errorReporter.reportError3(StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_O F_ITS_BOUND, node, [element.displayName]); 20144 _errorReporter.reportError3(StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_O F_ITS_BOUND, node, [element.displayName]);
19045 return true; 20145 return true;
19046 } 20146 }
19047 20147
19048 /** 20148 /**
19049 * This checks that if the passed generative constructor has neither an explic it super constructor 20149 * This checks that if the passed generative constructor has neither an explic it super constructor
19050 * invocation nor a redirecting constructor invocation, that the superclass ha s a default 20150 * invocation nor a redirecting constructor invocation, that the superclass ha s a default
19051 * generative constructor. 20151 * generative constructor.
19052 * 20152 *
19053 * @param node the constructor declaration to evaluate 20153 * @param node the constructor declaration to evaluate
19054 * @return `true` if and only if an error code is generated on the passed node 20154 * @return `true` if and only if an error code is generated on the passed node
19055 * @see CompileTimeErrorCode#UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT 20155 * @see CompileTimeErrorCode#UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
19056 * @see CompileTimeErrorCode#NON_GENERATIVE_CONSTRUCTOR 20156 * @see CompileTimeErrorCode#NON_GENERATIVE_CONSTRUCTOR
19057 * @see StaticWarningCode#NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT 20157 * @see StaticWarningCode#NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT
19058 */ 20158 */
19059 bool checkForUndefinedConstructorInInitializerImplicit(ConstructorDeclaration node) { 20159 bool checkForUndefinedConstructorInInitializerImplicit(ConstructorDeclaration node) {
20160 //
20161 // Ignore if the constructor is not generative.
20162 //
19060 if (node.factoryKeyword != null) { 20163 if (node.factoryKeyword != null) {
19061 return false; 20164 return false;
19062 } 20165 }
20166 //
20167 // Ignore if the constructor has either an implicit super constructor invoca tion or a
20168 // redirecting constructor invocation.
20169 //
19063 for (ConstructorInitializer constructorInitializer in node.initializers) { 20170 for (ConstructorInitializer constructorInitializer in node.initializers) {
19064 if (constructorInitializer is SuperConstructorInvocation || constructorIni tializer is RedirectingConstructorInvocation) { 20171 if (constructorInitializer is SuperConstructorInvocation || constructorIni tializer is RedirectingConstructorInvocation) {
19065 return false; 20172 return false;
19066 } 20173 }
19067 } 20174 }
20175 //
20176 // Check to see whether the superclass has a non-factory unnamed constructor .
20177 //
19068 if (_enclosingClass == null) { 20178 if (_enclosingClass == null) {
19069 return false; 20179 return false;
19070 } 20180 }
19071 InterfaceType superType = _enclosingClass.supertype; 20181 InterfaceType superType = _enclosingClass.supertype;
19072 if (superType == null) { 20182 if (superType == null) {
19073 return false; 20183 return false;
19074 } 20184 }
19075 ClassElement superElement = superType.element; 20185 ClassElement superElement = superType.element;
19076 ConstructorElement superUnnamedConstructor = superElement.unnamedConstructor ; 20186 ConstructorElement superUnnamedConstructor = superElement.unnamedConstructor ;
19077 if (superUnnamedConstructor != null) { 20187 if (superUnnamedConstructor != null) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
19127 * This verifies the passed operator-method declaration, has correct number of parameters. 20237 * This verifies the passed operator-method declaration, has correct number of parameters.
19128 * 20238 *
19129 * This method assumes that the method declaration was tested to be an operato r declaration before 20239 * This method assumes that the method declaration was tested to be an operato r declaration before
19130 * being called. 20240 * being called.
19131 * 20241 *
19132 * @param node the method declaration to evaluate 20242 * @param node the method declaration to evaluate
19133 * @return `true` if and only if an error code is generated on the passed node 20243 * @return `true` if and only if an error code is generated on the passed node
19134 * @see CompileTimeErrorCode#WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR 20244 * @see CompileTimeErrorCode#WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
19135 */ 20245 */
19136 bool checkForWrongNumberOfParametersForOperator(MethodDeclaration node) { 20246 bool checkForWrongNumberOfParametersForOperator(MethodDeclaration node) {
20247 // prepare number of parameters
19137 FormalParameterList parameterList = node.parameters; 20248 FormalParameterList parameterList = node.parameters;
19138 if (parameterList == null) { 20249 if (parameterList == null) {
19139 return false; 20250 return false;
19140 } 20251 }
19141 int numParameters = parameterList.parameters.length; 20252 int numParameters = parameterList.parameters.length;
20253 // prepare operator name
19142 SimpleIdentifier nameNode = node.name; 20254 SimpleIdentifier nameNode = node.name;
19143 if (nameNode == null) { 20255 if (nameNode == null) {
19144 return false; 20256 return false;
19145 } 20257 }
19146 String name = nameNode.name; 20258 String name = nameNode.name;
20259 // check for exact number of parameters
19147 int expected = -1; 20260 int expected = -1;
19148 if ("[]=" == name) { 20261 if ("[]=" == name) {
19149 expected = 2; 20262 expected = 2;
19150 } else if ("<" == name || ">" == name || "<=" == name || ">=" == name || "== " == name || "+" == name || "/" == name || "~/" == name || "*" == name || "%" == name || "|" == name || "^" == name || "&" == name || "<<" == name || ">>" == na me || "[]" == name) { 20263 } else if ("<" == name || ">" == name || "<=" == name || ">=" == name || "== " == name || "+" == name || "/" == name || "~/" == name || "*" == name || "%" == name || "|" == name || "^" == name || "&" == name || "<<" == name || ">>" == na me || "[]" == name) {
19151 expected = 1; 20264 expected = 1;
19152 } else if ("~" == name) { 20265 } else if ("~" == name) {
19153 expected = 0; 20266 expected = 0;
19154 } 20267 }
19155 if (expected != -1 && numParameters != expected) { 20268 if (expected != -1 && numParameters != expected) {
19156 _errorReporter.reportError3(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETER S_FOR_OPERATOR, nameNode, [name, expected, numParameters]); 20269 _errorReporter.reportError3(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETER S_FOR_OPERATOR, nameNode, [name, expected, numParameters]);
19157 return true; 20270 return true;
19158 } 20271 }
20272 // check for operator "-"
19159 if ("-" == name && numParameters > 1) { 20273 if ("-" == name && numParameters > 1) {
19160 _errorReporter.reportError3(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETER S_FOR_OPERATOR_MINUS, nameNode, [numParameters]); 20274 _errorReporter.reportError3(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETER S_FOR_OPERATOR_MINUS, nameNode, [numParameters]);
19161 return true; 20275 return true;
19162 } 20276 }
20277 // OK
19163 return false; 20278 return false;
19164 } 20279 }
19165 20280
19166 /** 20281 /**
19167 * This verifies if the passed setter parameter list have only one required pa rameter. 20282 * This verifies if the passed setter parameter list have only one required pa rameter.
19168 * 20283 *
19169 * This method assumes that the method declaration was tested to be a setter b efore being called. 20284 * This method assumes that the method declaration was tested to be a setter b efore being called.
19170 * 20285 *
19171 * @param setterName the name of the setter to report problems on 20286 * @param setterName the name of the setter to report problems on
19172 * @param parameterList the parameter list to evaluate 20287 * @param parameterList the parameter list to evaluate
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
19215 } 20330 }
19216 20331
19217 /** 20332 /**
19218 * This verifies that the given class declaration does not have the same class in the 'extends' 20333 * This verifies that the given class declaration does not have the same class in the 'extends'
19219 * and 'implements' clauses. 20334 * and 'implements' clauses.
19220 * 20335 *
19221 * @return `true` if and only if an error code is generated on the passed node 20336 * @return `true` if and only if an error code is generated on the passed node
19222 * @see CompileTimeErrorCode#IMPLEMENTS_SUPER_CLASS 20337 * @see CompileTimeErrorCode#IMPLEMENTS_SUPER_CLASS
19223 */ 20338 */
19224 bool checkImplementsSuperClass(ClassDeclaration node) { 20339 bool checkImplementsSuperClass(ClassDeclaration node) {
20340 // prepare super type
19225 InterfaceType superType = _enclosingClass.supertype; 20341 InterfaceType superType = _enclosingClass.supertype;
19226 if (superType == null) { 20342 if (superType == null) {
19227 return false; 20343 return false;
19228 } 20344 }
20345 // prepare interfaces
19229 ImplementsClause implementsClause = node.implementsClause; 20346 ImplementsClause implementsClause = node.implementsClause;
19230 if (implementsClause == null) { 20347 if (implementsClause == null) {
19231 return false; 20348 return false;
19232 } 20349 }
20350 // check interfaces
19233 bool hasProblem = false; 20351 bool hasProblem = false;
19234 for (TypeName interfaceNode in implementsClause.interfaces) { 20352 for (TypeName interfaceNode in implementsClause.interfaces) {
19235 if (interfaceNode.type == superType) { 20353 if (interfaceNode.type == superType) {
19236 hasProblem = true; 20354 hasProblem = true;
19237 _errorReporter.reportError3(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, interfaceNode, [superType.displayName]); 20355 _errorReporter.reportError3(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, interfaceNode, [superType.displayName]);
19238 } 20356 }
19239 } 20357 }
20358 // done
19240 return hasProblem; 20359 return hasProblem;
19241 } 20360 }
19242 20361
19243 /** 20362 /**
19244 * Returns the Type (return type) for a given getter. 20363 * Returns the Type (return type) for a given getter.
19245 * 20364 *
19246 * @param propertyAccessorElement 20365 * @param propertyAccessorElement
19247 * @return The type of the given getter. 20366 * @return The type of the given getter.
19248 */ 20367 */
19249 Type2 getGetterType(PropertyAccessorElement propertyAccessorElement) { 20368 Type2 getGetterType(PropertyAccessorElement propertyAccessorElement) {
19250 FunctionType functionType = propertyAccessorElement.type; 20369 FunctionType functionType = propertyAccessorElement.type;
19251 if (functionType != null) { 20370 if (functionType != null) {
19252 return functionType.returnType; 20371 return functionType.returnType;
19253 } else { 20372 } else {
19254 return null; 20373 return null;
19255 } 20374 }
19256 } 20375 }
19257 20376
19258 /** 20377 /**
19259 * Returns the Type (first and only parameter) for a given setter. 20378 * Returns the Type (first and only parameter) for a given setter.
19260 * 20379 *
19261 * @param propertyAccessorElement 20380 * @param propertyAccessorElement
19262 * @return The type of the given setter. 20381 * @return The type of the given setter.
19263 */ 20382 */
19264 Type2 getSetterType(PropertyAccessorElement propertyAccessorElement) { 20383 Type2 getSetterType(PropertyAccessorElement propertyAccessorElement) {
20384 // Get the parameters for MethodDeclaration or FunctionDeclaration
19265 List<ParameterElement> setterParameters = propertyAccessorElement.parameters ; 20385 List<ParameterElement> setterParameters = propertyAccessorElement.parameters ;
20386 // If there are no setter parameters, return no type.
19266 if (setterParameters.length == 0) { 20387 if (setterParameters.length == 0) {
19267 return null; 20388 return null;
19268 } 20389 }
19269 return setterParameters[0].type; 20390 return setterParameters[0].type;
19270 } 20391 }
19271 20392
19272 /** 20393 /**
19273 * Return the static type of the given expression that is to be used for type analysis. 20394 * Return the static type of the given expression that is to be used for type analysis.
19274 * 20395 *
19275 * @param expression the expression whose type is to be returned 20396 * @param expression the expression whose type is to be returned
19276 * @return the static type of the given expression 20397 * @return the static type of the given expression
19277 */ 20398 */
19278 Type2 getStaticType(Expression expression) { 20399 Type2 getStaticType(Expression expression) {
19279 Type2 type = expression.staticType; 20400 Type2 type = expression.staticType;
19280 if (type == null) { 20401 if (type == null) {
20402 // TODO(brianwilkerson) This should never happen.
19281 return _dynamicType; 20403 return _dynamicType;
19282 } 20404 }
19283 return type; 20405 return type;
19284 } 20406 }
19285 20407
19286 /** 20408 /**
19287 * Return the variable element represented by the given expression, or `null` if there is no 20409 * Return the variable element represented by the given expression, or `null` if there is no
19288 * such element. 20410 * such element.
19289 * 20411 *
19290 * @param expression the expression whose element is to be returned 20412 * @param expression the expression whose element is to be returned
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
19323 * @return <code>true</code> if given [Element] has direct or indirect referen ce to itself 20445 * @return <code>true</code> if given [Element] has direct or indirect referen ce to itself
19324 * from anywhere except [ClassElement] or type parameter bounds. 20446 * from anywhere except [ClassElement] or type parameter bounds.
19325 */ 20447 */
19326 bool hasTypedefSelfReference(Element target) { 20448 bool hasTypedefSelfReference(Element target) {
19327 Set<Element> checked = new Set<Element>(); 20449 Set<Element> checked = new Set<Element>();
19328 List<Element> toCheck = new List<Element>(); 20450 List<Element> toCheck = new List<Element>();
19329 toCheck.add(target); 20451 toCheck.add(target);
19330 bool firstIteration = true; 20452 bool firstIteration = true;
19331 while (true) { 20453 while (true) {
19332 Element current; 20454 Element current;
20455 // get next element
19333 while (true) { 20456 while (true) {
20457 // may be no more elements to check
19334 if (toCheck.isEmpty) { 20458 if (toCheck.isEmpty) {
19335 return false; 20459 return false;
19336 } 20460 }
20461 // try to get next element
19337 current = toCheck.removeAt(toCheck.length - 1); 20462 current = toCheck.removeAt(toCheck.length - 1);
19338 if (target == current) { 20463 if (target == current) {
19339 if (firstIteration) { 20464 if (firstIteration) {
19340 firstIteration = false; 20465 firstIteration = false;
19341 break; 20466 break;
19342 } else { 20467 } else {
19343 return true; 20468 return true;
19344 } 20469 }
19345 } 20470 }
19346 if (current != null && !checked.contains(current)) { 20471 if (current != null && !checked.contains(current)) {
19347 break; 20472 break;
19348 } 20473 }
19349 } 20474 }
20475 // check current element
19350 current.accept(new GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelf Reference(target, toCheck)); 20476 current.accept(new GeneralizingElementVisitor_ErrorVerifier_hasTypedefSelf Reference(target, toCheck));
19351 checked.add(current); 20477 checked.add(current);
19352 } 20478 }
19353 } 20479 }
19354 20480
19355 /** 20481 /**
19356 * @return `true` if given [Type] implements operator <i>==</i>, and it is not 20482 * @return `true` if given [Type] implements operator <i>==</i>, and it is not
19357 * <i>int</i> or <i>String</i>. 20483 * <i>int</i> or <i>String</i>.
19358 */ 20484 */
19359 bool implementsEqualsWhenNotAllowed(Type2 type) { 20485 bool implementsEqualsWhenNotAllowed(Type2 type) {
20486 // ignore int or String
19360 if (type == null || type == _typeProvider.intType || type == _typeProvider.s tringType) { 20487 if (type == null || type == _typeProvider.intType || type == _typeProvider.s tringType) {
19361 return false; 20488 return false;
19362 } 20489 }
20490 // prepare ClassElement
19363 Element element = type.element; 20491 Element element = type.element;
19364 if (element is! ClassElement) { 20492 if (element is! ClassElement) {
19365 return false; 20493 return false;
19366 } 20494 }
19367 ClassElement classElement = element as ClassElement; 20495 ClassElement classElement = element as ClassElement;
20496 // lookup for ==
19368 MethodElement method = classElement.lookUpMethod("==", _currentLibrary); 20497 MethodElement method = classElement.lookUpMethod("==", _currentLibrary);
19369 if (method == null || method.enclosingElement.type.isObject) { 20498 if (method == null || method.enclosingElement.type.isObject) {
19370 return false; 20499 return false;
19371 } 20500 }
20501 // there is == that we don't like
19372 return true; 20502 return true;
19373 } 20503 }
19374 20504
19375 bool isFunctionType(Type2 type) { 20505 bool isFunctionType(Type2 type) {
19376 if (type.isDynamic || type.isBottom) { 20506 if (type.isDynamic || type.isBottom) {
19377 return true; 20507 return true;
19378 } else if (type is FunctionType || type.isDartCoreFunction) { 20508 } else if (type is FunctionType || type.isDartCoreFunction) {
19379 return true; 20509 return true;
19380 } else if (type is InterfaceType) { 20510 } else if (type is InterfaceType) {
19381 MethodElement callMethod = type.lookUpMethod(ElementResolver.CALL_METHOD_N AME, _currentLibrary); 20511 MethodElement callMethod = type.lookUpMethod(ElementResolver.CALL_METHOD_N AME, _currentLibrary);
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
19657 Object visitVariableElement(VariableElement element) { 20787 Object visitVariableElement(VariableElement element) {
19658 addTypeToCheck(element.type); 20788 addTypeToCheck(element.type);
19659 return super.visitVariableElement(element); 20789 return super.visitVariableElement(element);
19660 } 20790 }
19661 20791
19662 void addTypeToCheck(Type2 type) { 20792 void addTypeToCheck(Type2 type) {
19663 if (type == null) { 20793 if (type == null) {
19664 return; 20794 return;
19665 } 20795 }
19666 Element element = type.element; 20796 Element element = type.element;
20797 // it is OK to reference target from class
19667 if (_inClass && target == element) { 20798 if (_inClass && target == element) {
19668 return; 20799 return;
19669 } 20800 }
20801 // schedule for checking
19670 toCheck.add(element); 20802 toCheck.add(element);
20803 // type arguments
19671 if (type is InterfaceType) { 20804 if (type is InterfaceType) {
19672 InterfaceType interfaceType = type; 20805 InterfaceType interfaceType = type;
19673 for (Type2 typeArgument in interfaceType.typeArguments) { 20806 for (Type2 typeArgument in interfaceType.typeArguments) {
19674 addTypeToCheck(typeArgument); 20807 addTypeToCheck(typeArgument);
19675 } 20808 }
19676 } 20809 }
19677 } 20810 }
19678 } 20811 }
19679 20812
19680 /** 20813 /**
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
19729 * @param correction the template used to create the correction to be displaye d for the error 20862 * @param correction the template used to create the correction to be displaye d for the error
19730 */ 20863 */
19731 ResolverErrorCode.con2(String name, int ordinal, this.type, this.message, Stri ng correction) : super(name, ordinal) { 20864 ResolverErrorCode.con2(String name, int ordinal, this.type, this.message, Stri ng correction) : super(name, ordinal) {
19732 this.correction10 = correction; 20865 this.correction10 = correction;
19733 } 20866 }
19734 20867
19735 String get correction => correction10; 20868 String get correction => correction10;
19736 20869
19737 ErrorSeverity get errorSeverity => type.severity; 20870 ErrorSeverity get errorSeverity => type.severity;
19738 } 20871 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/parser.dart ('k') | pkg/analyzer/lib/src/generated/scanner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698