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

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

Issue 45573002: Rename analyzer_experimental to analyzer. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Tweaks before publishing. Created 7 years, 1 month 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
OLDNEW
(Empty)
1 // This code was auto-generated, is not intended to be edited, and is subject to
2 // significant change. Please see the README file for more information.
3 library engine.resolver;
4 import 'dart:collection';
5 import 'java_core.dart';
6 import 'java_engine.dart';
7 import 'instrumentation.dart';
8 import 'source.dart';
9 import 'error.dart';
10 import 'scanner.dart' as sc;
11 import 'utilities_dart.dart';
12 import 'utilities_general.dart';
13 import 'ast.dart';
14 import 'parser.dart' show Parser, ParserErrorCode;
15 import 'sdk.dart' show DartSdk, SdkLibrary;
16 import 'element.dart';
17 import 'html.dart' as ht;
18 import 'engine.dart';
19 import 'constant.dart';
20 /**
21 * Instances of the class `CompilationUnitBuilder` build an element model for a single
22 * compilation unit.
23 *
24 * @coverage dart.engine.resolver
25 */
26 class CompilationUnitBuilder {
27
28 /**
29 * Build the compilation unit element for the given source.
30 *
31 * @param source the source describing the compilation unit
32 * @param unit the AST structure representing the compilation unit
33 * @return the compilation unit element that was built
34 * @throws AnalysisException if the analysis could not be performed
35 */
36 CompilationUnitElementImpl buildCompilationUnit(Source source, CompilationUnit unit) {
37 TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.st art();
38 try {
39 if (unit == null) {
40 return null;
41 }
42 ElementHolder holder = new ElementHolder();
43 ElementBuilder builder = new ElementBuilder(holder);
44 unit.accept(builder);
45 CompilationUnitElementImpl element = new CompilationUnitElementImpl(source .shortName);
46 element.accessors = holder.accessors;
47 element.functions = holder.functions;
48 element.source = source;
49 element.typeAliases = holder.typeAliases;
50 element.types = holder.types;
51 element.topLevelVariables = holder.topLevelVariables;
52 unit.element = element;
53 return element;
54 } finally {
55 timeCounter.stop();
56 }
57 }
58 }
59 /**
60 * Instances of the class `ElementBuilder` traverse an AST structure and build t he element
61 * model representing the AST structure.
62 *
63 * @coverage dart.engine.resolver
64 */
65 class ElementBuilder extends RecursiveASTVisitor<Object> {
66
67 /**
68 * The element holder associated with the element that is currently being buil t.
69 */
70 ElementHolder _currentHolder;
71
72 /**
73 * A flag indicating whether a variable declaration is in the context of a fie ld declaration.
74 */
75 bool _inFieldContext = false;
76
77 /**
78 * A flag indicating whether a variable declaration is within the body of a me thod or function.
79 */
80 bool _inFunction = false;
81
82 /**
83 * A flag indicating whether the class currently being visited can be used as a mixin.
84 */
85 bool _isValidMixin = false;
86
87 /**
88 * A collection holding the function types defined in a class that need to hav e their type
89 * arguments set to the types of the type parameters for the class, or `null` if we are not
90 * currently processing nodes within a class.
91 */
92 List<FunctionTypeImpl> _functionTypesToFix = null;
93
94 /**
95 * Initialize a newly created element builder to build the elements for a comp ilation unit.
96 *
97 * @param initialHolder the element holder associated with the compilation uni t being built
98 */
99 ElementBuilder(ElementHolder initialHolder) {
100 _currentHolder = initialHolder;
101 }
102 Object visitBlock(Block node) {
103 bool wasInField = _inFieldContext;
104 _inFieldContext = false;
105 try {
106 node.visitChildren(this);
107 } finally {
108 _inFieldContext = wasInField;
109 }
110 return null;
111 }
112 Object visitCatchClause(CatchClause node) {
113 SimpleIdentifier exceptionParameter = node.exceptionParameter;
114 if (exceptionParameter != null) {
115 LocalVariableElementImpl exception = new LocalVariableElementImpl(exceptio nParameter);
116 _currentHolder.addLocalVariable(exception);
117 exceptionParameter.staticElement = exception;
118 SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
119 if (stackTraceParameter != null) {
120 LocalVariableElementImpl stackTrace = new LocalVariableElementImpl(stack TraceParameter);
121 _currentHolder.addLocalVariable(stackTrace);
122 stackTraceParameter.staticElement = stackTrace;
123 }
124 }
125 return super.visitCatchClause(node);
126 }
127 Object visitClassDeclaration(ClassDeclaration node) {
128 ElementHolder holder = new ElementHolder();
129 _isValidMixin = true;
130 _functionTypesToFix = new List<FunctionTypeImpl>();
131 visitChildren(holder, node);
132 SimpleIdentifier className = node.name;
133 ClassElementImpl element = new ClassElementImpl(className);
134 List<TypeParameterElement> typeParameters = holder.typeParameters;
135 List<Type2> typeArguments = createTypeParameterTypes(typeParameters);
136 InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
137 interfaceType.typeArguments = typeArguments;
138 element.type = interfaceType;
139 List<ConstructorElement> constructors = holder.constructors;
140 if (constructors.length == 0) {
141 constructors = createDefaultConstructors(interfaceType);
142 }
143 element.abstract = node.abstractKeyword != null;
144 element.accessors = holder.accessors;
145 element.constructors = constructors;
146 element.fields = holder.fields;
147 element.methods = holder.methods;
148 element.typeParameters = typeParameters;
149 element.validMixin = _isValidMixin;
150 for (FunctionTypeImpl functionType in _functionTypesToFix) {
151 functionType.typeArguments = typeArguments;
152 }
153 _functionTypesToFix = null;
154 _currentHolder.addType(element);
155 className.staticElement = element;
156 holder.validate();
157 return null;
158 }
159 Object visitClassTypeAlias(ClassTypeAlias node) {
160 ElementHolder holder = new ElementHolder();
161 _functionTypesToFix = new List<FunctionTypeImpl>();
162 visitChildren(holder, node);
163 SimpleIdentifier className = node.name;
164 ClassElementImpl element = new ClassElementImpl(className);
165 element.abstract = node.abstractKeyword != null;
166 element.typedef = true;
167 List<TypeParameterElement> typeParameters = holder.typeParameters;
168 element.typeParameters = typeParameters;
169 List<Type2> typeArguments = createTypeParameterTypes(typeParameters);
170 InterfaceTypeImpl interfaceType = new InterfaceTypeImpl.con1(element);
171 interfaceType.typeArguments = typeArguments;
172 element.type = interfaceType;
173 element.constructors = createDefaultConstructors(interfaceType);
174 for (FunctionTypeImpl functionType in _functionTypesToFix) {
175 functionType.typeArguments = typeArguments;
176 }
177 _functionTypesToFix = null;
178 _currentHolder.addType(element);
179 className.staticElement = element;
180 holder.validate();
181 return null;
182 }
183 Object visitConstructorDeclaration(ConstructorDeclaration node) {
184 _isValidMixin = false;
185 ElementHolder holder = new ElementHolder();
186 bool wasInFunction = _inFunction;
187 _inFunction = true;
188 try {
189 visitChildren(holder, node);
190 } finally {
191 _inFunction = wasInFunction;
192 }
193 SimpleIdentifier constructorName = node.name;
194 ConstructorElementImpl element = new ConstructorElementImpl(constructorName) ;
195 if (node.factoryKeyword != null) {
196 element.factory = true;
197 }
198 element.functions = holder.functions;
199 element.labels = holder.labels;
200 element.localVariables = holder.localVariables;
201 element.parameters = holder.parameters;
202 element.const2 = node.constKeyword != null;
203 _currentHolder.addConstructor(element);
204 node.element = element;
205 if (constructorName == null) {
206 Identifier returnType = node.returnType;
207 if (returnType != null) {
208 element.nameOffset = returnType.offset;
209 }
210 } else {
211 constructorName.staticElement = element;
212 }
213 holder.validate();
214 return null;
215 }
216 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
217 SimpleIdentifier variableName = node.identifier;
218 sc.Token keyword = node.keyword;
219 LocalVariableElementImpl element = new LocalVariableElementImpl(variableName );
220 ForEachStatement statement = node.parent as ForEachStatement;
221 int declarationEnd = node.offset + node.length;
222 int statementEnd = statement.offset + statement.length;
223 element.setVisibleRange(declarationEnd, statementEnd - declarationEnd - 1);
224 element.const3 = matches(keyword, sc.Keyword.CONST);
225 element.final2 = matches(keyword, sc.Keyword.FINAL);
226 _currentHolder.addLocalVariable(element);
227 variableName.staticElement = element;
228 return super.visitDeclaredIdentifier(node);
229 }
230 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
231 ElementHolder holder = new ElementHolder();
232 visit(holder, node.defaultValue);
233 FunctionElementImpl initializer = new FunctionElementImpl();
234 initializer.functions = holder.functions;
235 initializer.labels = holder.labels;
236 initializer.localVariables = holder.localVariables;
237 initializer.parameters = holder.parameters;
238 SimpleIdentifier parameterName = node.parameter.identifier;
239 ParameterElementImpl parameter;
240 if (node.parameter is FieldFormalParameter) {
241 parameter = new DefaultFieldFormalParameterElementImpl(parameterName);
242 } else {
243 parameter = new DefaultParameterElementImpl(parameterName);
244 }
245 parameter.const3 = node.isConst;
246 parameter.final2 = node.isFinal;
247 parameter.initializer = initializer;
248 parameter.parameterKind = node.kind;
249 Expression defaultValue = node.defaultValue;
250 if (defaultValue != null) {
251 parameter.setDefaultValueRange(defaultValue.offset, defaultValue.length);
252 }
253 setParameterVisibleRange(node, parameter);
254 _currentHolder.addParameter(parameter);
255 parameterName.staticElement = parameter;
256 node.parameter.accept(this);
257 holder.validate();
258 return null;
259 }
260 Object visitFieldDeclaration(FieldDeclaration node) {
261 bool wasInField = _inFieldContext;
262 _inFieldContext = true;
263 try {
264 node.visitChildren(this);
265 } finally {
266 _inFieldContext = wasInField;
267 }
268 return null;
269 }
270 Object visitFieldFormalParameter(FieldFormalParameter node) {
271 if (node.parent is! DefaultFormalParameter) {
272 SimpleIdentifier parameterName = node.identifier;
273 FieldFormalParameterElementImpl parameter = new FieldFormalParameterElemen tImpl(parameterName);
274 parameter.const3 = node.isConst;
275 parameter.final2 = node.isFinal;
276 parameter.parameterKind = node.kind;
277 _currentHolder.addParameter(parameter);
278 parameterName.staticElement = parameter;
279 }
280 ElementHolder holder = new ElementHolder();
281 visitChildren(holder, node);
282 ((node.element as ParameterElementImpl)).parameters = holder.parameters;
283 holder.validate();
284 return null;
285 }
286 Object visitFunctionDeclaration(FunctionDeclaration node) {
287 FunctionExpression expression = node.functionExpression;
288 if (expression != null) {
289 ElementHolder holder = new ElementHolder();
290 bool wasInFunction = _inFunction;
291 _inFunction = true;
292 try {
293 visitChildren(holder, expression);
294 } finally {
295 _inFunction = wasInFunction;
296 }
297 sc.Token property = node.propertyKeyword;
298 if (property == null) {
299 SimpleIdentifier functionName = node.name;
300 FunctionElementImpl element = new FunctionElementImpl.con1(functionName) ;
301 element.functions = holder.functions;
302 element.labels = holder.labels;
303 element.localVariables = holder.localVariables;
304 element.parameters = holder.parameters;
305 if (_inFunction) {
306 Block enclosingBlock = node.getAncestor(Block);
307 if (enclosingBlock != null) {
308 int functionEnd = node.offset + node.length;
309 int blockEnd = enclosingBlock.offset + enclosingBlock.length;
310 element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
311 }
312 }
313 _currentHolder.addFunction(element);
314 expression.element = element;
315 functionName.staticElement = element;
316 } else {
317 SimpleIdentifier propertyNameNode = node.name;
318 if (propertyNameNode == null) {
319 return null;
320 }
321 String propertyName = propertyNameNode.name;
322 TopLevelVariableElementImpl variable = _currentHolder.getTopLevelVariabl e(propertyName) as TopLevelVariableElementImpl;
323 if (variable == null) {
324 variable = new TopLevelVariableElementImpl.con2(node.name.name);
325 variable.final2 = true;
326 variable.synthetic = true;
327 _currentHolder.addTopLevelVariable(variable);
328 }
329 if (matches(property, sc.Keyword.GET)) {
330 PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.c on1(propertyNameNode);
331 getter.functions = holder.functions;
332 getter.labels = holder.labels;
333 getter.localVariables = holder.localVariables;
334 getter.variable = variable;
335 getter.getter = true;
336 getter.static = true;
337 variable.getter = getter;
338 _currentHolder.addAccessor(getter);
339 expression.element = getter;
340 propertyNameNode.staticElement = getter;
341 } else {
342 PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.c on1(propertyNameNode);
343 setter.functions = holder.functions;
344 setter.labels = holder.labels;
345 setter.localVariables = holder.localVariables;
346 setter.parameters = holder.parameters;
347 setter.variable = variable;
348 setter.setter = true;
349 setter.static = true;
350 variable.setter = setter;
351 variable.final2 = false;
352 _currentHolder.addAccessor(setter);
353 expression.element = setter;
354 propertyNameNode.staticElement = setter;
355 }
356 }
357 holder.validate();
358 }
359 return null;
360 }
361 Object visitFunctionExpression(FunctionExpression node) {
362 ElementHolder holder = new ElementHolder();
363 bool wasInFunction = _inFunction;
364 _inFunction = true;
365 try {
366 visitChildren(holder, node);
367 } finally {
368 _inFunction = wasInFunction;
369 }
370 FunctionElementImpl element = new FunctionElementImpl.con2(node.beginToken.o ffset);
371 element.functions = holder.functions;
372 element.labels = holder.labels;
373 element.localVariables = holder.localVariables;
374 element.parameters = holder.parameters;
375 if (_inFunction) {
376 Block enclosingBlock = node.getAncestor(Block);
377 if (enclosingBlock != null) {
378 int functionEnd = node.offset + node.length;
379 int blockEnd = enclosingBlock.offset + enclosingBlock.length;
380 element.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
381 }
382 }
383 FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
384 if (_functionTypesToFix != null) {
385 _functionTypesToFix.add(type);
386 }
387 element.type = type;
388 _currentHolder.addFunction(element);
389 node.element = element;
390 holder.validate();
391 return null;
392 }
393 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
394 ElementHolder holder = new ElementHolder();
395 visitChildren(holder, node);
396 SimpleIdentifier aliasName = node.name;
397 List<ParameterElement> parameters = holder.parameters;
398 List<TypeParameterElement> typeParameters = holder.typeParameters;
399 FunctionTypeAliasElementImpl element = new FunctionTypeAliasElementImpl(alia sName);
400 element.parameters = parameters;
401 element.typeParameters = typeParameters;
402 FunctionTypeImpl type = new FunctionTypeImpl.con2(element);
403 type.typeArguments = createTypeParameterTypes(typeParameters);
404 element.type = type;
405 _currentHolder.addTypeAlias(element);
406 aliasName.staticElement = element;
407 holder.validate();
408 return null;
409 }
410 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
411 if (node.parent is! DefaultFormalParameter) {
412 SimpleIdentifier parameterName = node.identifier;
413 ParameterElementImpl parameter = new ParameterElementImpl.con1(parameterNa me);
414 parameter.parameterKind = node.kind;
415 setParameterVisibleRange(node, parameter);
416 _currentHolder.addParameter(parameter);
417 parameterName.staticElement = parameter;
418 }
419 ElementHolder holder = new ElementHolder();
420 visitChildren(holder, node);
421 ((node.element as ParameterElementImpl)).parameters = holder.parameters;
422 holder.validate();
423 return null;
424 }
425 Object visitLabeledStatement(LabeledStatement node) {
426 bool onSwitchStatement = node.statement is SwitchStatement;
427 for (Label label in node.labels) {
428 SimpleIdentifier labelName = label.label;
429 LabelElementImpl element = new LabelElementImpl(labelName, onSwitchStateme nt, false);
430 _currentHolder.addLabel(element);
431 labelName.staticElement = element;
432 }
433 return super.visitLabeledStatement(node);
434 }
435 Object visitMethodDeclaration(MethodDeclaration node) {
436 ElementHolder holder = new ElementHolder();
437 bool wasInFunction = _inFunction;
438 _inFunction = true;
439 try {
440 visitChildren(holder, node);
441 } finally {
442 _inFunction = wasInFunction;
443 }
444 bool isStatic = node.isStatic;
445 sc.Token property = node.propertyKeyword;
446 if (property == null) {
447 SimpleIdentifier methodName = node.name;
448 String nameOfMethod = methodName.name;
449 if (nameOfMethod == sc.TokenType.MINUS.lexeme && node.parameters.parameter s.length == 0) {
450 nameOfMethod = "unary-";
451 }
452 MethodElementImpl element = new MethodElementImpl.con2(nameOfMethod, metho dName.offset);
453 element.abstract = node.isAbstract;
454 element.functions = holder.functions;
455 element.labels = holder.labels;
456 element.localVariables = holder.localVariables;
457 element.parameters = holder.parameters;
458 element.static = isStatic;
459 _currentHolder.addMethod(element);
460 methodName.staticElement = element;
461 } else {
462 SimpleIdentifier propertyNameNode = node.name;
463 String propertyName = propertyNameNode.name;
464 FieldElementImpl field = _currentHolder.getField(propertyName) as FieldEle mentImpl;
465 if (field == null) {
466 field = new FieldElementImpl.con2(node.name.name);
467 field.final2 = true;
468 field.static = isStatic;
469 field.synthetic = true;
470 _currentHolder.addField(field);
471 }
472 if (matches(property, sc.Keyword.GET)) {
473 PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con 1(propertyNameNode);
474 getter.functions = holder.functions;
475 getter.labels = holder.labels;
476 getter.localVariables = holder.localVariables;
477 getter.variable = field;
478 getter.abstract = node.body is EmptyFunctionBody && node.externalKeyword == null;
479 getter.getter = true;
480 getter.static = isStatic;
481 field.getter = getter;
482 _currentHolder.addAccessor(getter);
483 propertyNameNode.staticElement = getter;
484 } else {
485 PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con 1(propertyNameNode);
486 setter.functions = holder.functions;
487 setter.labels = holder.labels;
488 setter.localVariables = holder.localVariables;
489 setter.parameters = holder.parameters;
490 setter.variable = field;
491 setter.abstract = node.body is EmptyFunctionBody && !matches(node.extern alKeyword, sc.Keyword.EXTERNAL);
492 setter.setter = true;
493 setter.static = isStatic;
494 field.setter = setter;
495 field.final2 = false;
496 _currentHolder.addAccessor(setter);
497 propertyNameNode.staticElement = setter;
498 }
499 }
500 holder.validate();
501 return null;
502 }
503 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
504 if (node.parent is! DefaultFormalParameter) {
505 SimpleIdentifier parameterName = node.identifier;
506 ParameterElementImpl parameter = new ParameterElementImpl.con1(parameterNa me);
507 parameter.const3 = node.isConst;
508 parameter.final2 = node.isFinal;
509 parameter.parameterKind = node.kind;
510 setParameterVisibleRange(node, parameter);
511 _currentHolder.addParameter(parameter);
512 parameterName.staticElement = parameter;
513 }
514 return super.visitSimpleFormalParameter(node);
515 }
516 Object visitSuperExpression(SuperExpression node) {
517 _isValidMixin = false;
518 return super.visitSuperExpression(node);
519 }
520 Object visitSwitchCase(SwitchCase node) {
521 for (Label label in node.labels) {
522 SimpleIdentifier labelName = label.label;
523 LabelElementImpl element = new LabelElementImpl(labelName, false, true);
524 _currentHolder.addLabel(element);
525 labelName.staticElement = element;
526 }
527 return super.visitSwitchCase(node);
528 }
529 Object visitSwitchDefault(SwitchDefault node) {
530 for (Label label in node.labels) {
531 SimpleIdentifier labelName = label.label;
532 LabelElementImpl element = new LabelElementImpl(labelName, false, true);
533 _currentHolder.addLabel(element);
534 labelName.staticElement = element;
535 }
536 return super.visitSwitchDefault(node);
537 }
538 Object visitTypeParameter(TypeParameter node) {
539 SimpleIdentifier parameterName = node.name;
540 TypeParameterElementImpl typeParameter = new TypeParameterElementImpl(parame terName);
541 TypeParameterTypeImpl typeParameterType = new TypeParameterTypeImpl(typePara meter);
542 typeParameter.type = typeParameterType;
543 _currentHolder.addTypeParameter(typeParameter);
544 parameterName.staticElement = typeParameter;
545 return super.visitTypeParameter(node);
546 }
547 Object visitVariableDeclaration(VariableDeclaration node) {
548 sc.Token keyword = ((node.parent as VariableDeclarationList)).keyword;
549 bool isConst = matches(keyword, sc.Keyword.CONST);
550 bool isFinal = matches(keyword, sc.Keyword.FINAL);
551 bool hasInitializer = node.initializer != null;
552 VariableElementImpl element;
553 if (_inFieldContext) {
554 SimpleIdentifier fieldName = node.name;
555 FieldElementImpl field;
556 if (isConst && hasInitializer) {
557 field = new ConstFieldElementImpl(fieldName);
558 } else {
559 field = new FieldElementImpl.con1(fieldName);
560 }
561 element = field;
562 _currentHolder.addField(field);
563 fieldName.staticElement = field;
564 } else if (_inFunction) {
565 SimpleIdentifier variableName = node.name;
566 LocalVariableElementImpl variable;
567 if (isConst && hasInitializer) {
568 variable = new ConstLocalVariableElementImpl(variableName);
569 } else {
570 variable = new LocalVariableElementImpl(variableName);
571 }
572 element = variable;
573 Block enclosingBlock = node.getAncestor(Block);
574 int functionEnd = node.offset + node.length;
575 int blockEnd = enclosingBlock.offset + enclosingBlock.length;
576 variable.setVisibleRange(functionEnd, blockEnd - functionEnd - 1);
577 _currentHolder.addLocalVariable(variable);
578 variableName.staticElement = element;
579 } else {
580 SimpleIdentifier variableName = node.name;
581 TopLevelVariableElementImpl variable;
582 if (isConst && hasInitializer) {
583 variable = new ConstTopLevelVariableElementImpl(variableName);
584 } else {
585 variable = new TopLevelVariableElementImpl.con1(variableName);
586 }
587 element = variable;
588 _currentHolder.addTopLevelVariable(variable);
589 variableName.staticElement = element;
590 }
591 element.const3 = isConst;
592 element.final2 = isFinal;
593 if (hasInitializer) {
594 ElementHolder holder = new ElementHolder();
595 bool wasInFieldContext = _inFieldContext;
596 _inFieldContext = false;
597 try {
598 visit(holder, node.initializer);
599 } finally {
600 _inFieldContext = wasInFieldContext;
601 }
602 FunctionElementImpl initializer = new FunctionElementImpl();
603 initializer.functions = holder.functions;
604 initializer.labels = holder.labels;
605 initializer.localVariables = holder.localVariables;
606 initializer.synthetic = true;
607 element.initializer = initializer;
608 holder.validate();
609 }
610 if (element is PropertyInducingElementImpl) {
611 PropertyInducingElementImpl variable = element as PropertyInducingElementI mpl;
612 if (_inFieldContext) {
613 ((variable as FieldElementImpl)).static = matches(((node.parent.parent a s FieldDeclaration)).staticKeyword, sc.Keyword.STATIC);
614 }
615 PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2( variable);
616 getter.getter = true;
617 getter.static = variable.isStatic;
618 _currentHolder.addAccessor(getter);
619 variable.getter = getter;
620 if (!isFinal) {
621 PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con 2(variable);
622 setter.setter = true;
623 setter.static = variable.isStatic;
624 ParameterElementImpl parameter = new ParameterElementImpl.con2("_${varia ble.name}", variable.nameOffset);
625 parameter.synthetic = true;
626 parameter.parameterKind = ParameterKind.REQUIRED;
627 setter.parameters = <ParameterElement> [parameter];
628 _currentHolder.addAccessor(setter);
629 variable.setter = setter;
630 }
631 }
632 return null;
633 }
634
635 /**
636 * Creates the [ConstructorElement]s array with the single default constructor element.
637 *
638 * @param interfaceType the interface type for which to create a default const ructor
639 * @return the [ConstructorElement]s array with the single default constructor element
640 */
641 List<ConstructorElement> createDefaultConstructors(InterfaceTypeImpl interface Type) {
642 ConstructorElementImpl constructor = new ConstructorElementImpl(null);
643 constructor.synthetic = true;
644 constructor.returnType = interfaceType;
645 FunctionTypeImpl type = new FunctionTypeImpl.con1(constructor);
646 _functionTypesToFix.add(type);
647 constructor.type = type;
648 return <ConstructorElement> [constructor];
649 }
650
651 /**
652 * Create the types associated with the given type parameters, setting the typ e of each type
653 * parameter, and return an array of types corresponding to the given paramete rs.
654 *
655 * @param typeParameters the type parameters for which types are to be created
656 * @return an array of types corresponding to the given parameters
657 */
658 List<Type2> createTypeParameterTypes(List<TypeParameterElement> typeParameters ) {
659 int typeParameterCount = typeParameters.length;
660 List<Type2> typeArguments = new List<Type2>(typeParameterCount);
661 for (int i = 0; i < typeParameterCount; i++) {
662 TypeParameterElementImpl typeParameter = typeParameters[i] as TypeParamete rElementImpl;
663 TypeParameterTypeImpl typeParameterType = new TypeParameterTypeImpl(typePa rameter);
664 typeParameter.type = typeParameterType;
665 typeArguments[i] = typeParameterType;
666 }
667 return typeArguments;
668 }
669
670 /**
671 * Return the body of the function that contains the given parameter, or `null ` if no
672 * function body could be found.
673 *
674 * @param node the parameter contained in the function whose body is to be ret urned
675 * @return the body of the function that contains the given parameter
676 */
677 FunctionBody getFunctionBody(FormalParameter node) {
678 ASTNode parent = node.parent;
679 while (parent != null) {
680 if (parent is ConstructorDeclaration) {
681 return ((parent as ConstructorDeclaration)).body;
682 } else if (parent is FunctionExpression) {
683 return ((parent as FunctionExpression)).body;
684 } else if (parent is MethodDeclaration) {
685 return ((parent as MethodDeclaration)).body;
686 }
687 parent = parent.parent;
688 }
689 return null;
690 }
691
692 /**
693 * Return `true` if the given token is a token for the given keyword.
694 *
695 * @param token the token being tested
696 * @param keyword the keyword being tested for
697 * @return `true` if the given token is a token for the given keyword
698 */
699 bool matches(sc.Token token, sc.Keyword keyword) => token != null && identical (token.type, sc.TokenType.KEYWORD) && identical(((token as sc.KeywordToken)).key word, keyword);
700
701 /**
702 * Sets the visible source range for formal parameter.
703 */
704 void setParameterVisibleRange(FormalParameter node, ParameterElementImpl eleme nt) {
705 FunctionBody body = getFunctionBody(node);
706 if (body != null) {
707 element.setVisibleRange(body.offset, body.length);
708 }
709 }
710
711 /**
712 * Make the given holder be the current holder while visiting the given node.
713 *
714 * @param holder the holder that will gather elements that are built while vis iting the children
715 * @param node the node to be visited
716 */
717 void visit(ElementHolder holder, ASTNode node) {
718 if (node != null) {
719 ElementHolder previousHolder = _currentHolder;
720 _currentHolder = holder;
721 try {
722 node.accept(this);
723 } finally {
724 _currentHolder = previousHolder;
725 }
726 }
727 }
728
729 /**
730 * Make the given holder be the current holder while visiting the children of the given node.
731 *
732 * @param holder the holder that will gather elements that are built while vis iting the children
733 * @param node the node whose children are to be visited
734 */
735 void visitChildren(ElementHolder holder, ASTNode node) {
736 if (node != null) {
737 ElementHolder previousHolder = _currentHolder;
738 _currentHolder = holder;
739 try {
740 node.visitChildren(this);
741 } finally {
742 _currentHolder = previousHolder;
743 }
744 }
745 }
746 }
747 /**
748 * Instances of the class `ElementHolder` hold on to elements created while trav ersing an AST
749 * structure so that they can be accessed when creating their enclosing element.
750 *
751 * @coverage dart.engine.resolver
752 */
753 class ElementHolder {
754 List<PropertyAccessorElement> _accessors;
755 List<ConstructorElement> _constructors;
756 List<FieldElement> _fields;
757 List<FunctionElement> _functions;
758 List<LabelElement> _labels;
759 List<VariableElement> _localVariables;
760 List<MethodElement> _methods;
761 List<ParameterElement> _parameters;
762 List<TopLevelVariableElement> _topLevelVariables;
763 List<ClassElement> _types;
764 List<FunctionTypeAliasElement> _typeAliases;
765 List<TypeParameterElement> _typeParameters;
766 void addAccessor(PropertyAccessorElement element) {
767 if (_accessors == null) {
768 _accessors = new List<PropertyAccessorElement>();
769 }
770 _accessors.add(element);
771 }
772 void addConstructor(ConstructorElement element) {
773 if (_constructors == null) {
774 _constructors = new List<ConstructorElement>();
775 }
776 _constructors.add(element);
777 }
778 void addField(FieldElement element) {
779 if (_fields == null) {
780 _fields = new List<FieldElement>();
781 }
782 _fields.add(element);
783 }
784 void addFunction(FunctionElement element) {
785 if (_functions == null) {
786 _functions = new List<FunctionElement>();
787 }
788 _functions.add(element);
789 }
790 void addLabel(LabelElement element) {
791 if (_labels == null) {
792 _labels = new List<LabelElement>();
793 }
794 _labels.add(element);
795 }
796 void addLocalVariable(LocalVariableElement element) {
797 if (_localVariables == null) {
798 _localVariables = new List<VariableElement>();
799 }
800 _localVariables.add(element);
801 }
802 void addMethod(MethodElement element) {
803 if (_methods == null) {
804 _methods = new List<MethodElement>();
805 }
806 _methods.add(element);
807 }
808 void addParameter(ParameterElement element) {
809 if (_parameters == null) {
810 _parameters = new List<ParameterElement>();
811 }
812 _parameters.add(element);
813 }
814 void addTopLevelVariable(TopLevelVariableElement element) {
815 if (_topLevelVariables == null) {
816 _topLevelVariables = new List<TopLevelVariableElement>();
817 }
818 _topLevelVariables.add(element);
819 }
820 void addType(ClassElement element) {
821 if (_types == null) {
822 _types = new List<ClassElement>();
823 }
824 _types.add(element);
825 }
826 void addTypeAlias(FunctionTypeAliasElement element) {
827 if (_typeAliases == null) {
828 _typeAliases = new List<FunctionTypeAliasElement>();
829 }
830 _typeAliases.add(element);
831 }
832 void addTypeParameter(TypeParameterElement element) {
833 if (_typeParameters == null) {
834 _typeParameters = new List<TypeParameterElement>();
835 }
836 _typeParameters.add(element);
837 }
838 List<PropertyAccessorElement> get accessors {
839 if (_accessors == null) {
840 return PropertyAccessorElementImpl.EMPTY_ARRAY;
841 }
842 List<PropertyAccessorElement> result = new List.from(_accessors);
843 _accessors = null;
844 return result;
845 }
846 List<ConstructorElement> get constructors {
847 if (_constructors == null) {
848 return ConstructorElementImpl.EMPTY_ARRAY;
849 }
850 List<ConstructorElement> result = new List.from(_constructors);
851 _constructors = null;
852 return result;
853 }
854 FieldElement getField(String fieldName) {
855 if (_fields == null) {
856 return null;
857 }
858 for (FieldElement field in _fields) {
859 if (field.name == fieldName) {
860 return field;
861 }
862 }
863 return null;
864 }
865 List<FieldElement> get fields {
866 if (_fields == null) {
867 return FieldElementImpl.EMPTY_ARRAY;
868 }
869 List<FieldElement> result = new List.from(_fields);
870 _fields = null;
871 return result;
872 }
873 List<FunctionElement> get functions {
874 if (_functions == null) {
875 return FunctionElementImpl.EMPTY_ARRAY;
876 }
877 List<FunctionElement> result = new List.from(_functions);
878 _functions = null;
879 return result;
880 }
881 List<LabelElement> get labels {
882 if (_labels == null) {
883 return LabelElementImpl.EMPTY_ARRAY;
884 }
885 List<LabelElement> result = new List.from(_labels);
886 _labels = null;
887 return result;
888 }
889 List<LocalVariableElement> get localVariables {
890 if (_localVariables == null) {
891 return LocalVariableElementImpl.EMPTY_ARRAY;
892 }
893 List<LocalVariableElement> result = new List.from(_localVariables);
894 _localVariables = null;
895 return result;
896 }
897 List<MethodElement> get methods {
898 if (_methods == null) {
899 return MethodElementImpl.EMPTY_ARRAY;
900 }
901 List<MethodElement> result = new List.from(_methods);
902 _methods = null;
903 return result;
904 }
905 List<ParameterElement> get parameters {
906 if (_parameters == null) {
907 return ParameterElementImpl.EMPTY_ARRAY;
908 }
909 List<ParameterElement> result = new List.from(_parameters);
910 _parameters = null;
911 return result;
912 }
913 TopLevelVariableElement getTopLevelVariable(String variableName) {
914 if (_topLevelVariables == null) {
915 return null;
916 }
917 for (TopLevelVariableElement variable in _topLevelVariables) {
918 if (variable.name == variableName) {
919 return variable;
920 }
921 }
922 return null;
923 }
924 List<TopLevelVariableElement> get topLevelVariables {
925 if (_topLevelVariables == null) {
926 return TopLevelVariableElementImpl.EMPTY_ARRAY;
927 }
928 List<TopLevelVariableElement> result = new List.from(_topLevelVariables);
929 _topLevelVariables = null;
930 return result;
931 }
932 List<FunctionTypeAliasElement> get typeAliases {
933 if (_typeAliases == null) {
934 return FunctionTypeAliasElementImpl.EMPTY_ARRAY;
935 }
936 List<FunctionTypeAliasElement> result = new List.from(_typeAliases);
937 _typeAliases = null;
938 return result;
939 }
940 List<TypeParameterElement> get typeParameters {
941 if (_typeParameters == null) {
942 return TypeParameterElementImpl.EMPTY_ARRAY;
943 }
944 List<TypeParameterElement> result = new List.from(_typeParameters);
945 _typeParameters = null;
946 return result;
947 }
948 List<ClassElement> get types {
949 if (_types == null) {
950 return ClassElementImpl.EMPTY_ARRAY;
951 }
952 List<ClassElement> result = new List.from(_types);
953 _types = null;
954 return result;
955 }
956 void validate() {
957 JavaStringBuilder builder = new JavaStringBuilder();
958 if (_accessors != null) {
959 builder.append(_accessors.length);
960 builder.append(" accessors");
961 }
962 if (_constructors != null) {
963 if (builder.length > 0) {
964 builder.append("; ");
965 }
966 builder.append(_constructors.length);
967 builder.append(" constructors");
968 }
969 if (_fields != null) {
970 if (builder.length > 0) {
971 builder.append("; ");
972 }
973 builder.append(_fields.length);
974 builder.append(" fields");
975 }
976 if (_functions != null) {
977 if (builder.length > 0) {
978 builder.append("; ");
979 }
980 builder.append(_functions.length);
981 builder.append(" functions");
982 }
983 if (_labels != null) {
984 if (builder.length > 0) {
985 builder.append("; ");
986 }
987 builder.append(_labels.length);
988 builder.append(" labels");
989 }
990 if (_localVariables != null) {
991 if (builder.length > 0) {
992 builder.append("; ");
993 }
994 builder.append(_localVariables.length);
995 builder.append(" local variables");
996 }
997 if (_methods != null) {
998 if (builder.length > 0) {
999 builder.append("; ");
1000 }
1001 builder.append(_methods.length);
1002 builder.append(" methods");
1003 }
1004 if (_parameters != null) {
1005 if (builder.length > 0) {
1006 builder.append("; ");
1007 }
1008 builder.append(_parameters.length);
1009 builder.append(" parameters");
1010 }
1011 if (_topLevelVariables != null) {
1012 if (builder.length > 0) {
1013 builder.append("; ");
1014 }
1015 builder.append(_topLevelVariables.length);
1016 builder.append(" top-level variables");
1017 }
1018 if (_types != null) {
1019 if (builder.length > 0) {
1020 builder.append("; ");
1021 }
1022 builder.append(_types.length);
1023 builder.append(" types");
1024 }
1025 if (_typeAliases != null) {
1026 if (builder.length > 0) {
1027 builder.append("; ");
1028 }
1029 builder.append(_typeAliases.length);
1030 builder.append(" type aliases");
1031 }
1032 if (_typeParameters != null) {
1033 if (builder.length > 0) {
1034 builder.append("; ");
1035 }
1036 builder.append(_typeParameters.length);
1037 builder.append(" type parameters");
1038 }
1039 if (builder.length > 0) {
1040 AnalysisEngine.instance.logger.logError("Failed to capture elements: ${bui lder.toString()}");
1041 }
1042 }
1043 }
1044 /**
1045 * Instances of the class `HtmlUnitBuilder` build an element model for a single HTML unit.
1046 */
1047 class HtmlUnitBuilder implements ht.XmlVisitor<Object> {
1048 static String _APPLICATION_DART_IN_DOUBLE_QUOTES = "\"application/dart\"";
1049 static String _APPLICATION_DART_IN_SINGLE_QUOTES = "'application/dart'";
1050 static String _SCRIPT = "script";
1051 static String _SRC = "src";
1052 static String _TYPE = "type";
1053
1054 /**
1055 * The analysis context in which the element model will be built.
1056 */
1057 InternalAnalysisContext _context;
1058
1059 /**
1060 * The error listener to which errors will be reported.
1061 */
1062 RecordingErrorListener errorListener;
1063
1064 /**
1065 * The modification time of the source for which an element is being built.
1066 */
1067 int _modificationStamp = 0;
1068
1069 /**
1070 * The line information associated with the source for which an element is bei ng built, or
1071 * `null` if we are not building an element.
1072 */
1073 LineInfo _lineInfo;
1074
1075 /**
1076 * The HTML element being built.
1077 */
1078 HtmlElementImpl _htmlElement;
1079
1080 /**
1081 * The elements in the path from the HTML unit to the current tag node.
1082 */
1083 List<ht.XmlTagNode> _parentNodes;
1084
1085 /**
1086 * The script elements being built.
1087 */
1088 List<HtmlScriptElement> _scripts;
1089
1090 /**
1091 * A set of the libraries that were resolved while resolving the HTML unit.
1092 */
1093 final Set<Library> resolvedLibraries = new Set<Library>();
1094
1095 /**
1096 * Initialize a newly created HTML unit builder.
1097 *
1098 * @param context the analysis context in which the element model will be buil t
1099 */
1100 HtmlUnitBuilder(InternalAnalysisContext context) {
1101 this._context = context;
1102 this.errorListener = new RecordingErrorListener();
1103 }
1104
1105 /**
1106 * Build the HTML element for the given source.
1107 *
1108 * @param source the source describing the compilation unit
1109 * @return the HTML element that was built
1110 * @throws AnalysisException if the analysis could not be performed
1111 */
1112 HtmlElementImpl buildHtmlElement(Source source) => buildHtmlElement2(source, s ource.modificationStamp, _context.parseHtmlUnit(source));
1113
1114 /**
1115 * Build the HTML element for the given source.
1116 *
1117 * @param source the source describing the compilation unit
1118 * @param modificationStamp the modification time of the source for which an e lement is being
1119 * built
1120 * @param unit the AST structure representing the HTML
1121 * @throws AnalysisException if the analysis could not be performed
1122 */
1123 HtmlElementImpl buildHtmlElement2(Source source, int modificationStamp, ht.Htm lUnit unit) {
1124 this._modificationStamp = modificationStamp;
1125 _lineInfo = _context.computeLineInfo(source);
1126 HtmlElementImpl result = new HtmlElementImpl(_context, source.shortName);
1127 result.source = source;
1128 _htmlElement = result;
1129 unit.accept(this);
1130 _htmlElement = null;
1131 unit.element = result;
1132 return result;
1133 }
1134 Object visitHtmlUnit(ht.HtmlUnit node) {
1135 _parentNodes = new List<ht.XmlTagNode>();
1136 _scripts = new List<HtmlScriptElement>();
1137 try {
1138 node.visitChildren(this);
1139 _htmlElement.scripts = new List.from(_scripts);
1140 } finally {
1141 _scripts = null;
1142 _parentNodes = null;
1143 }
1144 return null;
1145 }
1146 Object visitXmlAttributeNode(ht.XmlAttributeNode node) => null;
1147 Object visitXmlTagNode(ht.XmlTagNode node) {
1148 if (_parentNodes.contains(node)) {
1149 JavaStringBuilder builder = new JavaStringBuilder();
1150 builder.append("Found circularity in XML nodes: ");
1151 bool first = true;
1152 for (ht.XmlTagNode pathNode in _parentNodes) {
1153 if (first) {
1154 first = false;
1155 } else {
1156 builder.append(", ");
1157 }
1158 String tagName = pathNode.tag.lexeme;
1159 if (identical(pathNode, node)) {
1160 builder.append("*");
1161 builder.append(tagName);
1162 builder.append("*");
1163 } else {
1164 builder.append(tagName);
1165 }
1166 }
1167 AnalysisEngine.instance.logger.logError(builder.toString());
1168 return null;
1169 }
1170 _parentNodes.add(node);
1171 try {
1172 if (isScriptNode(node)) {
1173 Source htmlSource = _htmlElement.source;
1174 ht.XmlAttributeNode scriptAttribute = getScriptSourcePath(node);
1175 String scriptSourcePath = scriptAttribute == null ? null : scriptAttribu te.text;
1176 if (identical(node.attributeEnd.type, ht.TokenType.GT) && scriptSourcePa th == null) {
1177 EmbeddedHtmlScriptElementImpl script = new EmbeddedHtmlScriptElementIm pl(node);
1178 String contents = node.content;
1179 int attributeEnd = node.attributeEnd.end;
1180 LineInfo_Location location = _lineInfo.getLocation(attributeEnd);
1181 sc.Scanner scanner = new sc.Scanner(htmlSource, new sc.SubSequenceRead er(new CharSequence(contents), attributeEnd), errorListener);
1182 scanner.setSourceStart(location.lineNumber, location.columnNumber);
1183 sc.Token firstToken = scanner.tokenize();
1184 List<int> lineStarts = scanner.lineStarts;
1185 Parser parser = new Parser(htmlSource, errorListener);
1186 CompilationUnit unit = parser.parseCompilationUnit(firstToken);
1187 try {
1188 LibraryResolver resolver = new LibraryResolver(_context);
1189 LibraryElementImpl library = resolver.resolveEmbeddedLibrary(htmlSou rce, _modificationStamp, unit, true) as LibraryElementImpl;
1190 script.scriptLibrary = library;
1191 resolvedLibraries.addAll(resolver.resolvedLibraries);
1192 errorListener.addAll(resolver.errorListener);
1193 } on AnalysisException catch (exception) {
1194 AnalysisEngine.instance.logger.logError3(exception);
1195 }
1196 _scripts.add(script);
1197 } else {
1198 ExternalHtmlScriptElementImpl script = new ExternalHtmlScriptElementIm pl(node);
1199 if (scriptSourcePath != null) {
1200 try {
1201 scriptSourcePath = Uri.encodeFull(scriptSourcePath);
1202 parseUriWithException(scriptSourcePath);
1203 Source scriptSource = _context.sourceFactory.resolveUri(htmlSource , scriptSourcePath);
1204 script.scriptSource = scriptSource;
1205 if (scriptSource == null || !scriptSource.exists()) {
1206 reportValueError(HtmlWarningCode.URI_DOES_NOT_EXIST, scriptAttri bute, [scriptSourcePath]);
1207 }
1208 } on URISyntaxException catch (exception) {
1209 reportValueError(HtmlWarningCode.INVALID_URI, scriptAttribute, [sc riptSourcePath]);
1210 }
1211 }
1212 _scripts.add(script);
1213 }
1214 } else {
1215 node.visitChildren(this);
1216 }
1217 } finally {
1218 _parentNodes.remove(node);
1219 }
1220 return null;
1221 }
1222
1223 /**
1224 * Return the first source attribute for the given tag node, or `null` if it d oes not exist.
1225 *
1226 * @param node the node containing attributes
1227 * @return the source attribute contained in the given tag
1228 */
1229 ht.XmlAttributeNode getScriptSourcePath(ht.XmlTagNode node) {
1230 for (ht.XmlAttributeNode attribute in node.attributes) {
1231 if (attribute.name.lexeme == _SRC) {
1232 return attribute;
1233 }
1234 }
1235 return null;
1236 }
1237
1238 /**
1239 * Determine if the specified node is a Dart script.
1240 *
1241 * @param node the node to be tested (not `null`)
1242 * @return `true` if the node is a Dart script
1243 */
1244 bool isScriptNode(ht.XmlTagNode node) {
1245 if (node.tagNodes.length != 0 || node.tag.lexeme != _SCRIPT) {
1246 return false;
1247 }
1248 for (ht.XmlAttributeNode attribute in node.attributes) {
1249 if (attribute.name.lexeme == _TYPE) {
1250 ht.Token valueToken = attribute.value;
1251 if (valueToken != null) {
1252 String value = valueToken.lexeme;
1253 if (value == _APPLICATION_DART_IN_DOUBLE_QUOTES || value == _APPLICATI ON_DART_IN_SINGLE_QUOTES) {
1254 return true;
1255 }
1256 }
1257 }
1258 }
1259 return false;
1260 }
1261
1262 /**
1263 * Report an error with the given error code at the given location. Use the gi ven arguments to
1264 * compose the error message.
1265 *
1266 * @param errorCode the error code of the error to be reported
1267 * @param offset the offset of the first character to be highlighted
1268 * @param length the number of characters to be highlighted
1269 * @param arguments the arguments used to compose the error message
1270 */
1271 void reportError(ErrorCode errorCode, int offset, int length, List<Object> arg uments) {
1272 errorListener.onError(new AnalysisError.con2(_htmlElement.source, offset, le ngth, errorCode, arguments));
1273 }
1274
1275 /**
1276 * Report an error with the given error code at the location of the value of t he given attribute.
1277 * Use the given arguments to compose the error message.
1278 *
1279 * @param errorCode the error code of the error to be reported
1280 * @param offset the offset of the first character to be highlighted
1281 * @param length the number of characters to be highlighted
1282 * @param arguments the arguments used to compose the error message
1283 */
1284 void reportValueError(ErrorCode errorCode, ht.XmlAttributeNode attribute, List <Object> arguments) {
1285 int offset = attribute.value.offset + 1;
1286 int length = attribute.value.length - 2;
1287 reportError(errorCode, offset, length, arguments);
1288 }
1289 }
1290 /**
1291 * Instances of the class `BestPracticesVerifier` traverse an AST structure look ing for
1292 * violations of Dart best practices.
1293 *
1294 * @coverage dart.engine.resolver
1295 */
1296 class BestPracticesVerifier extends RecursiveASTVisitor<Object> {
1297 static String _GETTER = "getter";
1298 static String _HASHCODE_GETTER_NAME = "hashCode";
1299 static String _METHOD = "method";
1300 static String _NULL_TYPE_NAME = "Null";
1301 static String _SETTER = "setter";
1302 static String _TO_INT_METHOD_NAME = "toInt";
1303
1304 /**
1305 * Given a parenthesized expression, this returns the parent (or recursively g rand-parent) of the
1306 * expression that is a parenthesized expression, but whose parent is not a pa renthesized
1307 * expression.
1308 *
1309 * For example given the code `(((e)))`: `(e) -> (((e)))`.
1310 *
1311 * @param parenthesizedExpression some expression whose parent is a parenthesi zed expression
1312 * @return the first parent or grand-parent that is a parenthesized expression , that does not have
1313 * a parenthesized expression parent
1314 */
1315 static ParenthesizedExpression wrapParenthesizedExpression(ParenthesizedExpres sion parenthesizedExpression) {
1316 if (parenthesizedExpression.parent is ParenthesizedExpression) {
1317 return wrapParenthesizedExpression(parenthesizedExpression.parent as Paren thesizedExpression);
1318 }
1319 return parenthesizedExpression;
1320 }
1321
1322 /**
1323 * The class containing the AST nodes being visited, or `null` if we are not i n the scope of
1324 * a class.
1325 */
1326 ClassElement _enclosingClass;
1327
1328 /**
1329 * The error reporter by which errors will be reported.
1330 */
1331 ErrorReporter _errorReporter;
1332
1333 /**
1334 * Create a new instance of the [BestPracticesVerifier].
1335 *
1336 * @param errorReporter the error reporter
1337 */
1338 BestPracticesVerifier(ErrorReporter errorReporter) {
1339 this._errorReporter = errorReporter;
1340 }
1341 Object visitAsExpression(AsExpression node) {
1342 checkForUnnecessaryCast(node);
1343 return super.visitAsExpression(node);
1344 }
1345 Object visitBinaryExpression(BinaryExpression node) {
1346 checkForDivisionOptimizationHint(node);
1347 return super.visitBinaryExpression(node);
1348 }
1349 Object visitClassDeclaration(ClassDeclaration node) {
1350 ClassElement outerClass = _enclosingClass;
1351 try {
1352 _enclosingClass = node.element;
1353 return super.visitClassDeclaration(node);
1354 } finally {
1355 _enclosingClass = outerClass;
1356 }
1357 }
1358 Object visitIsExpression(IsExpression node) {
1359 checkAllTypeChecks(node);
1360 return super.visitIsExpression(node);
1361 }
1362 Object visitMethodDeclaration(MethodDeclaration node) {
1363 checkForOverridingPrivateMember(node);
1364 return super.visitMethodDeclaration(node);
1365 }
1366
1367 /**
1368 * Check for the passed is expression for the unnecessary type check hint code s as well as null
1369 * checks expressed using an is expression.
1370 *
1371 * @param node the is expression to check
1372 * @return `true` if and only if a hint code is generated on the passed node
1373 * @see HintCode#TYPE_CHECK_IS_NOT_NULL
1374 * @see HintCode#TYPE_CHECK_IS_NULL
1375 * @see HintCode#UNNECESSARY_TYPE_CHECK_TRUE
1376 * @see HintCode#UNNECESSARY_TYPE_CHECK_FALSE
1377 */
1378 bool checkAllTypeChecks(IsExpression node) {
1379 Expression expression = node.expression;
1380 TypeName typeName = node.type;
1381 Type2 lhsType = expression.staticType;
1382 Type2 rhsType = typeName.type;
1383 if (lhsType == null || rhsType == null) {
1384 return false;
1385 }
1386 String rhsNameStr = typeName.name.name;
1387 if (rhsType.isDynamic && rhsNameStr == sc.Keyword.DYNAMIC.syntax) {
1388 if (node.notOperator == null) {
1389 _errorReporter.reportError2(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node, []);
1390 } else {
1391 _errorReporter.reportError2(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, node, []);
1392 }
1393 return true;
1394 }
1395 Element rhsElement = rhsType.element;
1396 LibraryElement libraryElement = rhsElement != null ? rhsElement.library : nu ll;
1397 if (libraryElement != null && libraryElement.isDartCore) {
1398 if (rhsType.isObject || (expression is NullLiteral && rhsNameStr == _NULL_ TYPE_NAME)) {
1399 if (node.notOperator == null) {
1400 _errorReporter.reportError2(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node , []);
1401 } else {
1402 _errorReporter.reportError2(HintCode.UNNECESSARY_TYPE_CHECK_FALSE, nod e, []);
1403 }
1404 return true;
1405 } else if (rhsNameStr == _NULL_TYPE_NAME) {
1406 if (node.notOperator == null) {
1407 _errorReporter.reportError2(HintCode.TYPE_CHECK_IS_NULL, node, []);
1408 } else {
1409 _errorReporter.reportError2(HintCode.TYPE_CHECK_IS_NOT_NULL, node, []) ;
1410 }
1411 return true;
1412 }
1413 }
1414 return false;
1415 }
1416
1417 /**
1418 * Check for the passed binary expression for the [HintCode#DIVISION_OPTIMIZAT ION].
1419 *
1420 * @param node the binary expression to check
1421 * @return `true` if and only if a hint code is generated on the passed node
1422 * @see HintCode#DIVISION_OPTIMIZATION
1423 */
1424 bool checkForDivisionOptimizationHint(BinaryExpression node) {
1425 if (node.operator.type != sc.TokenType.SLASH) {
1426 return false;
1427 }
1428 MethodElement methodElement = node.bestElement;
1429 if (methodElement == null) {
1430 return false;
1431 }
1432 LibraryElement libraryElement = methodElement.library;
1433 if (libraryElement != null && !libraryElement.isDartCore) {
1434 return false;
1435 }
1436 if (node.parent is ParenthesizedExpression) {
1437 ParenthesizedExpression parenthesizedExpression = wrapParenthesizedExpress ion(node.parent as ParenthesizedExpression);
1438 if (parenthesizedExpression.parent is MethodInvocation) {
1439 MethodInvocation methodInvocation = parenthesizedExpression.parent as Me thodInvocation;
1440 if (_TO_INT_METHOD_NAME == methodInvocation.methodName.name && methodInv ocation.argumentList.arguments.isEmpty) {
1441 _errorReporter.reportError2(HintCode.DIVISION_OPTIMIZATION, methodInvo cation, []);
1442 return true;
1443 }
1444 }
1445 }
1446 return false;
1447 }
1448
1449 /**
1450 * Check for the passed class declaration for the
1451 * [HintCode#OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code.
1452 *
1453 * @param node the class declaration to check
1454 * @return `true` if and only if a hint code is generated on the passed node
1455 * @see HintCode#OVERRIDE_EQUALS_BUT_NOT_HASH_CODE
1456 */
1457 bool checkForOverrideEqualsButNotHashCode(ClassDeclaration node) {
1458 ClassElement classElement = node.element;
1459 if (classElement == null) {
1460 return false;
1461 }
1462 MethodElement equalsOperatorMethodElement = classElement.getMethod(sc.TokenT ype.EQ_EQ.lexeme);
1463 if (equalsOperatorMethodElement != null) {
1464 PropertyAccessorElement hashCodeElement = classElement.getGetter(_HASHCODE _GETTER_NAME);
1465 if (hashCodeElement == null) {
1466 _errorReporter.reportError2(HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE, node.name, [classElement.displayName]);
1467 return true;
1468 }
1469 }
1470 return false;
1471 }
1472
1473 /**
1474 * Check for the passed class declaration for the
1475 * [HintCode#OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code.
1476 *
1477 * @param node the class declaration to check
1478 * @return `true` if and only if a hint code is generated on the passed node
1479 * @see HintCode#OVERRIDDING_PRIVATE_MEMBER
1480 */
1481 bool checkForOverridingPrivateMember(MethodDeclaration node) {
1482 if (_enclosingClass == null) {
1483 return false;
1484 }
1485 if (!Identifier.isPrivateName(node.name.name)) {
1486 return false;
1487 }
1488 ExecutableElement executableElement = node.element;
1489 if (executableElement == null) {
1490 return false;
1491 }
1492 String elementName = executableElement.name;
1493 bool isGetterOrSetter = executableElement is PropertyAccessorElement;
1494 InterfaceType superType = _enclosingClass.supertype;
1495 if (superType == null) {
1496 return false;
1497 }
1498 ClassElement classElement = superType.element;
1499 while (classElement != null) {
1500 if (_enclosingClass.library != classElement.library) {
1501 if (isGetterOrSetter) {
1502 PropertyAccessorElement overriddenAccessor = null;
1503 List<PropertyAccessorElement> accessors = classElement.accessors;
1504 for (PropertyAccessorElement propertyAccessorElement in accessors) {
1505 if (elementName == propertyAccessorElement.name) {
1506 overriddenAccessor = propertyAccessorElement;
1507 break;
1508 }
1509 }
1510 if (overriddenAccessor != null) {
1511 String memberType = ((executableElement as PropertyAccessorElement)) .isGetter ? _GETTER : _SETTER;
1512 _errorReporter.reportError2(HintCode.OVERRIDDING_PRIVATE_MEMBER, nod e.name, [
1513 memberType,
1514 executableElement.displayName,
1515 classElement.displayName]);
1516 return true;
1517 }
1518 } else {
1519 MethodElement overriddenMethod = classElement.getMethod(elementName);
1520 if (overriddenMethod != null) {
1521 _errorReporter.reportError2(HintCode.OVERRIDDING_PRIVATE_MEMBER, nod e.name, [
1522 _METHOD,
1523 executableElement.displayName,
1524 classElement.displayName]);
1525 return true;
1526 }
1527 }
1528 }
1529 superType = classElement.supertype;
1530 classElement = superType != null ? superType.element : null;
1531 }
1532 return false;
1533 }
1534
1535 /**
1536 * Check for the passed as expression for the [HintCode#UNNECESSARY_CAST] hint code.
1537 *
1538 * @param node the as expression to check
1539 * @return `true` if and only if a hint code is generated on the passed node
1540 * @see HintCode#UNNECESSARY_CAST
1541 */
1542 bool checkForUnnecessaryCast(AsExpression node) {
1543 Expression expression = node.expression;
1544 TypeName typeName = node.type;
1545 Type2 lhsType = expression.staticType;
1546 Type2 rhsType = typeName.type;
1547 if (lhsType != null && rhsType != null && !lhsType.isDynamic && !rhsType.isD ynamic && lhsType is! TypeParameterType && rhsType is! TypeParameterType && lhsT ype.isSubtypeOf(rhsType)) {
1548 _errorReporter.reportError2(HintCode.UNNECESSARY_CAST, node, []);
1549 return true;
1550 }
1551 return false;
1552 }
1553 }
1554 /**
1555 * Instances of the class `Dart2JSVerifier` traverse an AST structure looking fo r hints for
1556 * code that will be compiled to JS, such as [HintCode#IS_DOUBLE].
1557 *
1558 * @coverage dart.engine.resolver
1559 */
1560 class Dart2JSVerifier extends RecursiveASTVisitor<Object> {
1561
1562 /**
1563 * The error reporter by which errors will be reported.
1564 */
1565 ErrorReporter _errorReporter;
1566
1567 /**
1568 * The name of the `double` type.
1569 */
1570 static String _DOUBLE_TYPE_NAME = "double";
1571
1572 /**
1573 * Create a new instance of the [Dart2JSVerifier].
1574 *
1575 * @param errorReporter the error reporter
1576 */
1577 Dart2JSVerifier(ErrorReporter errorReporter) {
1578 this._errorReporter = errorReporter;
1579 }
1580 Object visitIsExpression(IsExpression node) {
1581 checkForIsDoubleHints(node);
1582 return super.visitIsExpression(node);
1583 }
1584
1585 /**
1586 * Check for instances of `x is double`, `x is int`, `x is! double` and
1587 * `x is! int`.
1588 *
1589 * @param node the is expression to check
1590 * @return `true` if and only if a hint code is generated on the passed node
1591 * @see HintCode#IS_DOUBLE
1592 * @see HintCode#IS_INT
1593 * @see HintCode#IS_NOT_DOUBLE
1594 * @see HintCode#IS_NOT_INT
1595 */
1596 bool checkForIsDoubleHints(IsExpression node) {
1597 TypeName typeName = node.type;
1598 Type2 type = typeName.type;
1599 if (type != null && type.element != null) {
1600 Element element = type.element;
1601 String typeNameStr = element.name;
1602 LibraryElement libraryElement = element.library;
1603 if (typeNameStr == _DOUBLE_TYPE_NAME && libraryElement != null && libraryE lement.isDartCore) {
1604 if (node.notOperator == null) {
1605 _errorReporter.reportError2(HintCode.IS_DOUBLE, node, []);
1606 } else {
1607 _errorReporter.reportError2(HintCode.IS_NOT_DOUBLE, node, []);
1608 }
1609 return true;
1610 }
1611 }
1612 return false;
1613 }
1614 }
1615 /**
1616 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f or cases of
1617 * [HintCode#DEAD_CODE].
1618 *
1619 * @coverage dart.engine.resolver
1620 */
1621 class DeadCodeVerifier extends RecursiveASTVisitor<Object> {
1622
1623 /**
1624 * The error reporter by which errors will be reported.
1625 */
1626 ErrorReporter _errorReporter;
1627
1628 /**
1629 * Create a new instance of the [DeadCodeVerifier].
1630 *
1631 * @param errorReporter the error reporter
1632 */
1633 DeadCodeVerifier(ErrorReporter errorReporter) {
1634 this._errorReporter = errorReporter;
1635 }
1636 Object visitBinaryExpression(BinaryExpression node) {
1637 sc.Token operator = node.operator;
1638 bool isAmpAmp = identical(operator.type, sc.TokenType.AMPERSAND_AMPERSAND);
1639 bool isBarBar = identical(operator.type, sc.TokenType.BAR_BAR);
1640 if (isAmpAmp || isBarBar) {
1641 Expression lhsCondition = node.leftOperand;
1642 if (!isDebugConstant(lhsCondition)) {
1643 ValidResult lhsResult = getConstantBooleanValue(lhsCondition);
1644 if (lhsResult != null) {
1645 if (identical(lhsResult, ValidResult.RESULT_TRUE) && isBarBar) {
1646 _errorReporter.reportError2(HintCode.DEAD_CODE, node.rightOperand, [ ]);
1647 safelyVisit(lhsCondition);
1648 return null;
1649 } else if (identical(lhsResult, ValidResult.RESULT_FALSE) && isAmpAmp) {
1650 _errorReporter.reportError2(HintCode.DEAD_CODE, node.rightOperand, [ ]);
1651 safelyVisit(lhsCondition);
1652 return null;
1653 }
1654 }
1655 }
1656 }
1657 return super.visitBinaryExpression(node);
1658 }
1659
1660 /**
1661 * For each [Block], this method reports and error on all statements between t he end of the
1662 * block and the first return statement (assuming there it is not at the end o f the block.)
1663 *
1664 * @param node the block to evaluate
1665 */
1666 Object visitBlock(Block node) {
1667 NodeList<Statement> statements = node.statements;
1668 int size = statements.length;
1669 for (int i = 0; i < size; i++) {
1670 Statement currentStatement = statements[i];
1671 safelyVisit(currentStatement);
1672 if (currentStatement is ReturnStatement && i != size - 1) {
1673 Statement nextStatement = statements[i + 1];
1674 Statement lastStatement = statements[size - 1];
1675 int offset = nextStatement.offset;
1676 int length = lastStatement.end - offset;
1677 _errorReporter.reportError3(HintCode.DEAD_CODE, offset, length, []);
1678 return null;
1679 }
1680 }
1681 return null;
1682 }
1683 Object visitConditionalExpression(ConditionalExpression node) {
1684 Expression conditionExpression = node.condition;
1685 safelyVisit(conditionExpression);
1686 if (!isDebugConstant(conditionExpression)) {
1687 ValidResult result = getConstantBooleanValue(conditionExpression);
1688 if (result != null) {
1689 if (identical(result, ValidResult.RESULT_TRUE)) {
1690 _errorReporter.reportError2(HintCode.DEAD_CODE, node.elseExpression, [ ]);
1691 safelyVisit(node.thenExpression);
1692 return null;
1693 } else {
1694 _errorReporter.reportError2(HintCode.DEAD_CODE, node.thenExpression, [ ]);
1695 safelyVisit(node.elseExpression);
1696 return null;
1697 }
1698 }
1699 }
1700 return super.visitConditionalExpression(node);
1701 }
1702 Object visitIfStatement(IfStatement node) {
1703 Expression conditionExpression = node.condition;
1704 safelyVisit(conditionExpression);
1705 if (!isDebugConstant(conditionExpression)) {
1706 ValidResult result = getConstantBooleanValue(conditionExpression);
1707 if (result != null) {
1708 if (identical(result, ValidResult.RESULT_TRUE)) {
1709 Statement elseStatement = node.elseStatement;
1710 if (elseStatement != null) {
1711 _errorReporter.reportError2(HintCode.DEAD_CODE, elseStatement, []);
1712 safelyVisit(node.thenStatement);
1713 return null;
1714 }
1715 } else {
1716 _errorReporter.reportError2(HintCode.DEAD_CODE, node.thenStatement, [] );
1717 safelyVisit(node.elseStatement);
1718 return null;
1719 }
1720 }
1721 }
1722 return super.visitIfStatement(node);
1723 }
1724 Object visitTryStatement(TryStatement node) {
1725 safelyVisit(node.body);
1726 safelyVisit(node.finallyBlock);
1727 NodeList<CatchClause> catchClauses = node.catchClauses;
1728 int numOfCatchClauses = catchClauses.length;
1729 List<Type2> visitedTypes = new List<Type2>();
1730 for (int i = 0; i < numOfCatchClauses; i++) {
1731 CatchClause catchClause = catchClauses[i];
1732 if (catchClause.onKeyword != null) {
1733 TypeName typeName = catchClause.exceptionType;
1734 if (typeName != null && typeName.type != null) {
1735 Type2 currentType = typeName.type;
1736 if (currentType.isObject) {
1737 safelyVisit(catchClause);
1738 if (i + 1 != numOfCatchClauses) {
1739 CatchClause nextCatchClause = catchClauses[i + 1];
1740 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
1741 int offset = nextCatchClause.offset;
1742 int length = lastCatchClause.end - offset;
1743 _errorReporter.reportError3(HintCode.DEAD_CODE_CATCH_FOLLOWING_CAT CH, offset, length, []);
1744 return null;
1745 }
1746 }
1747 for (Type2 type in visitedTypes) {
1748 if (currentType.isSubtypeOf(type)) {
1749 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
1750 int offset = catchClause.offset;
1751 int length = lastCatchClause.end - offset;
1752 _errorReporter.reportError3(HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, o ffset, length, [currentType.displayName, type.displayName]);
1753 return null;
1754 }
1755 }
1756 visitedTypes.add(currentType);
1757 }
1758 safelyVisit(catchClause);
1759 } else {
1760 safelyVisit(catchClause);
1761 if (i + 1 != numOfCatchClauses) {
1762 CatchClause nextCatchClause = catchClauses[i + 1];
1763 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
1764 int offset = nextCatchClause.offset;
1765 int length = lastCatchClause.end - offset;
1766 _errorReporter.reportError3(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length, []);
1767 return null;
1768 }
1769 }
1770 }
1771 return null;
1772 }
1773 Object visitWhileStatement(WhileStatement node) {
1774 Expression conditionExpression = node.condition;
1775 safelyVisit(conditionExpression);
1776 if (!isDebugConstant(conditionExpression)) {
1777 ValidResult result = getConstantBooleanValue(conditionExpression);
1778 if (result != null) {
1779 if (identical(result, ValidResult.RESULT_FALSE)) {
1780 _errorReporter.reportError2(HintCode.DEAD_CODE, node.body, []);
1781 return null;
1782 }
1783 }
1784 }
1785 safelyVisit(node.body);
1786 return null;
1787 }
1788
1789 /**
1790 * Given some [Expression], this method returns [ValidResult#RESULT_TRUE] if i t is
1791 * `true`, [ValidResult#RESULT_FALSE] if it is `false`, or `null` if the
1792 * expression is not a constant boolean value.
1793 *
1794 * @param expression the expression to evaluate
1795 * @return [ValidResult#RESULT_TRUE] if it is `true`, [ValidResult#RESULT_FALS E]
1796 * if it is `false`, or `null` if the expression is not a constant boo lean
1797 * value
1798 */
1799 ValidResult getConstantBooleanValue(Expression expression) {
1800 if (expression is BooleanLiteral) {
1801 if (((expression as BooleanLiteral)).value) {
1802 return ValidResult.RESULT_TRUE;
1803 } else {
1804 return ValidResult.RESULT_FALSE;
1805 }
1806 }
1807 return null;
1808 }
1809
1810 /**
1811 * Return `true` if and only if the passed expression is resolved to a constan t variable.
1812 *
1813 * @param expression some conditional expression
1814 * @return `true` if and only if the passed expression is resolved to a consta nt variable
1815 */
1816 bool isDebugConstant(Expression expression) {
1817 Element element = null;
1818 if (expression is Identifier) {
1819 Identifier identifier = expression as Identifier;
1820 element = identifier.staticElement;
1821 } else if (expression is PropertyAccess) {
1822 PropertyAccess propertyAccess = expression as PropertyAccess;
1823 element = propertyAccess.propertyName.staticElement;
1824 }
1825 if (element is PropertyAccessorElement) {
1826 PropertyAccessorElement pae = element as PropertyAccessorElement;
1827 PropertyInducingElement variable = pae.variable;
1828 return variable != null && variable.isConst;
1829 }
1830 return false;
1831 }
1832
1833 /**
1834 * If the given node is not `null`, visit this instance of the dead code verif ier.
1835 *
1836 * @param node the node to be visited
1837 */
1838 void safelyVisit(ASTNode node) {
1839 if (node != null) {
1840 node.accept(this);
1841 }
1842 }
1843 }
1844 /**
1845 * Instances of the class `HintGenerator` traverse a library's worth of dart cod e at a time to
1846 * generate hints over the set of sources.
1847 *
1848 * @see HintCode
1849 * @coverage dart.engine.resolver
1850 */
1851 class HintGenerator {
1852 List<CompilationUnit> _compilationUnits;
1853 AnalysisContext _context;
1854 AnalysisErrorListener _errorListener;
1855 ImportsVerifier _importsVerifier;
1856 bool _enableDart2JSHints = false;
1857 HintGenerator(List<CompilationUnit> compilationUnits, AnalysisContext context, AnalysisErrorListener errorListener) {
1858 this._compilationUnits = compilationUnits;
1859 this._context = context;
1860 this._errorListener = errorListener;
1861 LibraryElement library = compilationUnits[0].element.library;
1862 _importsVerifier = new ImportsVerifier(library);
1863 _enableDart2JSHints = context.analysisOptions.dart2jsHint;
1864 }
1865 void generateForLibrary() {
1866 TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.hints.star t();
1867 try {
1868 for (int i = 0; i < _compilationUnits.length; i++) {
1869 CompilationUnitElement element = _compilationUnits[i].element;
1870 if (element != null) {
1871 if (i == 0) {
1872 _importsVerifier.inDefiningCompilationUnit = true;
1873 generateForCompilationUnit(_compilationUnits[i], element.source);
1874 _importsVerifier.inDefiningCompilationUnit = false;
1875 } else {
1876 generateForCompilationUnit(_compilationUnits[i], element.source);
1877 }
1878 }
1879 }
1880 ErrorReporter definingCompilationUnitErrorReporter = new ErrorReporter(_er rorListener, _compilationUnits[0].element.source);
1881 _importsVerifier.generateDuplicateImportHints(definingCompilationUnitError Reporter);
1882 _importsVerifier.generateUnusedImportHints(definingCompilationUnitErrorRep orter);
1883 } finally {
1884 timeCounter.stop();
1885 }
1886 }
1887 void generateForCompilationUnit(CompilationUnit unit, Source source) {
1888 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source);
1889 _importsVerifier.visitCompilationUnit(unit);
1890 new DeadCodeVerifier(errorReporter).visitCompilationUnit(unit);
1891 if (_enableDart2JSHints) {
1892 new Dart2JSVerifier(errorReporter).visitCompilationUnit(unit);
1893 }
1894 new BestPracticesVerifier(errorReporter).visitCompilationUnit(unit);
1895 }
1896 }
1897 /**
1898 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the
1899 * source code verifying that all of the imports are used, otherwise a
1900 * [HintCode#UNUSED_IMPORT] is generated with
1901 * [generateUnusedImportHints].
1902 *
1903 * While this class does not yet have support for an "Organize Imports" action, this logic built up
1904 * in this class could be used for such an action in the future.
1905 *
1906 * @coverage dart.engine.resolver
1907 */
1908 class ImportsVerifier extends RecursiveASTVisitor<Object> {
1909
1910 /**
1911 * This is set to `true` if the current compilation unit which is being visite d is the
1912 * defining compilation unit for the library, its value can be set with
1913 * [setInDefiningCompilationUnit].
1914 */
1915 bool _inDefiningCompilationUnit = false;
1916
1917 /**
1918 * The current library.
1919 */
1920 LibraryElement _currentLibrary;
1921
1922 /**
1923 * A list of [ImportDirective]s that the current library imports, as identifie rs are visited
1924 * by this visitor and an import has been identified as being used by the libr ary, the
1925 * [ImportDirective] is removed from this list. After all the sources in the l ibrary have
1926 * been evaluated, this list represents the set of unused imports.
1927 *
1928 * @see ImportsVerifier#generateUnusedImportErrors(ErrorReporter)
1929 */
1930 List<ImportDirective> _unusedImports;
1931
1932 /**
1933 * After the list of [unusedImports] has been computed, this list is a proper subset of the
1934 * unused imports that are listed more than once.
1935 */
1936 List<ImportDirective> _duplicateImports;
1937
1938 /**
1939 * This is a map between the set of [LibraryElement]s that the current library imports, and
1940 * a list of [ImportDirective]s that imports the library. In cases where the c urrent library
1941 * imports a library with a single directive (such as `import lib1.dart;`), th e library
1942 * element will map to a list of one [ImportDirective], which will then be rem oved from the
1943 * [unusedImports] list. In cases where the current library imports a library with multiple
1944 * directives (such as `import lib1.dart; import lib1.dart show C;`), the
1945 * [LibraryElement] will be mapped to a list of the import directives, and the namespace
1946 * will need to be used to compute the correct [ImportDirective] being used, s ee
1947 * [namespaceMap].
1948 */
1949 Map<LibraryElement, List<ImportDirective>> _libraryMap;
1950
1951 /**
1952 * In cases where there is more than one import directive per library element, this mapping is
1953 * used to determine which of the multiple import directives are used by gener ating a
1954 * [Namespace] for each of the imports to do lookups in the same way that they are done from
1955 * the [ElementResolver].
1956 */
1957 Map<ImportDirective, Namespace> _namespaceMap;
1958
1959 /**
1960 * This is a map between prefix elements and the import directive from which t hey are derived. In
1961 * cases where a type is referenced via a prefix element, the import directive can be marked as
1962 * used (removed from the unusedImports) by looking at the resolved `lib` in ` lib.X`,
1963 * instead of looking at which library the `lib.X` resolves.
1964 */
1965 Map<PrefixElement, ImportDirective> _prefixElementMap;
1966
1967 /**
1968 * Create a new instance of the [ImportsVerifier].
1969 *
1970 * @param errorReporter the error reporter
1971 */
1972 ImportsVerifier(LibraryElement library) {
1973 this._currentLibrary = library;
1974 this._unusedImports = new List<ImportDirective>();
1975 this._duplicateImports = new List<ImportDirective>();
1976 this._libraryMap = new Map<LibraryElement, List<ImportDirective>>();
1977 this._namespaceMap = new Map<ImportDirective, Namespace>();
1978 this._prefixElementMap = new Map<PrefixElement, ImportDirective>();
1979 }
1980
1981 /**
1982 * Any time after the defining compilation unit has been visited by this visit or, this method can
1983 * be called to report an [HintCode#DUPLICATE_IMPORT] hint for each of the imp ort directives
1984 * in the [duplicateImports] list.
1985 *
1986 * @param errorReporter the error reporter to report the set of [HintCode#DUPL ICATE_IMPORT]
1987 * hints to
1988 */
1989 void generateDuplicateImportHints(ErrorReporter errorReporter) {
1990 for (ImportDirective duplicateImport in _duplicateImports) {
1991 errorReporter.reportError2(HintCode.DUPLICATE_IMPORT, duplicateImport.uri, []);
1992 }
1993 }
1994
1995 /**
1996 * After all of the compilation units have been visited by this visitor, this method can be called
1997 * to report an [HintCode#UNUSED_IMPORT] hint for each of the import directive s in the
1998 * [unusedImports] list.
1999 *
2000 * @param errorReporter the error reporter to report the set of [HintCode#UNUS ED_IMPORT]
2001 * hints to
2002 */
2003 void generateUnusedImportHints(ErrorReporter errorReporter) {
2004 for (ImportDirective unusedImport in _unusedImports) {
2005 ImportElement importElement = unusedImport.element;
2006 if (importElement != null) {
2007 LibraryElement libraryElement = importElement.importedLibrary;
2008 if (libraryElement != null && libraryElement.isDartCore) {
2009 continue;
2010 }
2011 }
2012 errorReporter.reportError2(HintCode.UNUSED_IMPORT, unusedImport.uri, []);
2013 }
2014 }
2015 Object visitCompilationUnit(CompilationUnit node) {
2016 if (_inDefiningCompilationUnit) {
2017 NodeList<Directive> directives = node.directives;
2018 for (Directive directive in directives) {
2019 if (directive is ImportDirective) {
2020 ImportDirective importDirective = directive as ImportDirective;
2021 LibraryElement libraryElement = importDirective.uriElement;
2022 if (libraryElement != null) {
2023 _unusedImports.add(importDirective);
2024 if (importDirective.asToken != null) {
2025 SimpleIdentifier prefixIdentifier = importDirective.prefix;
2026 if (prefixIdentifier != null) {
2027 Element element = prefixIdentifier.staticElement;
2028 if (element is PrefixElement) {
2029 PrefixElement prefixElementKey = element as PrefixElement;
2030 _prefixElementMap[prefixElementKey] = importDirective;
2031 }
2032 }
2033 }
2034 putIntoLibraryMap(libraryElement, importDirective);
2035 addAdditionalLibrariesForExports(libraryElement, importDirective, ne w List<LibraryElement>());
2036 }
2037 }
2038 }
2039 }
2040 if (_unusedImports.isEmpty) {
2041 return null;
2042 }
2043 if (_unusedImports.length > 1) {
2044 List<ImportDirective> importDirectiveArray = new List.from(_unusedImports) ;
2045 importDirectiveArray.sort(ImportDirective.COMPARATOR);
2046 ImportDirective currentDirective = importDirectiveArray[0];
2047 for (int i = 1; i < importDirectiveArray.length; i++) {
2048 ImportDirective nextDirective = importDirectiveArray[i];
2049 if (ImportDirective.COMPARATOR(currentDirective, nextDirective) == 0) {
2050 if (currentDirective.offset < nextDirective.offset) {
2051 _duplicateImports.add(nextDirective);
2052 } else {
2053 _duplicateImports.add(currentDirective);
2054 }
2055 }
2056 currentDirective = nextDirective;
2057 }
2058 }
2059 return super.visitCompilationUnit(node);
2060 }
2061 Object visitExportDirective(ExportDirective node) {
2062 visitMetadata(node.metadata);
2063 return null;
2064 }
2065 Object visitImportDirective(ImportDirective node) {
2066 visitMetadata(node.metadata);
2067 return null;
2068 }
2069 Object visitLibraryDirective(LibraryDirective node) {
2070 visitMetadata(node.metadata);
2071 return null;
2072 }
2073 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
2074 SimpleIdentifier prefixIdentifier = node.prefix;
2075 Element element = prefixIdentifier.staticElement;
2076 if (element is PrefixElement) {
2077 _unusedImports.remove(_prefixElementMap[element]);
2078 return null;
2079 }
2080 return visitIdentifier(element, prefixIdentifier.name);
2081 }
2082 Object visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node.st aticElement, node.name);
2083 void set inDefiningCompilationUnit(bool inDefiningCompilationUnit) {
2084 this._inDefiningCompilationUnit = inDefiningCompilationUnit;
2085 }
2086
2087 /**
2088 * Recursively add any exported library elements into the [libraryMap].
2089 */
2090 void addAdditionalLibrariesForExports(LibraryElement library, ImportDirective importDirective, List<LibraryElement> exportPath) {
2091 if (exportPath.contains(library)) {
2092 return;
2093 }
2094 exportPath.add(library);
2095 for (LibraryElement exportedLibraryElt in library.exportedLibraries) {
2096 putIntoLibraryMap(exportedLibraryElt, importDirective);
2097 addAdditionalLibrariesForExports(exportedLibraryElt, importDirective, expo rtPath);
2098 }
2099 }
2100
2101 /**
2102 * Lookup and return the [Namespace] from the [namespaceMap], if the map does not
2103 * have the computed namespace, compute it and cache it in the map. If the imp ort directive is not
2104 * resolved or is not resolvable, `null` is returned.
2105 *
2106 * @param importDirective the import directive used to compute the returned na mespace
2107 * @return the computed or looked up [Namespace]
2108 */
2109 Namespace computeNamespace(ImportDirective importDirective) {
2110 Namespace namespace = _namespaceMap[importDirective];
2111 if (namespace == null) {
2112 ImportElement importElement = importDirective.element;
2113 if (importElement != null) {
2114 NamespaceBuilder builder = new NamespaceBuilder();
2115 namespace = builder.createImportNamespace(importElement);
2116 _namespaceMap[importDirective] = namespace;
2117 }
2118 }
2119 return namespace;
2120 }
2121
2122 /**
2123 * The [libraryMap] is a mapping between a library elements and a list of impo rt
2124 * directives, but when adding these mappings into the [libraryMap], this meth od can be
2125 * used to simply add the mapping between the library element an an import dir ective without
2126 * needing to check to see if a list needs to be created.
2127 */
2128 void putIntoLibraryMap(LibraryElement libraryElement, ImportDirective importDi rective) {
2129 List<ImportDirective> importList = _libraryMap[libraryElement];
2130 if (importList == null) {
2131 importList = new List<ImportDirective>();
2132 _libraryMap[libraryElement] = importList;
2133 }
2134 importList.add(importDirective);
2135 }
2136 Object visitIdentifier(Element element, String name) {
2137 if (element == null) {
2138 return null;
2139 }
2140 if (element is MultiplyDefinedElement) {
2141 MultiplyDefinedElement multiplyDefinedElement = element as MultiplyDefined Element;
2142 for (Element elt in multiplyDefinedElement.conflictingElements) {
2143 visitIdentifier(elt, name);
2144 }
2145 return null;
2146 } else if (element is PrefixElement) {
2147 _unusedImports.remove(_prefixElementMap[element]);
2148 return null;
2149 }
2150 LibraryElement containingLibrary = element.library;
2151 if (containingLibrary == null) {
2152 return null;
2153 }
2154 if (_currentLibrary == containingLibrary) {
2155 return null;
2156 }
2157 List<ImportDirective> importsFromSameLibrary = _libraryMap[containingLibrary ];
2158 if (importsFromSameLibrary == null) {
2159 return null;
2160 }
2161 if (importsFromSameLibrary.length == 1) {
2162 ImportDirective usedImportDirective = importsFromSameLibrary[0];
2163 _unusedImports.remove(usedImportDirective);
2164 } else {
2165 for (ImportDirective importDirective in importsFromSameLibrary) {
2166 Namespace namespace = computeNamespace(importDirective);
2167 if (namespace != null && namespace.get(name) != null) {
2168 _unusedImports.remove(importDirective);
2169 }
2170 }
2171 }
2172 return null;
2173 }
2174
2175 /**
2176 * Given some [NodeList] of [Annotation]s, ensure that the identifiers are vis ited by
2177 * this visitor. Specifically, this covers the cases where AST nodes don't hav e their identifiers
2178 * visited by this visitor, but still need their annotations visited.
2179 *
2180 * @param annotations the list of annotations to visit
2181 */
2182 void visitMetadata(NodeList<Annotation> annotations) {
2183 for (Annotation annotation in annotations) {
2184 Identifier name = annotation.name;
2185 visitIdentifier(name.staticElement, name.name);
2186 }
2187 }
2188 }
2189 /**
2190 * Instances of the class `PubVerifier` traverse an AST structure looking for de viations from
2191 * pub best practices.
2192 */
2193 class PubVerifier extends RecursiveASTVisitor<Object> {
2194 static String _PUBSPEC_YAML = "pubspec.yaml";
2195
2196 /**
2197 * The analysis context containing the sources to be analyzed
2198 */
2199 AnalysisContext _context;
2200
2201 /**
2202 * The error reporter by which errors will be reported.
2203 */
2204 ErrorReporter _errorReporter;
2205 PubVerifier(AnalysisContext context, ErrorReporter errorReporter) {
2206 this._context = context;
2207 this._errorReporter = errorReporter;
2208 }
2209 Object visitImportDirective(ImportDirective directive) {
2210 return null;
2211 }
2212
2213 /**
2214 * This verifies that the passed file import directive is not contained in a s ource inside a
2215 * package "lib" directory hierarchy referencing a source outside that package "lib" directory
2216 * hierarchy.
2217 *
2218 * @param uriLiteral the import URL (not `null`)
2219 * @param path the file path being verified (not `null`)
2220 * @return `true` if and only if an error code is generated on the passed node
2221 * @see PubSuggestionCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE
2222 */
2223 bool checkForFileImportInsideLibReferencesFileOutside(StringLiteral uriLiteral , String path) {
2224 Source source = getSource(uriLiteral);
2225 String fullName = getSourceFullName(source);
2226 if (fullName != null) {
2227 int pathIndex = 0;
2228 int fullNameIndex = fullName.length;
2229 while (pathIndex < path.length && JavaString.startsWithBefore(path, "../", pathIndex)) {
2230 fullNameIndex = JavaString.lastIndexOf(fullName, '/', fullNameIndex);
2231 if (fullNameIndex < 4) {
2232 return false;
2233 }
2234 if (JavaString.startsWithBefore(fullName, "/lib", fullNameIndex - 4)) {
2235 String relativePubspecPath = path.substring(0, pathIndex + 3) + _PUBSP EC_YAML;
2236 Source pubspecSource = _context.sourceFactory.resolveUri(source, relat ivePubspecPath);
2237 if (pubspecSource != null && pubspecSource.exists()) {
2238 _errorReporter.reportError2(PubSuggestionCode.FILE_IMPORT_INSIDE_LIB _REFERENCES_FILE_OUTSIDE, uriLiteral, []);
2239 }
2240 return true;
2241 }
2242 pathIndex += 3;
2243 }
2244 }
2245 return false;
2246 }
2247
2248 /**
2249 * This verifies that the passed file import directive is not contained in a s ource outside a
2250 * package "lib" directory hierarchy referencing a source inside that package "lib" directory
2251 * hierarchy.
2252 *
2253 * @param uriLiteral the import URL (not `null`)
2254 * @param path the file path being verified (not `null`)
2255 * @return `true` if and only if an error code is generated on the passed node
2256 * @see PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE
2257 */
2258 bool checkForFileImportOutsideLibReferencesFileInside(StringLiteral uriLiteral , String path) {
2259 if (path.startsWith("lib/")) {
2260 if (checkForFileImportOutsideLibReferencesFileInside2(uriLiteral, path, 0) ) {
2261 return true;
2262 }
2263 }
2264 int pathIndex = path.indexOf("/lib/");
2265 while (pathIndex != -1) {
2266 if (checkForFileImportOutsideLibReferencesFileInside2(uriLiteral, path, pa thIndex + 1)) {
2267 return true;
2268 }
2269 pathIndex = JavaString.indexOf(path, "/lib/", pathIndex + 4);
2270 }
2271 return false;
2272 }
2273 bool checkForFileImportOutsideLibReferencesFileInside2(StringLiteral uriLitera l, String path, int pathIndex) {
2274 Source source = getSource(uriLiteral);
2275 String relativePubspecPath = path.substring(0, pathIndex) + _PUBSPEC_YAML;
2276 Source pubspecSource = _context.sourceFactory.resolveUri(source, relativePub specPath);
2277 if (pubspecSource == null || !pubspecSource.exists()) {
2278 return false;
2279 }
2280 String fullName = getSourceFullName(source);
2281 if (fullName != null) {
2282 if (!fullName.contains("/lib/")) {
2283 _errorReporter.reportError2(PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_RE FERENCES_FILE_INSIDE, uriLiteral, []);
2284 return true;
2285 }
2286 }
2287 return false;
2288 }
2289
2290 /**
2291 * This verifies that the passed package import directive does not contain ".. "
2292 *
2293 * @param uriLiteral the import URL (not `null`)
2294 * @param path the path to be validated (not `null`)
2295 * @return `true` if and only if an error code is generated on the passed node
2296 * @see PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
2297 */
2298 bool checkForPackageImportContainsDotDot(StringLiteral uriLiteral, String path ) {
2299 if (path.startsWith("../") || path.contains("/../")) {
2300 _errorReporter.reportError2(PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_ DOT, uriLiteral, []);
2301 return true;
2302 }
2303 return false;
2304 }
2305
2306 /**
2307 * Answer the source associated with the compilation unit containing the given AST node.
2308 *
2309 * @param node the node (not `null`)
2310 * @return the source or `null` if it could not be determined
2311 */
2312 Source getSource(ASTNode node) {
2313 Source source = null;
2314 CompilationUnit unit = node.getAncestor(CompilationUnit);
2315 if (unit != null) {
2316 CompilationUnitElement element = unit.element;
2317 if (element != null) {
2318 source = element.source;
2319 }
2320 }
2321 return source;
2322 }
2323
2324 /**
2325 * Answer the full name of the given source. The returned value will have all
2326 * [File#separatorChar] replace by '/'.
2327 *
2328 * @param source the source
2329 * @return the full name or `null` if it could not be determined
2330 */
2331 String getSourceFullName(Source source) {
2332 if (source != null) {
2333 String fullName = source.fullName;
2334 if (fullName != null) {
2335 return fullName.replaceAll(r'\', '/');
2336 }
2337 }
2338 return null;
2339 }
2340 }
2341 /**
2342 * Instances of the class `DeclarationResolver` are used to resolve declarations in an AST
2343 * structure to already built elements.
2344 */
2345 class DeclarationResolver extends RecursiveASTVisitor<Object> {
2346
2347 /**
2348 * The compilation unit containing the AST nodes being visited.
2349 */
2350 CompilationUnitElement _enclosingUnit;
2351
2352 /**
2353 * The function type alias containing the AST nodes being visited, or `null` i f we are not
2354 * in the scope of a function type alias.
2355 */
2356 FunctionTypeAliasElement _enclosingAlias;
2357
2358 /**
2359 * The class containing the AST nodes being visited, or `null` if we are not i n the scope of
2360 * a class.
2361 */
2362 ClassElement _enclosingClass;
2363
2364 /**
2365 * The method or function containing the AST nodes being visited, or `null` if we are not in
2366 * the scope of a method or function.
2367 */
2368 ExecutableElement _enclosingExecutable;
2369
2370 /**
2371 * The parameter containing the AST nodes being visited, or `null` if we are n ot in the
2372 * scope of a parameter.
2373 */
2374 ParameterElement _enclosingParameter;
2375
2376 /**
2377 * Resolve the declarations within the given compilation unit to the elements rooted at the given
2378 * element.
2379 *
2380 * @param unit the compilation unit to be resolved
2381 * @param element the root of the element model used to resolve the AST nodes
2382 */
2383 void resolve(CompilationUnit unit, CompilationUnitElement element) {
2384 _enclosingUnit = element;
2385 unit.element = element;
2386 unit.accept(this);
2387 }
2388 Object visitCatchClause(CatchClause node) {
2389 SimpleIdentifier exceptionParameter = node.exceptionParameter;
2390 if (exceptionParameter != null) {
2391 List<LocalVariableElement> localVariables = _enclosingExecutable.localVari ables;
2392 find3(localVariables, exceptionParameter);
2393 SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
2394 if (stackTraceParameter != null) {
2395 find3(localVariables, stackTraceParameter);
2396 }
2397 }
2398 return super.visitCatchClause(node);
2399 }
2400 Object visitClassDeclaration(ClassDeclaration node) {
2401 ClassElement outerClass = _enclosingClass;
2402 try {
2403 SimpleIdentifier className = node.name;
2404 _enclosingClass = find3(_enclosingUnit.types, className);
2405 return super.visitClassDeclaration(node);
2406 } finally {
2407 _enclosingClass = outerClass;
2408 }
2409 }
2410 Object visitClassTypeAlias(ClassTypeAlias node) {
2411 ClassElement outerClass = _enclosingClass;
2412 try {
2413 SimpleIdentifier className = node.name;
2414 _enclosingClass = find3(_enclosingUnit.types, className);
2415 return super.visitClassTypeAlias(node);
2416 } finally {
2417 _enclosingClass = outerClass;
2418 }
2419 }
2420 Object visitConstructorDeclaration(ConstructorDeclaration node) {
2421 ExecutableElement outerExecutable = _enclosingExecutable;
2422 try {
2423 SimpleIdentifier constructorName = node.name;
2424 if (constructorName == null) {
2425 _enclosingExecutable = _enclosingClass.unnamedConstructor;
2426 } else {
2427 _enclosingExecutable = _enclosingClass.getNamedConstructor(constructorNa me.name);
2428 constructorName.staticElement = _enclosingExecutable;
2429 }
2430 node.element = _enclosingExecutable as ConstructorElement;
2431 return super.visitConstructorDeclaration(node);
2432 } finally {
2433 _enclosingExecutable = outerExecutable;
2434 }
2435 }
2436 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
2437 SimpleIdentifier variableName = node.identifier;
2438 find3(_enclosingExecutable.localVariables, variableName);
2439 return super.visitDeclaredIdentifier(node);
2440 }
2441 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
2442 SimpleIdentifier parameterName = node.parameter.identifier;
2443 ParameterElement element = getElementForParameter(node, parameterName);
2444 Expression defaultValue = node.defaultValue;
2445 if (defaultValue != null) {
2446 ExecutableElement outerExecutable = _enclosingExecutable;
2447 try {
2448 if (element == null) {
2449 } else {
2450 _enclosingExecutable = element.initializer;
2451 }
2452 defaultValue.accept(this);
2453 } finally {
2454 _enclosingExecutable = outerExecutable;
2455 }
2456 }
2457 ParameterElement outerParameter = _enclosingParameter;
2458 try {
2459 _enclosingParameter = element;
2460 return super.visitDefaultFormalParameter(node);
2461 } finally {
2462 _enclosingParameter = outerParameter;
2463 }
2464 }
2465 Object visitExportDirective(ExportDirective node) {
2466 String uri = getStringValue(node.uri);
2467 if (uri != null) {
2468 LibraryElement library = _enclosingUnit.library;
2469 ExportElement exportElement = find5(library.exports, _enclosingUnit.contex t.sourceFactory.resolveUri(_enclosingUnit.source, uri));
2470 node.element = exportElement;
2471 }
2472 return super.visitExportDirective(node);
2473 }
2474 Object visitFieldFormalParameter(FieldFormalParameter node) {
2475 if (node.parent is! DefaultFormalParameter) {
2476 SimpleIdentifier parameterName = node.identifier;
2477 ParameterElement element = getElementForParameter(node, parameterName);
2478 ParameterElement outerParameter = _enclosingParameter;
2479 try {
2480 _enclosingParameter = element;
2481 return super.visitFieldFormalParameter(node);
2482 } finally {
2483 _enclosingParameter = outerParameter;
2484 }
2485 } else {
2486 return super.visitFieldFormalParameter(node);
2487 }
2488 }
2489 Object visitFunctionDeclaration(FunctionDeclaration node) {
2490 ExecutableElement outerExecutable = _enclosingExecutable;
2491 try {
2492 SimpleIdentifier functionName = node.name;
2493 sc.Token property = node.propertyKeyword;
2494 if (property == null) {
2495 if (_enclosingExecutable != null) {
2496 _enclosingExecutable = find3(_enclosingExecutable.functions, functionN ame);
2497 } else {
2498 _enclosingExecutable = find3(_enclosingUnit.functions, functionName);
2499 }
2500 } else {
2501 PropertyAccessorElement accessor = find3(_enclosingUnit.accessors, funct ionName);
2502 if (identical(((property as sc.KeywordToken)).keyword, sc.Keyword.SET)) {
2503 accessor = accessor.variable.setter;
2504 functionName.staticElement = accessor;
2505 }
2506 _enclosingExecutable = accessor;
2507 }
2508 node.functionExpression.element = _enclosingExecutable;
2509 return super.visitFunctionDeclaration(node);
2510 } finally {
2511 _enclosingExecutable = outerExecutable;
2512 }
2513 }
2514 Object visitFunctionExpression(FunctionExpression node) {
2515 if (node.parent is! FunctionDeclaration) {
2516 FunctionElement element = find2(_enclosingExecutable.functions, node.begin Token.offset);
2517 node.element = element;
2518 }
2519 ExecutableElement outerExecutable = _enclosingExecutable;
2520 try {
2521 _enclosingExecutable = node.element;
2522 return super.visitFunctionExpression(node);
2523 } finally {
2524 _enclosingExecutable = outerExecutable;
2525 }
2526 }
2527 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
2528 FunctionTypeAliasElement outerAlias = _enclosingAlias;
2529 try {
2530 SimpleIdentifier aliasName = node.name;
2531 _enclosingAlias = find3(_enclosingUnit.functionTypeAliases, aliasName);
2532 return super.visitFunctionTypeAlias(node);
2533 } finally {
2534 _enclosingAlias = outerAlias;
2535 }
2536 }
2537 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
2538 if (node.parent is! DefaultFormalParameter) {
2539 SimpleIdentifier parameterName = node.identifier;
2540 ParameterElement element = getElementForParameter(node, parameterName);
2541 ParameterElement outerParameter = _enclosingParameter;
2542 try {
2543 _enclosingParameter = element;
2544 return super.visitFunctionTypedFormalParameter(node);
2545 } finally {
2546 _enclosingParameter = outerParameter;
2547 }
2548 } else {
2549 return super.visitFunctionTypedFormalParameter(node);
2550 }
2551 }
2552 Object visitImportDirective(ImportDirective node) {
2553 String uri = getStringValue(node.uri);
2554 if (uri != null) {
2555 LibraryElement library = _enclosingUnit.library;
2556 ImportElement importElement = find6(library.imports, _enclosingUnit.contex t.sourceFactory.resolveUri(_enclosingUnit.source, uri), node.prefix);
2557 node.element = importElement;
2558 }
2559 return super.visitImportDirective(node);
2560 }
2561 Object visitLabeledStatement(LabeledStatement node) {
2562 for (Label label in node.labels) {
2563 SimpleIdentifier labelName = label.label;
2564 find3(_enclosingExecutable.labels, labelName);
2565 }
2566 return super.visitLabeledStatement(node);
2567 }
2568 Object visitLibraryDirective(LibraryDirective node) {
2569 node.element = _enclosingUnit.library;
2570 return super.visitLibraryDirective(node);
2571 }
2572 Object visitMethodDeclaration(MethodDeclaration node) {
2573 ExecutableElement outerExecutable = _enclosingExecutable;
2574 try {
2575 sc.Token property = node.propertyKeyword;
2576 SimpleIdentifier methodName = node.name;
2577 String nameOfMethod = methodName.name;
2578 if (nameOfMethod == sc.TokenType.MINUS.lexeme && node.parameters.parameter s.length == 0) {
2579 nameOfMethod = "unary-";
2580 }
2581 if (property == null) {
2582 _enclosingExecutable = find4(_enclosingClass.methods, nameOfMethod, meth odName.offset);
2583 methodName.staticElement = _enclosingExecutable;
2584 } else {
2585 PropertyAccessorElement accessor = find3(_enclosingClass.accessors, meth odName);
2586 if (identical(((property as sc.KeywordToken)).keyword, sc.Keyword.SET)) {
2587 accessor = accessor.variable.setter;
2588 methodName.staticElement = accessor;
2589 }
2590 _enclosingExecutable = accessor;
2591 }
2592 return super.visitMethodDeclaration(node);
2593 } finally {
2594 _enclosingExecutable = outerExecutable;
2595 }
2596 }
2597 Object visitPartDirective(PartDirective node) {
2598 String uri = getStringValue(node.uri);
2599 if (uri != null) {
2600 Source partSource = _enclosingUnit.context.sourceFactory.resolveUri(_enclo singUnit.source, uri);
2601 node.element = find(_enclosingUnit.library.parts, partSource);
2602 }
2603 return super.visitPartDirective(node);
2604 }
2605 Object visitPartOfDirective(PartOfDirective node) {
2606 node.element = _enclosingUnit.library;
2607 return super.visitPartOfDirective(node);
2608 }
2609 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
2610 if (node.parent is! DefaultFormalParameter) {
2611 SimpleIdentifier parameterName = node.identifier;
2612 ParameterElement element = getElementForParameter(node, parameterName);
2613 ParameterElement outerParameter = _enclosingParameter;
2614 try {
2615 _enclosingParameter = element;
2616 return super.visitSimpleFormalParameter(node);
2617 } finally {
2618 _enclosingParameter = outerParameter;
2619 }
2620 } else {
2621 }
2622 return super.visitSimpleFormalParameter(node);
2623 }
2624 Object visitSwitchCase(SwitchCase node) {
2625 for (Label label in node.labels) {
2626 SimpleIdentifier labelName = label.label;
2627 find3(_enclosingExecutable.labels, labelName);
2628 }
2629 return super.visitSwitchCase(node);
2630 }
2631 Object visitSwitchDefault(SwitchDefault node) {
2632 for (Label label in node.labels) {
2633 SimpleIdentifier labelName = label.label;
2634 find3(_enclosingExecutable.labels, labelName);
2635 }
2636 return super.visitSwitchDefault(node);
2637 }
2638 Object visitTypeParameter(TypeParameter node) {
2639 SimpleIdentifier parameterName = node.name;
2640 if (_enclosingClass != null) {
2641 find3(_enclosingClass.typeParameters, parameterName);
2642 } else if (_enclosingAlias != null) {
2643 find3(_enclosingAlias.typeParameters, parameterName);
2644 }
2645 return super.visitTypeParameter(node);
2646 }
2647 Object visitVariableDeclaration(VariableDeclaration node) {
2648 VariableElement element = null;
2649 SimpleIdentifier variableName = node.name;
2650 if (_enclosingExecutable != null) {
2651 element = find3(_enclosingExecutable.localVariables, variableName);
2652 }
2653 if (element == null && _enclosingClass != null) {
2654 element = find3(_enclosingClass.fields, variableName);
2655 }
2656 if (element == null && _enclosingUnit != null) {
2657 element = find3(_enclosingUnit.topLevelVariables, variableName);
2658 }
2659 Expression initializer = node.initializer;
2660 if (initializer != null) {
2661 ExecutableElement outerExecutable = _enclosingExecutable;
2662 try {
2663 if (element == null) {
2664 } else {
2665 _enclosingExecutable = element.initializer;
2666 }
2667 return super.visitVariableDeclaration(node);
2668 } finally {
2669 _enclosingExecutable = outerExecutable;
2670 }
2671 }
2672 return super.visitVariableDeclaration(node);
2673 }
2674
2675 /**
2676 * Return the element for the part with the given source, or `null` if there i s no element
2677 * for the given source.
2678 *
2679 * @param parts the elements for the parts
2680 * @param partSource the source for the part whose element is to be returned
2681 * @return the element for the part with the given source
2682 */
2683 CompilationUnitElement find(List<CompilationUnitElement> parts, Source partSou rce) {
2684 for (CompilationUnitElement part in parts) {
2685 if (part.source == partSource) {
2686 return part;
2687 }
2688 }
2689 return null;
2690 }
2691
2692 /**
2693 * Return the element in the given array of elements that was created for the declaration at the
2694 * given offset. This method should only be used when there is no name
2695 *
2696 * @param elements the elements of the appropriate kind that exist in the curr ent context
2697 * @param offset the offset of the name of the element to be returned
2698 * @return the element at the given offset
2699 */
2700 Element find2(List<Element> elements, int offset) => find4(elements, "", offse t);
2701
2702 /**
2703 * Return the element in the given array of elements that was created for the declaration with the
2704 * given name.
2705 *
2706 * @param elements the elements of the appropriate kind that exist in the curr ent context
2707 * @param identifier the name node in the declaration of the element to be ret urned
2708 * @return the element created for the declaration with the given name
2709 */
2710 Element find3(List<Element> elements, SimpleIdentifier identifier) {
2711 Element element = find4(elements, identifier.name, identifier.offset);
2712 identifier.staticElement = element;
2713 return element;
2714 }
2715
2716 /**
2717 * Return the element in the given array of elements that was created for the declaration with the
2718 * given name at the given offset.
2719 *
2720 * @param elements the elements of the appropriate kind that exist in the curr ent context
2721 * @param name the name of the element to be returned
2722 * @param offset the offset of the name of the element to be returned
2723 * @return the element with the given name and offset
2724 */
2725 Element find4(List<Element> elements, String name, int offset) {
2726 for (Element element in elements) {
2727 if (element.displayName == name && element.nameOffset == offset) {
2728 return element;
2729 }
2730 }
2731 return null;
2732 }
2733
2734 /**
2735 * Return the export element from the given array whose library has the given source, or
2736 * `null` if there is no such export.
2737 *
2738 * @param exports the export elements being searched
2739 * @param source the source of the library associated with the export element to being searched
2740 * for
2741 * @return the export element whose library has the given source
2742 */
2743 ExportElement find5(List<ExportElement> exports, Source source) {
2744 for (ExportElement export in exports) {
2745 if (export.exportedLibrary.source == source) {
2746 return export;
2747 }
2748 }
2749 return null;
2750 }
2751
2752 /**
2753 * Return the import element from the given array whose library has the given source and that has
2754 * the given prefix, or `null` if there is no such import.
2755 *
2756 * @param imports the import elements being searched
2757 * @param source the source of the library associated with the import element to being searched
2758 * for
2759 * @param prefix the prefix with which the library was imported
2760 * @return the import element whose library has the given source and prefix
2761 */
2762 ImportElement find6(List<ImportElement> imports, Source source, SimpleIdentifi er prefix) {
2763 for (ImportElement element in imports) {
2764 if (element.importedLibrary.source == source) {
2765 PrefixElement prefixElement = element.prefix;
2766 if (prefix == null) {
2767 if (prefixElement == null) {
2768 return element;
2769 }
2770 } else {
2771 if (prefixElement != null && prefix.name == prefixElement.displayName) {
2772 return element;
2773 }
2774 }
2775 }
2776 }
2777 return null;
2778 }
2779
2780 /**
2781 * Search the most closely enclosing list of parameters for a parameter with t he given name.
2782 *
2783 * @param node the node defining the parameter with the given name
2784 * @param parameterName the name of the parameter being searched for
2785 * @return the element representing the parameter with that name
2786 */
2787 ParameterElement getElementForParameter(FormalParameter node, SimpleIdentifier parameterName) {
2788 List<ParameterElement> parameters = null;
2789 if (_enclosingParameter != null) {
2790 parameters = _enclosingParameter.parameters;
2791 }
2792 if (parameters == null && _enclosingExecutable != null) {
2793 parameters = _enclosingExecutable.parameters;
2794 }
2795 if (parameters == null && _enclosingAlias != null) {
2796 parameters = _enclosingAlias.parameters;
2797 }
2798 ParameterElement element = parameters == null ? null : find3(parameters, par ameterName);
2799 if (element == null) {
2800 PrintStringWriter writer = new PrintStringWriter();
2801 writer.println("Invalid state found in the Analysis Engine:");
2802 writer.println("DeclarationResolver.getElementForParameter() is visiting a parameter that does not appear to be in a method or function.");
2803 writer.println("Ancestors:");
2804 ASTNode parent = node.parent;
2805 while (parent != null) {
2806 writer.println(parent.runtimeType.toString());
2807 writer.println("---------");
2808 parent = parent.parent;
2809 }
2810 AnalysisEngine.instance.logger.logError2(writer.toString(), new AnalysisEx ception());
2811 }
2812 return element;
2813 }
2814
2815 /**
2816 * Return the value of the given string literal, or `null` if the string is no t a constant
2817 * string without any string interpolation.
2818 *
2819 * @param literal the string literal whose value is to be returned
2820 * @return the value of the given string literal
2821 */
2822 String getStringValue(StringLiteral literal) {
2823 if (literal is StringInterpolation) {
2824 return null;
2825 }
2826 return literal.stringValue;
2827 }
2828 }
2829 /**
2830 * Instances of the class `ElementResolver` are used by instances of [ResolverVi sitor]
2831 * to resolve references within the AST structure to the elements being referenc ed. The requirements
2832 * for the element resolver are:
2833 * <ol>
2834 * * Every [SimpleIdentifier] should be resolved to the element to which it refe rs.
2835 * Specifically:
2836 *
2837 * * An identifier within the declaration of that name should resolve to the ele ment being
2838 * declared.
2839 * * An identifier denoting a prefix should resolve to the element representing the import that
2840 * defines the prefix (an [ImportElement]).
2841 * * An identifier denoting a variable should resolve to the element representin g the variable (a
2842 * [VariableElement]).
2843 * * An identifier denoting a parameter should resolve to the element representi ng the parameter
2844 * (a [ParameterElement]).
2845 * * An identifier denoting a field should resolve to the element representing t he getter or
2846 * setter being invoked (a [PropertyAccessorElement]).
2847 * * An identifier denoting the name of a method or function being invoked shoul d resolve to the
2848 * element representing the method or function (a [ExecutableElement]).
2849 * * An identifier denoting a label should resolve to the element representing t he label (a
2850 * [LabelElement]).
2851 *
2852 * The identifiers within directives are exceptions to this rule and are covered below.
2853 * * Every node containing a token representing an operator that can be overridd en (
2854 * [BinaryExpression], [PrefixExpression], [PostfixExpression]) should resolve t o
2855 * the element representing the method invoked by that operator (a [MethodElemen t]).
2856 * * Every [FunctionExpressionInvocation] should resolve to the element represen ting the
2857 * function being invoked (a [FunctionElement]). This will be the same element a s that to
2858 * which the name is resolved if the function has a name, but is provided for th ose cases where an
2859 * unnamed function is being invoked.
2860 * * Every [LibraryDirective] and [PartOfDirective] should resolve to the elemen t
2861 * representing the library being specified by the directive (a [LibraryElement] ) unless, in
2862 * the case of a part-of directive, the specified library does not exist.
2863 * * Every [ImportDirective] and [ExportDirective] should resolve to the element
2864 * representing the library being specified by the directive unless the specifie d library does not
2865 * exist (an [ImportElement] or [ExportElement]).
2866 * * The identifier representing the prefix in an [ImportDirective] should resol ve to the
2867 * element representing the prefix (a [PrefixElement]).
2868 * * The identifiers in the hide and show combinators in [ImportDirective]s and
2869 * [ExportDirective]s should resolve to the elements that are being hidden or sh own,
2870 * respectively, unless those names are not defined in the specified library (or the specified
2871 * library does not exist).
2872 * * Every [PartDirective] should resolve to the element representing the compil ation unit
2873 * being specified by the string unless the specified compilation unit does not exist (a
2874 * [CompilationUnitElement]).
2875 * </ol>
2876 * Note that AST nodes that would represent elements that are not defined are no t resolved to
2877 * anything. This includes such things as references to undeclared variables (wh ich is an error) and
2878 * names in hide and show combinators that are not defined in the imported libra ry (which is not an
2879 * error).
2880 *
2881 * @coverage dart.engine.resolver
2882 */
2883 class ElementResolver extends SimpleASTVisitor<Object> {
2884
2885 /**
2886 * @return `true` if the given identifier is the return type of a constructor declaration.
2887 */
2888 static bool isConstructorReturnType(SimpleIdentifier node) {
2889 ASTNode parent = node.parent;
2890 if (parent is ConstructorDeclaration) {
2891 ConstructorDeclaration constructor = parent as ConstructorDeclaration;
2892 return identical(constructor.returnType, node);
2893 }
2894 return false;
2895 }
2896
2897 /**
2898 * @return `true` if the given identifier is the return type of a factory cons tructor
2899 * declaration.
2900 */
2901 static bool isFactoryConstructorReturnType(SimpleIdentifier node) {
2902 ASTNode parent = node.parent;
2903 if (parent is ConstructorDeclaration) {
2904 ConstructorDeclaration constructor = parent as ConstructorDeclaration;
2905 return identical(constructor.returnType, node) && constructor.factoryKeywo rd != null;
2906 }
2907 return false;
2908 }
2909
2910 /**
2911 * Checks if the given 'super' expression is used in the valid context.
2912 *
2913 * @param node the 'super' expression to analyze
2914 * @return `true` if the given 'super' expression is in the valid context
2915 */
2916 static bool isSuperInValidContext(SuperExpression node) {
2917 for (ASTNode n = node; n != null; n = n.parent) {
2918 if (n is CompilationUnit) {
2919 return false;
2920 }
2921 if (n is ConstructorDeclaration) {
2922 ConstructorDeclaration constructor = n as ConstructorDeclaration;
2923 return constructor.factoryKeyword == null;
2924 }
2925 if (n is ConstructorFieldInitializer) {
2926 return false;
2927 }
2928 if (n is MethodDeclaration) {
2929 MethodDeclaration method = n as MethodDeclaration;
2930 return !method.isStatic;
2931 }
2932 }
2933 return false;
2934 }
2935
2936 /**
2937 * The resolver driving this participant.
2938 */
2939 ResolverVisitor _resolver;
2940
2941 /**
2942 * A flag indicating whether we are running in strict mode. In strict mode, er ror reporting is
2943 * based exclusively on the static type information.
2944 */
2945 bool _strictMode = false;
2946
2947 /**
2948 * A flag indicating whether we should generate hints.
2949 */
2950 bool _enableHints = false;
2951
2952 /**
2953 * The type representing the type 'dynamic'.
2954 */
2955 Type2 _dynamicType;
2956
2957 /**
2958 * The type representing the type 'type'.
2959 */
2960 Type2 _typeType;
2961
2962 /**
2963 * A utility class for the resolver to answer the question of "what are my sub types?".
2964 */
2965 SubtypeManager _subtypeManager;
2966
2967 /**
2968 * The object keeping track of which elements have had their types promoted.
2969 */
2970 TypePromotionManager _promoteManager;
2971
2972 /**
2973 * The name of the method that can be implemented by a class to allow its inst ances to be invoked
2974 * as if they were a function.
2975 */
2976 static String CALL_METHOD_NAME = "call";
2977
2978 /**
2979 * The name of the method that will be invoked if an attempt is made to invoke an undefined method
2980 * on an object.
2981 */
2982 static String NO_SUCH_METHOD_METHOD_NAME = "noSuchMethod";
2983
2984 /**
2985 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
2986 *
2987 * @param resolver the resolver driving this participant
2988 */
2989 ElementResolver(ResolverVisitor resolver) {
2990 this._resolver = resolver;
2991 AnalysisOptions options = resolver.definingLibrary.context.analysisOptions;
2992 _strictMode = options.strictMode;
2993 _enableHints = options.hint;
2994 _dynamicType = resolver.typeProvider.dynamicType;
2995 _typeType = resolver.typeProvider.typeType;
2996 _subtypeManager = new SubtypeManager();
2997 _promoteManager = resolver.promoteManager;
2998 }
2999 Object visitAssignmentExpression(AssignmentExpression node) {
3000 sc.Token operator = node.operator;
3001 sc.TokenType operatorType = operator.type;
3002 if (operatorType != sc.TokenType.EQ) {
3003 operatorType = operatorFromCompoundAssignment(operatorType);
3004 Expression leftHandSide = node.leftHandSide;
3005 if (leftHandSide != null) {
3006 String methodName = operatorType.lexeme;
3007 Type2 staticType = getStaticType(leftHandSide);
3008 MethodElement staticMethod = lookUpMethod(leftHandSide, staticType, meth odName);
3009 node.staticElement = staticMethod;
3010 Type2 propagatedType = getPropagatedType(leftHandSide);
3011 MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedTy pe, methodName);
3012 node.propagatedElement = propagatedMethod;
3013 bool shouldReportMissingMember_static = shouldReportMissingMember(static Type, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
3014 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_s tatic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMeth od) : false;
3015 if (shouldReportMissingMember_propagated) {
3016 if (memberFoundInSubclass(propagatedType.element, methodName, true, fa lse)) {
3017 shouldReportMissingMember_propagated = false;
3018 }
3019 }
3020 if (shouldReportMissingMember_static || shouldReportMissingMember_propag ated) {
3021 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_METHOD : HintCode.UNDEFINED_METHOD) as ErrorCode;
3022 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissin gMember_static ? staticType.element : propagatedType.element, errorCode, operato r, [
3023 methodName,
3024 shouldReportMissingMember_static ? staticType.displayName : propag atedType.displayName]);
3025 }
3026 }
3027 }
3028 return null;
3029 }
3030 Object visitBinaryExpression(BinaryExpression node) {
3031 sc.Token operator = node.operator;
3032 if (operator.isUserDefinableOperator) {
3033 Expression leftOperand = node.leftOperand;
3034 if (leftOperand != null) {
3035 String methodName = operator.lexeme;
3036 Type2 staticType = getStaticType(leftOperand);
3037 MethodElement staticMethod = lookUpMethod(leftOperand, staticType, metho dName);
3038 node.staticElement = staticMethod;
3039 Type2 propagatedType = getPropagatedType(leftOperand);
3040 MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedTyp e, methodName);
3041 node.propagatedElement = propagatedMethod;
3042 bool shouldReportMissingMember_static = shouldReportMissingMember(static Type, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod));
3043 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_s tatic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMeth od) : false;
3044 if (shouldReportMissingMember_propagated) {
3045 if (memberFoundInSubclass(propagatedType.element, methodName, true, fa lse)) {
3046 shouldReportMissingMember_propagated = false;
3047 }
3048 }
3049 if (shouldReportMissingMember_static || shouldReportMissingMember_propag ated) {
3050 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
3051 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissin gMember_static ? staticType.element : propagatedType.element, errorCode, operato r, [
3052 methodName,
3053 shouldReportMissingMember_static ? staticType.displayName : propag atedType.displayName]);
3054 }
3055 }
3056 }
3057 return null;
3058 }
3059 Object visitBreakStatement(BreakStatement node) {
3060 SimpleIdentifier labelNode = node.label;
3061 LabelElementImpl labelElement = lookupLabel(node, labelNode);
3062 if (labelElement != null && labelElement.isOnSwitchMember) {
3063 _resolver.reportError5(ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, lab elNode, []);
3064 }
3065 return null;
3066 }
3067 Object visitClassDeclaration(ClassDeclaration node) {
3068 setMetadata(node.element, node);
3069 return null;
3070 }
3071 Object visitClassTypeAlias(ClassTypeAlias node) {
3072 setMetadata(node.element, node);
3073 return null;
3074 }
3075 Object visitCommentReference(CommentReference node) {
3076 Identifier identifier = node.identifier;
3077 if (identifier is SimpleIdentifier) {
3078 SimpleIdentifier simpleIdentifier = identifier as SimpleIdentifier;
3079 Element element = resolveSimpleIdentifier(simpleIdentifier);
3080 if (element == null) {
3081 element = findImportWithoutPrefix(simpleIdentifier);
3082 if (element is MultiplyDefinedElement) {
3083 element = null;
3084 }
3085 }
3086 if (element == null) {
3087 } else {
3088 if (element.library == null || element.library != _resolver.definingLibr ary) {
3089 }
3090 simpleIdentifier.staticElement = element;
3091 if (node.newKeyword != null) {
3092 if (element is ClassElement) {
3093 ConstructorElement constructor = ((element as ClassElement)).unnamed Constructor;
3094 if (constructor == null) {
3095 } else {
3096 simpleIdentifier.staticElement = constructor;
3097 }
3098 } else {
3099 }
3100 }
3101 }
3102 } else if (identifier is PrefixedIdentifier) {
3103 PrefixedIdentifier prefixedIdentifier = identifier as PrefixedIdentifier;
3104 SimpleIdentifier prefix = prefixedIdentifier.prefix;
3105 SimpleIdentifier name = prefixedIdentifier.identifier;
3106 Element element = resolveSimpleIdentifier(prefix);
3107 if (element == null) {
3108 } else {
3109 if (element is PrefixElement) {
3110 prefix.staticElement = element;
3111 element = _resolver.nameScope.lookup(identifier, _resolver.definingLib rary);
3112 name.staticElement = element;
3113 return null;
3114 }
3115 LibraryElement library = element.library;
3116 if (library == null) {
3117 AnalysisEngine.instance.logger.logError("Found element with null libra ry: ${element.name}");
3118 } else if (library != _resolver.definingLibrary) {
3119 }
3120 name.staticElement = element;
3121 if (node.newKeyword == null) {
3122 if (element is ClassElement) {
3123 Element memberElement = lookupGetterOrMethod(((element as ClassEleme nt)).type, name.name);
3124 if (memberElement == null) {
3125 memberElement = ((element as ClassElement)).getNamedConstructor(na me.name);
3126 if (memberElement == null) {
3127 memberElement = lookUpSetter(prefix, ((element as ClassElement)) .type, name.name);
3128 }
3129 }
3130 if (memberElement == null) {
3131 } else {
3132 name.staticElement = memberElement;
3133 }
3134 } else {
3135 }
3136 } else {
3137 if (element is ClassElement) {
3138 ConstructorElement constructor = ((element as ClassElement)).getName dConstructor(name.name);
3139 if (constructor == null) {
3140 } else {
3141 name.staticElement = constructor;
3142 }
3143 } else {
3144 }
3145 }
3146 }
3147 }
3148 return null;
3149 }
3150 Object visitConstructorDeclaration(ConstructorDeclaration node) {
3151 super.visitConstructorDeclaration(node);
3152 ConstructorElement element = node.element;
3153 if (element is ConstructorElementImpl) {
3154 ConstructorElementImpl constructorElement = element as ConstructorElementI mpl;
3155 ConstructorName redirectedNode = node.redirectedConstructor;
3156 if (redirectedNode != null) {
3157 ConstructorElement redirectedElement = redirectedNode.staticElement;
3158 constructorElement.redirectedConstructor = redirectedElement;
3159 }
3160 for (ConstructorInitializer initializer in node.initializers) {
3161 if (initializer is RedirectingConstructorInvocation) {
3162 ConstructorElement redirectedElement = ((initializer as RedirectingCon structorInvocation)).staticElement;
3163 constructorElement.redirectedConstructor = redirectedElement;
3164 }
3165 }
3166 setMetadata(constructorElement, node);
3167 }
3168 return null;
3169 }
3170 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
3171 SimpleIdentifier fieldName = node.fieldName;
3172 ClassElement enclosingClass = _resolver.enclosingClass;
3173 FieldElement fieldElement = ((enclosingClass as ClassElementImpl)).getField( fieldName.name);
3174 fieldName.staticElement = fieldElement;
3175 if (fieldElement == null || fieldElement.isSynthetic) {
3176 _resolver.reportError5(CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTANT_F IELD, node, [fieldName]);
3177 } else if (fieldElement.isStatic) {
3178 _resolver.reportError5(CompileTimeErrorCode.INITIALIZER_FOR_STATIC_FIELD, node, [fieldName]);
3179 }
3180 return null;
3181 }
3182 Object visitConstructorName(ConstructorName node) {
3183 Type2 type = node.type.type;
3184 if (type != null && type.isDynamic) {
3185 return null;
3186 } else if (type is! InterfaceType) {
3187 ASTNode parent = node.parent;
3188 if (parent is InstanceCreationExpression) {
3189 if (((parent as InstanceCreationExpression)).isConst) {
3190 } else {
3191 }
3192 } else {
3193 }
3194 return null;
3195 }
3196 ConstructorElement constructor;
3197 SimpleIdentifier name = node.name;
3198 InterfaceType interfaceType = type as InterfaceType;
3199 LibraryElement definingLibrary = _resolver.definingLibrary;
3200 if (name == null) {
3201 constructor = interfaceType.lookUpConstructor(null, definingLibrary);
3202 } else {
3203 constructor = interfaceType.lookUpConstructor(name.name, definingLibrary);
3204 name.staticElement = constructor;
3205 }
3206 node.staticElement = constructor;
3207 return null;
3208 }
3209 Object visitContinueStatement(ContinueStatement node) {
3210 SimpleIdentifier labelNode = node.label;
3211 LabelElementImpl labelElement = lookupLabel(node, labelNode);
3212 if (labelElement != null && labelElement.isOnSwitchStatement) {
3213 _resolver.reportError5(ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH, labelNo de, []);
3214 }
3215 return null;
3216 }
3217 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
3218 setMetadata(node.element, node);
3219 return null;
3220 }
3221 Object visitExportDirective(ExportDirective node) {
3222 Element element = node.element;
3223 if (element is ExportElement) {
3224 resolveCombinators(((element as ExportElement)).exportedLibrary, node.comb inators);
3225 setMetadata(element, node);
3226 }
3227 return null;
3228 }
3229 Object visitFieldFormalParameter(FieldFormalParameter node) {
3230 String fieldName = node.identifier.name;
3231 ClassElement classElement = _resolver.enclosingClass;
3232 if (classElement != null) {
3233 FieldElement fieldElement = ((classElement as ClassElementImpl)).getField( fieldName);
3234 if (fieldElement == null) {
3235 _resolver.reportError5(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_ EXISTANT_FIELD, node, [fieldName]);
3236 } else {
3237 ParameterElement parameterElement = node.element;
3238 if (parameterElement is FieldFormalParameterElementImpl) {
3239 FieldFormalParameterElementImpl fieldFormal = parameterElement as Fiel dFormalParameterElementImpl;
3240 fieldFormal.field = fieldElement;
3241 Type2 declaredType = fieldFormal.type;
3242 Type2 fieldType = fieldElement.type;
3243 if (node.type == null) {
3244 fieldFormal.type = fieldType;
3245 }
3246 if (fieldElement.isSynthetic) {
3247 _resolver.reportError5(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ NON_EXISTANT_FIELD, node, [fieldName]);
3248 } else if (fieldElement.isStatic) {
3249 _resolver.reportError5(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ STATIC_FIELD, node, [fieldName]);
3250 } else if (declaredType != null && fieldType != null && !declaredType. isAssignableTo(fieldType)) {
3251 _resolver.reportError5(StaticWarningCode.FIELD_INITIALIZING_FORMAL_N OT_ASSIGNABLE, node, [declaredType.displayName, fieldType.displayName]);
3252 }
3253 } else {
3254 if (fieldElement.isSynthetic) {
3255 _resolver.reportError5(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ NON_EXISTANT_FIELD, node, [fieldName]);
3256 } else if (fieldElement.isStatic) {
3257 _resolver.reportError5(CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_ STATIC_FIELD, node, [fieldName]);
3258 }
3259 }
3260 }
3261 }
3262 return super.visitFieldFormalParameter(node);
3263 }
3264 Object visitFunctionDeclaration(FunctionDeclaration node) {
3265 setMetadata(node.element, node);
3266 return null;
3267 }
3268 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) => null;
3269 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
3270 setMetadata(node.element, node);
3271 return null;
3272 }
3273 Object visitImportDirective(ImportDirective node) {
3274 SimpleIdentifier prefixNode = node.prefix;
3275 if (prefixNode != null) {
3276 String prefixName = prefixNode.name;
3277 for (PrefixElement prefixElement in _resolver.definingLibrary.prefixes) {
3278 if (prefixElement.displayName == prefixName) {
3279 prefixNode.staticElement = prefixElement;
3280 break;
3281 }
3282 }
3283 }
3284 ImportElement importElement = node.element;
3285 if (importElement != null) {
3286 LibraryElement library = importElement.importedLibrary;
3287 if (library != null) {
3288 resolveCombinators(library, node.combinators);
3289 }
3290 setMetadata(importElement, node);
3291 }
3292 return null;
3293 }
3294 Object visitIndexExpression(IndexExpression node) {
3295 Expression target = node.realTarget;
3296 Type2 staticType = getStaticType(target);
3297 Type2 propagatedType = getPropagatedType(target);
3298 String getterMethodName = sc.TokenType.INDEX.lexeme;
3299 String setterMethodName = sc.TokenType.INDEX_EQ.lexeme;
3300 bool isInGetterContext = node.inGetterContext();
3301 bool isInSetterContext = node.inSetterContext();
3302 if (isInGetterContext && isInSetterContext) {
3303 MethodElement setterStaticMethod = lookUpMethod(target, staticType, setter MethodName);
3304 MethodElement setterPropagatedMethod = lookUpMethod(target, propagatedType , setterMethodName);
3305 node.staticElement = setterStaticMethod;
3306 node.propagatedElement = setterPropagatedMethod;
3307 checkForUndefinedIndexOperator(node, target, getterMethodName, setterStati cMethod, setterPropagatedMethod, staticType, propagatedType);
3308 MethodElement getterStaticMethod = lookUpMethod(target, staticType, getter MethodName);
3309 MethodElement getterPropagatedMethod = lookUpMethod(target, propagatedType , getterMethodName);
3310 AuxiliaryElements auxiliaryElements = new AuxiliaryElements(getterStaticMe thod, getterPropagatedMethod);
3311 node.auxiliaryElements = auxiliaryElements;
3312 checkForUndefinedIndexOperator(node, target, getterMethodName, getterStati cMethod, getterPropagatedMethod, staticType, propagatedType);
3313 } else if (isInGetterContext) {
3314 MethodElement staticMethod = lookUpMethod(target, staticType, getterMethod Name);
3315 MethodElement propagatedMethod = lookUpMethod(target, propagatedType, gett erMethodName);
3316 node.staticElement = staticMethod;
3317 node.propagatedElement = propagatedMethod;
3318 checkForUndefinedIndexOperator(node, target, getterMethodName, staticMetho d, propagatedMethod, staticType, propagatedType);
3319 } else if (isInSetterContext) {
3320 MethodElement staticMethod = lookUpMethod(target, staticType, setterMethod Name);
3321 MethodElement propagatedMethod = lookUpMethod(target, propagatedType, sett erMethodName);
3322 node.staticElement = staticMethod;
3323 node.propagatedElement = propagatedMethod;
3324 checkForUndefinedIndexOperator(node, target, setterMethodName, staticMetho d, propagatedMethod, staticType, propagatedType);
3325 }
3326 return null;
3327 }
3328 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
3329 ConstructorElement invokedConstructor = node.constructorName.staticElement;
3330 node.staticElement = invokedConstructor;
3331 ArgumentList argumentList = node.argumentList;
3332 List<ParameterElement> parameters = resolveArgumentsToParameters(node.isCons t, argumentList, invokedConstructor);
3333 if (parameters != null) {
3334 argumentList.correspondingStaticParameters = parameters;
3335 }
3336 return null;
3337 }
3338 Object visitLibraryDirective(LibraryDirective node) {
3339 setMetadata(node.element, node);
3340 return null;
3341 }
3342 Object visitMethodDeclaration(MethodDeclaration node) {
3343 setMetadata(node.element, node);
3344 return null;
3345 }
3346 Object visitMethodInvocation(MethodInvocation node) {
3347 SimpleIdentifier methodName = node.methodName;
3348 Expression target = node.realTarget;
3349 if (target is SuperExpression && !isSuperInValidContext(target as SuperExpre ssion)) {
3350 return null;
3351 }
3352 Element staticElement;
3353 Element propagatedElement;
3354 if (target == null) {
3355 staticElement = resolveInvokedElement2(methodName);
3356 propagatedElement = null;
3357 } else {
3358 Type2 staticType = getStaticType(target);
3359 staticElement = resolveInvokedElement(target, staticType, methodName);
3360 propagatedElement = resolveInvokedElement(target, getPropagatedType(target ), methodName);
3361 }
3362 staticElement = convertSetterToGetter(staticElement);
3363 propagatedElement = convertSetterToGetter(propagatedElement);
3364 methodName.staticElement = staticElement;
3365 methodName.propagatedElement = propagatedElement;
3366 ArgumentList argumentList = node.argumentList;
3367 if (staticElement != null) {
3368 List<ParameterElement> parameters = computeCorrespondingParameters(argumen tList, staticElement);
3369 if (parameters != null) {
3370 argumentList.correspondingStaticParameters = parameters;
3371 }
3372 }
3373 if (propagatedElement != null) {
3374 List<ParameterElement> parameters = computeCorrespondingParameters(argumen tList, propagatedElement);
3375 if (parameters != null) {
3376 argumentList.correspondingPropagatedParameters = parameters;
3377 }
3378 }
3379 ErrorCode errorCode = checkForInvocationError(target, true, staticElement);
3380 bool generatedWithTypePropagation = false;
3381 if (_enableHints && errorCode == null && staticElement == null) {
3382 errorCode = checkForInvocationError(target, false, propagatedElement);
3383 if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
3384 ClassElement classElementContext = null;
3385 if (target == null) {
3386 classElementContext = _resolver.enclosingClass;
3387 } else {
3388 Type2 type = target.bestType;
3389 if (type != null) {
3390 if (type.element is ClassElement) {
3391 classElementContext = type.element as ClassElement;
3392 }
3393 }
3394 }
3395 if (classElementContext != null) {
3396 _subtypeManager.ensureLibraryVisited(_resolver.definingLibrary);
3397 Set<ClassElement> subtypeElements = _subtypeManager.computeAllSubtypes (classElementContext);
3398 for (ClassElement subtypeElement in subtypeElements) {
3399 if (subtypeElement.getMethod(methodName.name) != null) {
3400 errorCode = null;
3401 }
3402 }
3403 }
3404 }
3405 generatedWithTypePropagation = true;
3406 }
3407 if (errorCode == null) {
3408 return null;
3409 }
3410 if (identical(errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION)) {
3411 _resolver.reportError5(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, m ethodName, [methodName.name]);
3412 } else if (identical(errorCode, CompileTimeErrorCode.UNDEFINED_FUNCTION)) {
3413 _resolver.reportError5(CompileTimeErrorCode.UNDEFINED_FUNCTION, methodName , [methodName.name]);
3414 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
3415 String targetTypeName;
3416 if (target == null) {
3417 ClassElement enclosingClass = _resolver.enclosingClass;
3418 targetTypeName = enclosingClass.displayName;
3419 ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDE FINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode;
3420 _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingCl ass, proxyErrorCode, methodName, [methodName.name, targetTypeName]);
3421 } else {
3422 Type2 targetType = null;
3423 if (!generatedWithTypePropagation) {
3424 targetType = getStaticType(target);
3425 } else {
3426 targetType = getPropagatedType(target);
3427 if (targetType == null) {
3428 targetType = getStaticType(target);
3429 }
3430 }
3431 if (targetType != null && targetType.isDartCoreFunction && methodName.na me == CALL_METHOD_NAME) {
3432 return null;
3433 }
3434 targetTypeName = targetType == null ? null : targetType.displayName;
3435 ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDE FINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode;
3436 _resolver.reportErrorProxyConditionalAnalysisError(targetType.element, p roxyErrorCode, methodName, [methodName.name, targetTypeName]);
3437 }
3438 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD )) {
3439 Type2 targetType = getStaticType(target);
3440 String targetTypeName = targetType == null ? null : targetType.name;
3441 _resolver.reportError5(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, metho dName, [methodName.name, targetTypeName]);
3442 }
3443 return null;
3444 }
3445 Object visitPartDirective(PartDirective node) {
3446 setMetadata(node.element, node);
3447 return null;
3448 }
3449 Object visitPartOfDirective(PartOfDirective node) {
3450 setMetadata(node.element, node);
3451 return null;
3452 }
3453 Object visitPostfixExpression(PostfixExpression node) {
3454 Expression operand = node.operand;
3455 String methodName = getPostfixOperator(node);
3456 Type2 staticType = getStaticType(operand);
3457 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName);
3458 node.staticElement = staticMethod;
3459 Type2 propagatedType = getPropagatedType(operand);
3460 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, metho dName);
3461 node.propagatedElement = propagatedMethod;
3462 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, pro pagatedMethod));
3463 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
3464 if (shouldReportMissingMember_propagated) {
3465 if (memberFoundInSubclass(propagatedType.element, methodName, true, false) ) {
3466 shouldReportMissingMember_propagated = false;
3467 }
3468 }
3469 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) {
3470 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarnin gCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
3471 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissingMem ber_static ? staticType.element : propagatedType.element, errorCode, node.operat or, [
3472 methodName,
3473 shouldReportMissingMember_static ? staticType.displayName : propagated Type.displayName]);
3474 }
3475 return null;
3476 }
3477 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
3478 SimpleIdentifier prefix = node.prefix;
3479 SimpleIdentifier identifier = node.identifier;
3480 Element prefixElement = prefix.staticElement;
3481 if (prefixElement is PrefixElement) {
3482 Element element = _resolver.nameScope.lookup(node, _resolver.definingLibra ry);
3483 if (element == null && identifier.inSetterContext()) {
3484 element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdenti fier("${node.name}="), _resolver.definingLibrary);
3485 }
3486 if (element == null) {
3487 if (identifier.inSetterContext()) {
3488 _resolver.reportError5(StaticWarningCode.UNDEFINED_SETTER, identifier, [identifier.name, prefixElement.name]);
3489 } else {
3490 _resolver.reportError5(StaticWarningCode.UNDEFINED_GETTER, identifier, [identifier.name, prefixElement.name]);
3491 }
3492 return null;
3493 }
3494 if (element is PropertyAccessorElement && identifier.inSetterContext()) {
3495 PropertyInducingElement variable = ((element as PropertyAccessorElement) ).variable;
3496 if (variable != null) {
3497 PropertyAccessorElement setter = variable.setter;
3498 if (setter != null) {
3499 element = setter;
3500 }
3501 }
3502 }
3503 identifier.staticElement = element;
3504 if (node.parent is Annotation) {
3505 Annotation annotation = node.parent as Annotation;
3506 resolveAnnotationElement(annotation, element, null);
3507 return null;
3508 }
3509 return null;
3510 }
3511 if (node.parent is Annotation) {
3512 Annotation annotation = node.parent as Annotation;
3513 resolveAnnotationElement(annotation, prefixElement, identifier);
3514 }
3515 resolvePropertyAccess(prefix, identifier);
3516 return null;
3517 }
3518 Object visitPrefixExpression(PrefixExpression node) {
3519 sc.Token operator = node.operator;
3520 sc.TokenType operatorType = operator.type;
3521 if (operatorType.isUserDefinableOperator || identical(operatorType, sc.Token Type.PLUS_PLUS) || identical(operatorType, sc.TokenType.MINUS_MINUS)) {
3522 Expression operand = node.operand;
3523 String methodName = getPrefixOperator(node);
3524 Type2 staticType = getStaticType(operand);
3525 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName) ;
3526 node.staticElement = staticMethod;
3527 Type2 propagatedType = getPropagatedType(operand);
3528 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, met hodName);
3529 node.propagatedElement = propagatedMethod;
3530 bool shouldReportMissingMember_static = shouldReportMissingMember(staticTy pe, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, p ropagatedMethod));
3531 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_sta tic && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod ) : false;
3532 if (shouldReportMissingMember_propagated) {
3533 if (memberFoundInSubclass(propagatedType.element, methodName, true, fals e)) {
3534 shouldReportMissingMember_propagated = false;
3535 }
3536 }
3537 if (shouldReportMissingMember_static || shouldReportMissingMember_propagat ed) {
3538 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarn ingCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
3539 _resolver.reportErrorProxyConditionalAnalysisError3(shouldReportMissingM ember_static ? staticType.element : propagatedType.element, errorCode, operator, [
3540 methodName,
3541 shouldReportMissingMember_static ? staticType.displayName : propagat edType.displayName]);
3542 }
3543 }
3544 return null;
3545 }
3546 Object visitPropertyAccess(PropertyAccess node) {
3547 Expression target = node.realTarget;
3548 if (target is SuperExpression && !isSuperInValidContext(target as SuperExpre ssion)) {
3549 return null;
3550 }
3551 SimpleIdentifier propertyName = node.propertyName;
3552 resolvePropertyAccess(target, propertyName);
3553 return null;
3554 }
3555 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
3556 ClassElement enclosingClass = _resolver.enclosingClass;
3557 if (enclosingClass == null) {
3558 return null;
3559 }
3560 SimpleIdentifier name = node.constructorName;
3561 ConstructorElement element;
3562 if (name == null) {
3563 element = enclosingClass.unnamedConstructor;
3564 } else {
3565 element = enclosingClass.getNamedConstructor(name.name);
3566 }
3567 if (element == null) {
3568 return null;
3569 }
3570 if (name != null) {
3571 name.staticElement = element;
3572 }
3573 node.staticElement = element;
3574 ArgumentList argumentList = node.argumentList;
3575 List<ParameterElement> parameters = resolveArgumentsToParameters(false, argu mentList, element);
3576 if (parameters != null) {
3577 argumentList.correspondingStaticParameters = parameters;
3578 }
3579 return null;
3580 }
3581 Object visitSimpleIdentifier(SimpleIdentifier node) {
3582 if (node.staticElement != null) {
3583 return null;
3584 }
3585 if (node.name == _dynamicType.name) {
3586 node.staticElement = _dynamicType.element;
3587 node.staticType = _typeType;
3588 return null;
3589 }
3590 Element element = resolveSimpleIdentifier(node);
3591 ClassElement enclosingClass = _resolver.enclosingClass;
3592 if (isFactoryConstructorReturnType(node) && element != enclosingClass) {
3593 _resolver.reportError5(CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLA SS, node, []);
3594 } else if (isConstructorReturnType(node) && element != enclosingClass) {
3595 _resolver.reportError5(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node , []);
3596 element = null;
3597 } else if (element == null || (element is PrefixElement && !isValidAsPrefix( node))) {
3598 if (isConstructorReturnType(node)) {
3599 _resolver.reportError5(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, no de, []);
3600 } else {
3601 _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingCl ass, StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]);
3602 }
3603 }
3604 node.staticElement = element;
3605 if (node.inSetterContext() && node.inGetterContext() && enclosingClass != nu ll) {
3606 InterfaceType enclosingType = enclosingClass.type;
3607 AuxiliaryElements auxiliaryElements = new AuxiliaryElements(lookUpGetter(n ull, enclosingType, node.name), null);
3608 node.auxiliaryElements = auxiliaryElements;
3609 }
3610 if (node.parent is Annotation) {
3611 Annotation annotation = node.parent as Annotation;
3612 resolveAnnotationElement(annotation, element, null);
3613 }
3614 return null;
3615 }
3616 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
3617 ClassElement enclosingClass = _resolver.enclosingClass;
3618 if (enclosingClass == null) {
3619 return null;
3620 }
3621 InterfaceType superType = enclosingClass.supertype;
3622 if (superType == null) {
3623 return null;
3624 }
3625 SimpleIdentifier name = node.constructorName;
3626 String superName = name != null ? name.name : null;
3627 ConstructorElement element = superType.lookUpConstructor(superName, _resolve r.definingLibrary);
3628 if (element == null) {
3629 if (name != null) {
3630 _resolver.reportError5(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INI TIALIZER, node, [superType.displayName, name]);
3631 } else {
3632 _resolver.reportError5(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_INI TIALIZER_DEFAULT, node, [superType.displayName]);
3633 }
3634 return null;
3635 } else {
3636 if (element.isFactory) {
3637 _resolver.reportError5(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, node, [element]);
3638 }
3639 }
3640 if (name != null) {
3641 name.staticElement = element;
3642 }
3643 node.staticElement = element;
3644 ArgumentList argumentList = node.argumentList;
3645 List<ParameterElement> parameters = resolveArgumentsToParameters(isInConstCo nstructor, argumentList, element);
3646 if (parameters != null) {
3647 argumentList.correspondingStaticParameters = parameters;
3648 }
3649 return null;
3650 }
3651 Object visitSuperExpression(SuperExpression node) {
3652 if (!isSuperInValidContext(node)) {
3653 _resolver.reportError5(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, node , []);
3654 }
3655 return super.visitSuperExpression(node);
3656 }
3657 Object visitTypeParameter(TypeParameter node) {
3658 TypeName bound = node.bound;
3659 if (bound != null) {
3660 TypeParameterElementImpl typeParameter = node.name.staticElement as TypePa rameterElementImpl;
3661 if (typeParameter != null) {
3662 typeParameter.bound = bound.type;
3663 }
3664 }
3665 setMetadata(node.element, node);
3666 return null;
3667 }
3668 Object visitVariableDeclaration(VariableDeclaration node) {
3669 setMetadata(node.element, node);
3670 return null;
3671 }
3672
3673 /**
3674 * Generate annotation elements for each of the annotations in the given node list and add them to
3675 * the given list of elements.
3676 *
3677 * @param annotationList the list of elements to which new elements are to be added
3678 * @param annotations the AST nodes used to generate new elements
3679 */
3680 void addAnnotations(List<ElementAnnotationImpl> annotationList, NodeList<Annot ation> annotations) {
3681 for (Annotation annotationNode in annotations) {
3682 Element resolvedElement = annotationNode.element;
3683 if (resolvedElement != null) {
3684 annotationList.add(new ElementAnnotationImpl(resolvedElement));
3685 }
3686 }
3687 }
3688
3689 /**
3690 * Given that we have found code to invoke the given element, return the error code that should be
3691 * reported, or `null` if no error should be reported.
3692 *
3693 * @param target the target of the invocation, or `null` if there was no targe t
3694 * @param useStaticContext
3695 * @param element the element to be invoked
3696 * @return the error code that should be reported
3697 */
3698 ErrorCode checkForInvocationError(Expression target, bool useStaticContext, El ement element) {
3699 if (element is PrefixElement) {
3700 element = null;
3701 }
3702 if (element is PropertyAccessorElement) {
3703 FunctionType getterType = ((element as PropertyAccessorElement)).type;
3704 if (getterType != null) {
3705 Type2 returnType = getterType.returnType;
3706 if (!isExecutableType(returnType)) {
3707 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
3708 }
3709 }
3710 } else if (element is ExecutableElement) {
3711 return null;
3712 } else if (element == null && target is SuperExpression) {
3713 return StaticTypeWarningCode.UNDEFINED_SUPER_METHOD;
3714 } else {
3715 if (element is PropertyInducingElement) {
3716 PropertyAccessorElement getter = ((element as PropertyInducingElement)). getter;
3717 FunctionType getterType = getter.type;
3718 if (getterType != null) {
3719 Type2 returnType = getterType.returnType;
3720 if (!isExecutableType(returnType)) {
3721 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
3722 }
3723 }
3724 } else if (element is VariableElement) {
3725 Type2 variableType = ((element as VariableElement)).type;
3726 if (!isExecutableType(variableType)) {
3727 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
3728 }
3729 } else {
3730 if (target == null) {
3731 ClassElement enclosingClass = _resolver.enclosingClass;
3732 if (enclosingClass == null) {
3733 return CompileTimeErrorCode.UNDEFINED_FUNCTION;
3734 } else if (element == null) {
3735 return StaticTypeWarningCode.UNDEFINED_METHOD;
3736 } else {
3737 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
3738 }
3739 } else {
3740 Type2 targetType;
3741 if (useStaticContext) {
3742 targetType = getStaticType(target);
3743 } else {
3744 targetType = target.bestType;
3745 }
3746 if (targetType == null) {
3747 return CompileTimeErrorCode.UNDEFINED_FUNCTION;
3748 } else if (!targetType.isDynamic && !targetType.isBottom) {
3749 return StaticTypeWarningCode.UNDEFINED_METHOD;
3750 }
3751 }
3752 }
3753 }
3754 return null;
3755 }
3756
3757 /**
3758 * Check that the for some index expression that the method element was resolv ed, otherwise a
3759 * [StaticWarningCode#UNDEFINED_OPERATOR] is generated.
3760 *
3761 * @param node the index expression to resolve
3762 * @param target the target of the expression
3763 * @param methodName the name of the operator associated with the context of u sing of the given
3764 * index expression
3765 * @return `true` if and only if an error code is generated on the passed node
3766 */
3767 bool checkForUndefinedIndexOperator(IndexExpression node, Expression target, S tring methodName, MethodElement staticMethod, MethodElement propagatedMethod, Ty pe2 staticType, Type2 propagatedType) {
3768 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, pro pagatedMethod));
3769 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false;
3770 if (shouldReportMissingMember_propagated) {
3771 if (memberFoundInSubclass(propagatedType.element, methodName, true, false) ) {
3772 shouldReportMissingMember_propagated = false;
3773 }
3774 }
3775 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) {
3776 sc.Token leftBracket = node.leftBracket;
3777 sc.Token rightBracket = node.rightBracket;
3778 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarnin gCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode;
3779 if (leftBracket == null || rightBracket == null) {
3780 _resolver.reportErrorProxyConditionalAnalysisError(shouldReportMissingMe mber_static ? staticType.element : propagatedType.element, errorCode, node, [
3781 methodName,
3782 shouldReportMissingMember_static ? staticType.displayName : propagat edType.displayName]);
3783 } else {
3784 int offset = leftBracket.offset;
3785 int length = rightBracket.offset - offset + 1;
3786 _resolver.reportErrorProxyConditionalAnalysisError2(shouldReportMissingM ember_static ? staticType.element : propagatedType.element, errorCode, offset, l ength, [
3787 methodName,
3788 shouldReportMissingMember_static ? staticType.displayName : propagat edType.displayName]);
3789 }
3790 return true;
3791 }
3792 return false;
3793 }
3794
3795 /**
3796 * Given a list of arguments and the element that will be invoked using those argument, compute
3797 * the list of parameters that correspond to the list of arguments. Return the parameters that
3798 * correspond to the arguments, or `null` if no correspondence could be comput ed.
3799 *
3800 * @param argumentList the list of arguments being passed to the element
3801 * @param executableElement the element that will be invoked with the argument s
3802 * @return the parameters that correspond to the arguments
3803 */
3804 List<ParameterElement> computeCorrespondingParameters(ArgumentList argumentLis t, Element element) {
3805 if (element is PropertyAccessorElement) {
3806 FunctionType getterType = ((element as PropertyAccessorElement)).type;
3807 if (getterType != null) {
3808 Type2 getterReturnType = getterType.returnType;
3809 if (getterReturnType is InterfaceType) {
3810 MethodElement callMethod = ((getterReturnType as InterfaceType)).lookU pMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
3811 if (callMethod != null) {
3812 return resolveArgumentsToParameters(false, argumentList, callMethod) ;
3813 }
3814 } else if (getterReturnType is FunctionType) {
3815 Element functionElement = ((getterReturnType as FunctionType)).element ;
3816 if (functionElement is ExecutableElement) {
3817 return resolveArgumentsToParameters(false, argumentList, functionEle ment as ExecutableElement);
3818 }
3819 }
3820 }
3821 } else if (element is ExecutableElement) {
3822 return resolveArgumentsToParameters(false, argumentList, element as Execut ableElement);
3823 } else if (element is VariableElement) {
3824 VariableElement variable = element as VariableElement;
3825 Type2 type = _promoteManager.getStaticType(variable);
3826 if (type is FunctionType) {
3827 FunctionType functionType = type as FunctionType;
3828 List<ParameterElement> parameters = functionType.parameters;
3829 return resolveArgumentsToParameters2(false, argumentList, parameters);
3830 } else if (type is InterfaceType) {
3831 MethodElement callMethod = ((type as InterfaceType)).lookUpMethod(CALL_M ETHOD_NAME, _resolver.definingLibrary);
3832 if (callMethod != null) {
3833 List<ParameterElement> parameters = callMethod.parameters;
3834 return resolveArgumentsToParameters2(false, argumentList, parameters);
3835 }
3836 }
3837 }
3838 return null;
3839 }
3840
3841 /**
3842 * If the given element is a setter, return the getter associated with it. Oth erwise, return the
3843 * element unchanged.
3844 *
3845 * @param element the element to be normalized
3846 * @return a non-setter element derived from the given element
3847 */
3848 Element convertSetterToGetter(Element element) {
3849 if (element is PropertyAccessorElement) {
3850 return ((element as PropertyAccessorElement)).variable.getter;
3851 }
3852 return element;
3853 }
3854
3855 /**
3856 * Look for any declarations of the given identifier that are imported using a prefix. Return the
3857 * element that was found, or `null` if the name is not imported using a prefi x.
3858 *
3859 * @param identifier the identifier that might have been imported using a pref ix
3860 * @return the element that was found
3861 */
3862 Element findImportWithoutPrefix(SimpleIdentifier identifier) {
3863 Element element = null;
3864 Scope nameScope = _resolver.nameScope;
3865 LibraryElement definingLibrary = _resolver.definingLibrary;
3866 for (ImportElement importElement in definingLibrary.imports) {
3867 PrefixElement prefixElement = importElement.prefix;
3868 if (prefixElement != null) {
3869 Identifier prefixedIdentifier = new ElementResolver_SyntheticIdentifier( "${prefixElement.name}.${identifier.name}");
3870 Element importedElement = nameScope.lookup(prefixedIdentifier, definingL ibrary);
3871 if (importedElement != null) {
3872 if (element == null) {
3873 element = importedElement;
3874 } else {
3875 element = MultiplyDefinedElementImpl.fromElements(definingLibrary.co ntext, element, importedElement);
3876 }
3877 }
3878 }
3879 }
3880 return element;
3881 }
3882
3883 /**
3884 * Return the name of the method invoked by the given postfix expression.
3885 *
3886 * @param node the postfix expression being invoked
3887 * @return the name of the method invoked by the expression
3888 */
3889 String getPostfixOperator(PostfixExpression node) => (identical(node.operator. type, sc.TokenType.PLUS_PLUS)) ? sc.TokenType.PLUS.lexeme : sc.TokenType.MINUS.l exeme;
3890
3891 /**
3892 * Return the name of the method invoked by the given postfix expression.
3893 *
3894 * @param node the postfix expression being invoked
3895 * @return the name of the method invoked by the expression
3896 */
3897 String getPrefixOperator(PrefixExpression node) {
3898 sc.Token operator = node.operator;
3899 sc.TokenType operatorType = operator.type;
3900 if (identical(operatorType, sc.TokenType.PLUS_PLUS)) {
3901 return sc.TokenType.PLUS.lexeme;
3902 } else if (identical(operatorType, sc.TokenType.MINUS_MINUS)) {
3903 return sc.TokenType.MINUS.lexeme;
3904 } else if (identical(operatorType, sc.TokenType.MINUS)) {
3905 return "unary-";
3906 } else {
3907 return operator.lexeme;
3908 }
3909 }
3910
3911 /**
3912 * Return the propagated type of the given expression that is to be used for t ype analysis.
3913 *
3914 * @param expression the expression whose type is to be returned
3915 * @return the type of the given expression
3916 */
3917 Type2 getPropagatedType(Expression expression) {
3918 Type2 propagatedType = resolveTypeParameter(expression.propagatedType);
3919 if (propagatedType is FunctionType) {
3920 propagatedType = _resolver.typeProvider.functionType;
3921 }
3922 return propagatedType;
3923 }
3924
3925 /**
3926 * Return the static type of the given expression that is to be used for type analysis.
3927 *
3928 * @param expression the expression whose type is to be returned
3929 * @return the type of the given expression
3930 */
3931 Type2 getStaticType(Expression expression) {
3932 if (expression is NullLiteral) {
3933 return _resolver.typeProvider.bottomType;
3934 }
3935 Type2 staticType = resolveTypeParameter(expression.staticType);
3936 if (staticType is FunctionType) {
3937 staticType = _resolver.typeProvider.functionType;
3938 }
3939 return staticType;
3940 }
3941
3942 /**
3943 * Return `true` if the given type represents an object that could be invoked using the call
3944 * operator '()'.
3945 *
3946 * @param type the type being tested
3947 * @return `true` if the given type represents an object that could be invoked
3948 */
3949 bool isExecutableType(Type2 type) {
3950 if (type.isDynamic || (type is FunctionType) || type.isDartCoreFunction || t ype.isObject) {
3951 return true;
3952 } else if (type is InterfaceType) {
3953 ClassElement classElement = ((type as InterfaceType)).element;
3954 MethodElement methodElement = classElement.lookUpMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
3955 return methodElement != null;
3956 }
3957 return false;
3958 }
3959
3960 /**
3961 * @return `true` iff current enclosing function is constant constructor decla ration.
3962 */
3963 bool get isInConstConstructor {
3964 ExecutableElement function = _resolver.enclosingFunction;
3965 if (function is ConstructorElement) {
3966 return ((function as ConstructorElement)).isConst;
3967 }
3968 return false;
3969 }
3970
3971 /**
3972 * Return `true` if the given element is a static element.
3973 *
3974 * @param element the element being tested
3975 * @return `true` if the given element is a static element
3976 */
3977 bool isStatic(Element element) {
3978 if (element is ExecutableElement) {
3979 return ((element as ExecutableElement)).isStatic;
3980 } else if (element is PropertyInducingElement) {
3981 return ((element as PropertyInducingElement)).isStatic;
3982 }
3983 return false;
3984 }
3985
3986 /**
3987 * Return `true` if the given node can validly be resolved to a prefix:
3988 *
3989 * * it is the prefix in an import directive, or
3990 * * it is the prefix in a prefixed identifier.
3991 *
3992 *
3993 * @param node the node being tested
3994 * @return `true` if the given node is the prefix in an import directive
3995 */
3996 bool isValidAsPrefix(SimpleIdentifier node) {
3997 ASTNode parent = node.parent;
3998 if (parent is ImportDirective) {
3999 return identical(((parent as ImportDirective)).prefix, node);
4000 } else if (parent is PrefixedIdentifier) {
4001 return true;
4002 } else if (parent is MethodInvocation) {
4003 return identical(((parent as MethodInvocation)).target, node);
4004 }
4005 return false;
4006 }
4007
4008 /**
4009 * Look up the getter with the given name in the given type. Return the elemen t representing the
4010 * getter that was found, or `null` if there is no getter with the given name.
4011 *
4012 * @param target the target of the invocation, or `null` if there is no target
4013 * @param type the type in which the getter is defined
4014 * @param getterName the name of the getter being looked up
4015 * @return the element representing the getter that was found
4016 */
4017 PropertyAccessorElement lookUpGetter(Expression target, Type2 type, String get terName) {
4018 type = resolveTypeParameter(type);
4019 if (type is InterfaceType) {
4020 InterfaceType interfaceType = type as InterfaceType;
4021 PropertyAccessorElement accessor;
4022 if (target is SuperExpression) {
4023 accessor = interfaceType.lookUpGetterInSuperclass(getterName, _resolver. definingLibrary);
4024 } else {
4025 accessor = interfaceType.lookUpGetter(getterName, _resolver.definingLibr ary);
4026 }
4027 if (accessor != null) {
4028 return accessor;
4029 }
4030 return lookUpGetterInInterfaces(interfaceType, false, getterName, new Set< ClassElement>());
4031 }
4032 return null;
4033 }
4034
4035 /**
4036 * Look up the getter with the given name in the interfaces implemented by the given type, either
4037 * directly or indirectly. Return the element representing the getter that was found, or
4038 * `null` if there is no getter with the given name.
4039 *
4040 * @param targetType the type in which the getter might be defined
4041 * @param includeTargetType `true` if the search should include the target typ e
4042 * @param getterName the name of the getter being looked up
4043 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used
4044 * to prevent infinite recursion and to optimize the search
4045 * @return the element representing the getter that was found
4046 */
4047 PropertyAccessorElement lookUpGetterInInterfaces(InterfaceType targetType, boo l includeTargetType, String getterName, Set<ClassElement> visitedInterfaces) {
4048 ClassElement targetClass = targetType.element;
4049 if (visitedInterfaces.contains(targetClass)) {
4050 return null;
4051 }
4052 javaSetAdd(visitedInterfaces, targetClass);
4053 if (includeTargetType) {
4054 PropertyAccessorElement getter = targetType.getGetter(getterName);
4055 if (getter != null && getter.isAccessibleIn(_resolver.definingLibrary)) {
4056 return getter;
4057 }
4058 }
4059 for (InterfaceType interfaceType in targetType.interfaces) {
4060 PropertyAccessorElement getter = lookUpGetterInInterfaces(interfaceType, t rue, getterName, visitedInterfaces);
4061 if (getter != null) {
4062 return getter;
4063 }
4064 }
4065 for (InterfaceType mixinType in targetType.mixins) {
4066 PropertyAccessorElement getter = lookUpGetterInInterfaces(mixinType, true, getterName, visitedInterfaces);
4067 if (getter != null) {
4068 return getter;
4069 }
4070 }
4071 InterfaceType superclass = targetType.superclass;
4072 if (superclass == null) {
4073 return null;
4074 }
4075 return lookUpGetterInInterfaces(superclass, true, getterName, visitedInterfa ces);
4076 }
4077
4078 /**
4079 * Look up the method or getter with the given name in the given type. Return the element
4080 * representing the method or getter that was found, or `null` if there is no method or
4081 * getter with the given name.
4082 *
4083 * @param type the type in which the method or getter is defined
4084 * @param memberName the name of the method or getter being looked up
4085 * @return the element representing the method or getter that was found
4086 */
4087 ExecutableElement lookupGetterOrMethod(Type2 type, String memberName) {
4088 type = resolveTypeParameter(type);
4089 if (type is InterfaceType) {
4090 InterfaceType interfaceType = type as InterfaceType;
4091 ExecutableElement member = interfaceType.lookUpMethod(memberName, _resolve r.definingLibrary);
4092 if (member != null) {
4093 return member;
4094 }
4095 member = interfaceType.lookUpGetter(memberName, _resolver.definingLibrary) ;
4096 if (member != null) {
4097 return member;
4098 }
4099 return lookUpGetterOrMethodInInterfaces(interfaceType, false, memberName, new Set<ClassElement>());
4100 }
4101 return null;
4102 }
4103
4104 /**
4105 * Look up the method or getter with the given name in the interfaces implemen ted by the given
4106 * type, either directly or indirectly. Return the element representing the me thod or getter that
4107 * was found, or `null` if there is no method or getter with the given name.
4108 *
4109 * @param targetType the type in which the method or getter might be defined
4110 * @param includeTargetType `true` if the search should include the target typ e
4111 * @param memberName the name of the method or getter being looked up
4112 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used
4113 * to prevent infinite recursion and to optimize the search
4114 * @return the element representing the method or getter that was found
4115 */
4116 ExecutableElement lookUpGetterOrMethodInInterfaces(InterfaceType targetType, b ool includeTargetType, String memberName, Set<ClassElement> visitedInterfaces) {
4117 ClassElement targetClass = targetType.element;
4118 if (visitedInterfaces.contains(targetClass)) {
4119 return null;
4120 }
4121 javaSetAdd(visitedInterfaces, targetClass);
4122 if (includeTargetType) {
4123 ExecutableElement member = targetType.getMethod(memberName);
4124 if (member != null) {
4125 return member;
4126 }
4127 member = targetType.getGetter(memberName);
4128 if (member != null) {
4129 return member;
4130 }
4131 }
4132 for (InterfaceType interfaceType in targetType.interfaces) {
4133 ExecutableElement member = lookUpGetterOrMethodInInterfaces(interfaceType, true, memberName, visitedInterfaces);
4134 if (member != null) {
4135 return member;
4136 }
4137 }
4138 for (InterfaceType mixinType in targetType.mixins) {
4139 ExecutableElement member = lookUpGetterOrMethodInInterfaces(mixinType, tru e, memberName, visitedInterfaces);
4140 if (member != null) {
4141 return member;
4142 }
4143 }
4144 InterfaceType superclass = targetType.superclass;
4145 if (superclass == null) {
4146 return null;
4147 }
4148 return lookUpGetterOrMethodInInterfaces(superclass, true, memberName, visite dInterfaces);
4149 }
4150
4151 /**
4152 * Find the element corresponding to the given label node in the current label scope.
4153 *
4154 * @param parentNode the node containing the given label
4155 * @param labelNode the node representing the label being looked up
4156 * @return the element corresponding to the given label node in the current sc ope
4157 */
4158 LabelElementImpl lookupLabel(ASTNode parentNode, SimpleIdentifier labelNode) {
4159 LabelScope labelScope = _resolver.labelScope;
4160 LabelElementImpl labelElement = null;
4161 if (labelNode == null) {
4162 if (labelScope == null) {
4163 } else {
4164 labelElement = labelScope.lookup2(LabelScope.EMPTY_LABEL) as LabelElemen tImpl;
4165 if (labelElement == null) {
4166 }
4167 labelElement = null;
4168 }
4169 } else {
4170 if (labelScope == null) {
4171 _resolver.reportError5(CompileTimeErrorCode.LABEL_UNDEFINED, labelNode, [labelNode.name]);
4172 } else {
4173 labelElement = labelScope.lookup(labelNode) as LabelElementImpl;
4174 if (labelElement == null) {
4175 _resolver.reportError5(CompileTimeErrorCode.LABEL_UNDEFINED, labelNode , [labelNode.name]);
4176 } else {
4177 labelNode.staticElement = labelElement;
4178 }
4179 }
4180 }
4181 if (labelElement != null) {
4182 ExecutableElement labelContainer = labelElement.getAncestor(ExecutableElem ent);
4183 if (labelContainer != _resolver.enclosingFunction) {
4184 _resolver.reportError5(CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, labelN ode, [labelNode.name]);
4185 labelElement = null;
4186 }
4187 }
4188 return labelElement;
4189 }
4190
4191 /**
4192 * Look up the method with the given name in the given type. Return the elemen t representing the
4193 * method that was found, or `null` if there is no method with the given name.
4194 *
4195 * @param target the target of the invocation, or `null` if there is no target
4196 * @param type the type in which the method is defined
4197 * @param methodName the name of the method being looked up
4198 * @return the element representing the method that was found
4199 */
4200 MethodElement lookUpMethod(Expression target, Type2 type, String methodName) {
4201 type = resolveTypeParameter(type);
4202 if (type is InterfaceType) {
4203 InterfaceType interfaceType = type as InterfaceType;
4204 MethodElement method;
4205 if (target is SuperExpression) {
4206 method = interfaceType.lookUpMethodInSuperclass(methodName, _resolver.de finingLibrary);
4207 } else {
4208 method = interfaceType.lookUpMethod(methodName, _resolver.definingLibrar y);
4209 }
4210 if (method != null) {
4211 return method;
4212 }
4213 return lookUpMethodInInterfaces(interfaceType, false, methodName, new Set< ClassElement>());
4214 }
4215 return null;
4216 }
4217
4218 /**
4219 * Look up the method with the given name in the interfaces implemented by the given type, either
4220 * directly or indirectly. Return the element representing the method that was found, or
4221 * `null` if there is no method with the given name.
4222 *
4223 * @param targetType the type in which the member might be defined
4224 * @param includeTargetType `true` if the search should include the target typ e
4225 * @param methodName the name of the method being looked up
4226 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used
4227 * to prevent infinite recursion and to optimize the search
4228 * @return the element representing the method that was found
4229 */
4230 MethodElement lookUpMethodInInterfaces(InterfaceType targetType, bool includeT argetType, String methodName, Set<ClassElement> visitedInterfaces) {
4231 ClassElement targetClass = targetType.element;
4232 if (visitedInterfaces.contains(targetClass)) {
4233 return null;
4234 }
4235 javaSetAdd(visitedInterfaces, targetClass);
4236 if (includeTargetType) {
4237 MethodElement method = targetType.getMethod(methodName);
4238 if (method != null && method.isAccessibleIn(_resolver.definingLibrary)) {
4239 return method;
4240 }
4241 }
4242 for (InterfaceType interfaceType in targetType.interfaces) {
4243 MethodElement method = lookUpMethodInInterfaces(interfaceType, true, metho dName, visitedInterfaces);
4244 if (method != null) {
4245 return method;
4246 }
4247 }
4248 for (InterfaceType mixinType in targetType.mixins) {
4249 MethodElement method = lookUpMethodInInterfaces(mixinType, true, methodNam e, visitedInterfaces);
4250 if (method != null) {
4251 return method;
4252 }
4253 }
4254 InterfaceType superclass = targetType.superclass;
4255 if (superclass == null) {
4256 return null;
4257 }
4258 return lookUpMethodInInterfaces(superclass, true, methodName, visitedInterfa ces);
4259 }
4260
4261 /**
4262 * Look up the setter with the given name in the given type. Return the elemen t representing the
4263 * setter that was found, or `null` if there is no setter with the given name.
4264 *
4265 * @param target the target of the invocation, or `null` if there is no target
4266 * @param type the type in which the setter is defined
4267 * @param setterName the name of the setter being looked up
4268 * @return the element representing the setter that was found
4269 */
4270 PropertyAccessorElement lookUpSetter(Expression target, Type2 type, String set terName) {
4271 type = resolveTypeParameter(type);
4272 if (type is InterfaceType) {
4273 InterfaceType interfaceType = type as InterfaceType;
4274 PropertyAccessorElement accessor;
4275 if (target is SuperExpression) {
4276 accessor = interfaceType.lookUpSetterInSuperclass(setterName, _resolver. definingLibrary);
4277 } else {
4278 accessor = interfaceType.lookUpSetter(setterName, _resolver.definingLibr ary);
4279 }
4280 if (accessor != null) {
4281 return accessor;
4282 }
4283 return lookUpSetterInInterfaces(interfaceType, false, setterName, new Set< ClassElement>());
4284 }
4285 return null;
4286 }
4287
4288 /**
4289 * Look up the setter with the given name in the interfaces implemented by the given type, either
4290 * directly or indirectly. Return the element representing the setter that was found, or
4291 * `null` if there is no setter with the given name.
4292 *
4293 * @param targetType the type in which the setter might be defined
4294 * @param includeTargetType `true` if the search should include the target typ e
4295 * @param setterName the name of the setter being looked up
4296 * @param visitedInterfaces a set containing all of the interfaces that have b een examined, used
4297 * to prevent infinite recursion and to optimize the search
4298 * @return the element representing the setter that was found
4299 */
4300 PropertyAccessorElement lookUpSetterInInterfaces(InterfaceType targetType, boo l includeTargetType, String setterName, Set<ClassElement> visitedInterfaces) {
4301 ClassElement targetClass = targetType.element;
4302 if (visitedInterfaces.contains(targetClass)) {
4303 return null;
4304 }
4305 javaSetAdd(visitedInterfaces, targetClass);
4306 if (includeTargetType) {
4307 PropertyAccessorElement setter = targetType.getSetter(setterName);
4308 if (setter != null && setter.isAccessibleIn(_resolver.definingLibrary)) {
4309 return setter;
4310 }
4311 }
4312 for (InterfaceType interfaceType in targetType.interfaces) {
4313 PropertyAccessorElement setter = lookUpSetterInInterfaces(interfaceType, t rue, setterName, visitedInterfaces);
4314 if (setter != null) {
4315 return setter;
4316 }
4317 }
4318 for (InterfaceType mixinType in targetType.mixins) {
4319 PropertyAccessorElement setter = lookUpSetterInInterfaces(mixinType, true, setterName, visitedInterfaces);
4320 if (setter != null) {
4321 return setter;
4322 }
4323 }
4324 InterfaceType superclass = targetType.superclass;
4325 if (superclass == null) {
4326 return null;
4327 }
4328 return lookUpSetterInInterfaces(superclass, true, setterName, visitedInterfa ces);
4329 }
4330
4331 /**
4332 * Given some class element, this method uses [subtypeManager] to find the set of all
4333 * subtypes; the subtypes are then searched for a member (method, getter, or s etter), that matches
4334 * a passed
4335 *
4336 * @param element the class element to search the subtypes of, if a non-ClassE lement element is
4337 * passed, then `false` is returned
4338 * @param memberName the member name to search for
4339 * @param asMethod `true` if the methods should be searched for in the subtype s
4340 * @param asAccessor `true` if the accessors (getters and setters) should be s earched for in
4341 * the subtypes
4342 * @return `true` if and only if the passed memberName was found in a subtype
4343 */
4344 bool memberFoundInSubclass(Element element, String memberName, bool asMethod, bool asAccessor) {
4345 if (element is ClassElement) {
4346 _subtypeManager.ensureLibraryVisited(_resolver.definingLibrary);
4347 Set<ClassElement> subtypeElements = _subtypeManager.computeAllSubtypes(ele ment as ClassElement);
4348 for (ClassElement subtypeElement in subtypeElements) {
4349 if (asMethod && subtypeElement.getMethod(memberName) != null) {
4350 return true;
4351 } else if (asAccessor && (subtypeElement.getGetter(memberName) != null | | subtypeElement.getSetter(memberName) != null)) {
4352 return true;
4353 }
4354 }
4355 }
4356 return false;
4357 }
4358
4359 /**
4360 * Return the binary operator that is invoked by the given compound assignment operator.
4361 *
4362 * @param operator the assignment operator being mapped
4363 * @return the binary operator that invoked by the given assignment operator
4364 */
4365 sc.TokenType operatorFromCompoundAssignment(sc.TokenType operator) {
4366 while (true) {
4367 if (operator == sc.TokenType.AMPERSAND_EQ) {
4368 return sc.TokenType.AMPERSAND;
4369 } else if (operator == sc.TokenType.BAR_EQ) {
4370 return sc.TokenType.BAR;
4371 } else if (operator == sc.TokenType.CARET_EQ) {
4372 return sc.TokenType.CARET;
4373 } else if (operator == sc.TokenType.GT_GT_EQ) {
4374 return sc.TokenType.GT_GT;
4375 } else if (operator == sc.TokenType.LT_LT_EQ) {
4376 return sc.TokenType.LT_LT;
4377 } else if (operator == sc.TokenType.MINUS_EQ) {
4378 return sc.TokenType.MINUS;
4379 } else if (operator == sc.TokenType.PERCENT_EQ) {
4380 return sc.TokenType.PERCENT;
4381 } else if (operator == sc.TokenType.PLUS_EQ) {
4382 return sc.TokenType.PLUS;
4383 } else if (operator == sc.TokenType.SLASH_EQ) {
4384 return sc.TokenType.SLASH;
4385 } else if (operator == sc.TokenType.STAR_EQ) {
4386 return sc.TokenType.STAR;
4387 } else if (operator == sc.TokenType.TILDE_SLASH_EQ) {
4388 return sc.TokenType.TILDE_SLASH;
4389 }
4390 break;
4391 }
4392 AnalysisEngine.instance.logger.logError("Failed to map ${operator.lexeme} to it's corresponding operator");
4393 return operator;
4394 }
4395 void resolveAnnotationConstructorInvocationArguments(Annotation annotation, Co nstructorElement constructor) {
4396 ArgumentList argumentList = annotation.arguments;
4397 if (argumentList == null) {
4398 return;
4399 }
4400 List<ParameterElement> parameters = resolveArgumentsToParameters(true, argum entList, constructor);
4401 if (parameters != null) {
4402 argumentList.correspondingStaticParameters = parameters;
4403 }
4404 }
4405
4406 /**
4407 * Validates that the given [Element] is the constant variable; or resolves it as a
4408 * constructor invocation.
4409 *
4410 * @param annotation the [Annotation] to resolve
4411 * @param element the current known [Element] of the annotation, or [ClassElem ent]
4412 * @param nameNode the name of the invoked constructor, may be `null` if unnam ed constructor
4413 * or not a constructor invocation
4414 */
4415 void resolveAnnotationElement(Annotation annotation, Element element, SimpleId entifier nameNode) {
4416 if (element is PropertyAccessorElement) {
4417 PropertyAccessorElement accessorElement = element as PropertyAccessorEleme nt;
4418 if (!accessorElement.isSynthetic) {
4419 _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotati on, []);
4420 return;
4421 }
4422 VariableElement variableElement = accessorElement.variable;
4423 if (!variableElement.isConst) {
4424 _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotati on, []);
4425 }
4426 return;
4427 }
4428 if (element is ClassElement) {
4429 if (nameNode == null) {
4430 nameNode = annotation.constructorName;
4431 }
4432 String name = nameNode != null ? nameNode.name : null;
4433 ConstructorElement constructor;
4434 {
4435 InterfaceType interfaceType = new InterfaceTypeImpl.con1(element as Clas sElement);
4436 LibraryElement definingLibrary = _resolver.definingLibrary;
4437 constructor = interfaceType.lookUpConstructor(name, definingLibrary);
4438 }
4439 if (constructor == null) {
4440 _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotati on, []);
4441 return;
4442 }
4443 annotation.element = constructor;
4444 if (nameNode != null) {
4445 nameNode.staticElement = constructor;
4446 }
4447 resolveAnnotationConstructorInvocationArguments(annotation, constructor);
4448 return;
4449 }
4450 if (element != null) {
4451 _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotation , []);
4452 }
4453 }
4454
4455 /**
4456 * Given a list of arguments and the element that will be invoked using those argument, compute
4457 * the list of parameters that correspond to the list of arguments. Return the parameters that
4458 * correspond to the arguments, or `null` if no correspondence could be comput ed.
4459 *
4460 * @param reportError if `true` then compile-time error should be reported; if `false`
4461 * then compile-time warning
4462 * @param argumentList the list of arguments being passed to the element
4463 * @param executableElement the element that will be invoked with the argument s
4464 * @return the parameters that correspond to the arguments
4465 */
4466 List<ParameterElement> resolveArgumentsToParameters(bool reportError, Argument List argumentList, ExecutableElement executableElement) {
4467 if (executableElement == null) {
4468 return null;
4469 }
4470 List<ParameterElement> parameters = executableElement.parameters;
4471 return resolveArgumentsToParameters2(reportError, argumentList, parameters);
4472 }
4473
4474 /**
4475 * Given a list of arguments and the parameters related to the element that wi ll be invoked using
4476 * those argument, compute the list of parameters that correspond to the list of arguments. Return
4477 * the parameters that correspond to the arguments.
4478 *
4479 * @param reportError if `true` then compile-time error should be reported; if `false`
4480 * then compile-time warning
4481 * @param argumentList the list of arguments being passed to the element
4482 * @param parameters the of the function that will be invoked with the argumen ts
4483 * @return the parameters that correspond to the arguments
4484 */
4485 List<ParameterElement> resolveArgumentsToParameters2(bool reportError, Argumen tList argumentList, List<ParameterElement> parameters) {
4486 List<ParameterElement> requiredParameters = new List<ParameterElement>();
4487 List<ParameterElement> positionalParameters = new List<ParameterElement>();
4488 Map<String, ParameterElement> namedParameters = new Map<String, ParameterEle ment>();
4489 for (ParameterElement parameter in parameters) {
4490 ParameterKind kind = parameter.parameterKind;
4491 if (identical(kind, ParameterKind.REQUIRED)) {
4492 requiredParameters.add(parameter);
4493 } else if (identical(kind, ParameterKind.POSITIONAL)) {
4494 positionalParameters.add(parameter);
4495 } else {
4496 namedParameters[parameter.name] = parameter;
4497 }
4498 }
4499 List<ParameterElement> unnamedParameters = new List<ParameterElement>.from(r equiredParameters);
4500 unnamedParameters.addAll(positionalParameters);
4501 int unnamedParameterCount = unnamedParameters.length;
4502 int unnamedIndex = 0;
4503 NodeList<Expression> arguments = argumentList.arguments;
4504 int argumentCount = arguments.length;
4505 List<ParameterElement> resolvedParameters = new List<ParameterElement>(argum entCount);
4506 int positionalArgumentCount = 0;
4507 Set<String> usedNames = new Set<String>();
4508 for (int i = 0; i < argumentCount; i++) {
4509 Expression argument = arguments[i];
4510 if (argument is NamedExpression) {
4511 SimpleIdentifier nameNode = ((argument as NamedExpression)).name.label;
4512 String name = nameNode.name;
4513 ParameterElement element = namedParameters[name];
4514 if (element == null) {
4515 ErrorCode errorCode = (reportError ? CompileTimeErrorCode.UNDEFINED_NA MED_PARAMETER : StaticWarningCode.UNDEFINED_NAMED_PARAMETER) as ErrorCode;
4516 _resolver.reportError5(errorCode, nameNode, [name]);
4517 } else {
4518 resolvedParameters[i] = element;
4519 nameNode.staticElement = element;
4520 }
4521 if (!javaSetAdd(usedNames, name)) {
4522 _resolver.reportError5(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, nameNode, [name]);
4523 }
4524 } else {
4525 positionalArgumentCount++;
4526 if (unnamedIndex < unnamedParameterCount) {
4527 resolvedParameters[i] = unnamedParameters[unnamedIndex++];
4528 }
4529 }
4530 }
4531 if (positionalArgumentCount < requiredParameters.length) {
4532 ErrorCode errorCode = (reportError ? CompileTimeErrorCode.NOT_ENOUGH_REQUI RED_ARGUMENTS : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS) as ErrorCode;
4533 _resolver.reportError5(errorCode, argumentList, [requiredParameters.length , positionalArgumentCount]);
4534 } else if (positionalArgumentCount > unnamedParameterCount) {
4535 ErrorCode errorCode = (reportError ? CompileTimeErrorCode.EXTRA_POSITIONAL _ARGUMENTS : StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS) as ErrorCode;
4536 _resolver.reportError5(errorCode, argumentList, [unnamedParameterCount, po sitionalArgumentCount]);
4537 }
4538 return resolvedParameters;
4539 }
4540
4541 /**
4542 * Resolve the names in the given combinators in the scope of the given librar y.
4543 *
4544 * @param library the library that defines the names
4545 * @param combinators the combinators containing the names to be resolved
4546 */
4547 void resolveCombinators(LibraryElement library, NodeList<Combinator> combinato rs) {
4548 if (library == null) {
4549 return;
4550 }
4551 Namespace namespace = new NamespaceBuilder().createExportNamespace2(library) ;
4552 for (Combinator combinator in combinators) {
4553 NodeList<SimpleIdentifier> names;
4554 if (combinator is HideCombinator) {
4555 names = ((combinator as HideCombinator)).hiddenNames;
4556 } else {
4557 names = ((combinator as ShowCombinator)).shownNames;
4558 }
4559 for (SimpleIdentifier name in names) {
4560 Element element = namespace.get(name.name);
4561 if (element != null) {
4562 name.staticElement = element;
4563 }
4564 }
4565 }
4566 }
4567
4568 /**
4569 * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the el ement being invoked.
4570 * If the returned element is a method, then the method will be invoked. If th e returned element
4571 * is a getter, the getter will be invoked without arguments and the result of that invocation
4572 * will then be invoked with the arguments.
4573 *
4574 * @param target the target of the invocation ('e')
4575 * @param targetType the type of the target
4576 * @param methodName the name of the method being invoked ('m')
4577 * @return the element being invoked
4578 */
4579 Element resolveInvokedElement(Expression target, Type2 targetType, SimpleIdent ifier methodName) {
4580 if (targetType is InterfaceType) {
4581 InterfaceType classType = targetType as InterfaceType;
4582 Element element = lookUpMethod(target, classType, methodName.name);
4583 if (element == null) {
4584 element = lookUpGetter(target, classType, methodName.name);
4585 }
4586 return element;
4587 } else if (target is SimpleIdentifier) {
4588 Element targetElement = ((target as SimpleIdentifier)).staticElement;
4589 if (targetElement is PrefixElement) {
4590 String name = "${((target as SimpleIdentifier)).name}.${methodName}";
4591 Identifier functionName = new ElementResolver_SyntheticIdentifier(name);
4592 Element element = _resolver.nameScope.lookup(functionName, _resolver.def iningLibrary);
4593 if (element != null) {
4594 return element;
4595 }
4596 }
4597 }
4598 return null;
4599 }
4600
4601 /**
4602 * Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the elemen t being invoked. If
4603 * the returned element is a method, then the method will be invoked. If the r eturned element is a
4604 * getter, the getter will be invoked without arguments and the result of that invocation will
4605 * then be invoked with the arguments.
4606 *
4607 * @param methodName the name of the method being invoked ('m')
4608 * @return the element being invoked
4609 */
4610 Element resolveInvokedElement2(SimpleIdentifier methodName) {
4611 Element element = _resolver.nameScope.lookup(methodName, _resolver.definingL ibrary);
4612 if (element == null) {
4613 ClassElement enclosingClass = _resolver.enclosingClass;
4614 if (enclosingClass != null) {
4615 InterfaceType enclosingType = enclosingClass.type;
4616 element = lookUpMethod(null, enclosingType, methodName.name);
4617 if (element == null) {
4618 element = lookUpGetter(null, enclosingType, methodName.name);
4619 }
4620 }
4621 }
4622 return element;
4623 }
4624
4625 /**
4626 * Given that we are accessing a property of the given type with the given nam e, return the
4627 * element that represents the property.
4628 *
4629 * @param target the target of the invocation ('e')
4630 * @param targetType the type in which the search for the property should begi n
4631 * @param propertyName the name of the property being accessed
4632 * @return the element that represents the property
4633 */
4634 ExecutableElement resolveProperty(Expression target, Type2 targetType, SimpleI dentifier propertyName) {
4635 ExecutableElement memberElement = null;
4636 if (propertyName.inSetterContext()) {
4637 memberElement = lookUpSetter(target, targetType, propertyName.name);
4638 }
4639 if (memberElement == null) {
4640 memberElement = lookUpGetter(target, targetType, propertyName.name);
4641 }
4642 if (memberElement == null) {
4643 memberElement = lookUpMethod(target, targetType, propertyName.name);
4644 }
4645 return memberElement;
4646 }
4647 void resolvePropertyAccess(Expression target, SimpleIdentifier propertyName) {
4648 Type2 staticType = getStaticType(target);
4649 ExecutableElement staticElement = resolveProperty(target, staticType, proper tyName);
4650 if (target.parent.parent is Annotation) {
4651 if (staticElement != null) {
4652 propertyName.staticElement = staticElement;
4653 }
4654 return;
4655 }
4656 propertyName.staticElement = staticElement;
4657 Type2 propagatedType = getPropagatedType(target);
4658 ExecutableElement propagatedElement = resolveProperty(target, propagatedType , propertyName);
4659 propertyName.propagatedElement = propagatedElement;
4660 bool shouldReportMissingMember_static = shouldReportMissingMember(staticType , staticElement) && (_strictMode || shouldReportMissingMember(propagatedType, pr opagatedElement));
4661 bool shouldReportMissingMember_propagated = !shouldReportMissingMember_stati c && _enableHints ? shouldReportMissingMember(propagatedType, propagatedElement) : false;
4662 if (shouldReportMissingMember_propagated) {
4663 if (memberFoundInSubclass(propagatedType.element, propertyName.name, false , true)) {
4664 shouldReportMissingMember_propagated = false;
4665 }
4666 }
4667 if (shouldReportMissingMember_static || shouldReportMissingMember_propagated ) {
4668 Element staticOrPropagatedEnclosingElt = shouldReportMissingMember_static ? staticType.element : propagatedType.element;
4669 bool isStaticProperty = isStatic(staticOrPropagatedEnclosingElt);
4670 if (propertyName.inSetterContext()) {
4671 if (isStaticProperty) {
4672 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarnin gCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode;
4673 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, errorCode, propertyName, [
4674 propertyName.name,
4675 staticOrPropagatedEnclosingElt.displayName]);
4676 } else {
4677 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode;
4678 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, errorCode, propertyName, [
4679 propertyName.name,
4680 staticOrPropagatedEnclosingElt.displayName]);
4681 }
4682 } else if (propertyName.inGetterContext()) {
4683 if (isStaticProperty) {
4684 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarnin gCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode;
4685 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, errorCode, propertyName, [
4686 propertyName.name,
4687 staticOrPropagatedEnclosingElt.displayName]);
4688 } else {
4689 ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWa rningCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode;
4690 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedE nclosingElt, errorCode, propertyName, [
4691 propertyName.name,
4692 staticOrPropagatedEnclosingElt.displayName]);
4693 }
4694 } else {
4695 _resolver.reportErrorProxyConditionalAnalysisError(staticOrPropagatedEnc losingElt, StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName, [propertyName.n ame]);
4696 }
4697 }
4698 }
4699
4700 /**
4701 * Resolve the given simple identifier if possible. Return the element to whic h it could be
4702 * resolved, or `null` if it could not be resolved. This does not record the r esults of the
4703 * resolution.
4704 *
4705 * @param node the identifier to be resolved
4706 * @return the element to which the identifier could be resolved
4707 */
4708 Element resolveSimpleIdentifier(SimpleIdentifier node) {
4709 Element element = _resolver.nameScope.lookup(node, _resolver.definingLibrary );
4710 if (element is PropertyAccessorElement && node.inSetterContext()) {
4711 PropertyInducingElement variable = ((element as PropertyAccessorElement)). variable;
4712 if (variable != null) {
4713 PropertyAccessorElement setter = variable.setter;
4714 if (setter == null) {
4715 ClassElement enclosingClass = _resolver.enclosingClass;
4716 if (enclosingClass != null) {
4717 setter = lookUpSetter(null, enclosingClass.type, node.name);
4718 }
4719 }
4720 if (setter != null) {
4721 element = setter;
4722 }
4723 }
4724 } else if (element == null && node.inSetterContext()) {
4725 element = _resolver.nameScope.lookup(new ElementResolver_SyntheticIdentifi er("${node.name}="), _resolver.definingLibrary);
4726 }
4727 ClassElement enclosingClass = _resolver.enclosingClass;
4728 if (element == null && enclosingClass != null) {
4729 InterfaceType enclosingType = enclosingClass.type;
4730 if (element == null && node.inSetterContext()) {
4731 element = lookUpSetter(null, enclosingType, node.name);
4732 }
4733 if (element == null && node.inGetterContext()) {
4734 element = lookUpGetter(null, enclosingType, node.name);
4735 }
4736 if (element == null) {
4737 element = lookUpMethod(null, enclosingType, node.name);
4738 }
4739 }
4740 return element;
4741 }
4742
4743 /**
4744 * If the given type is a type parameter, resolve it to the type that should b e used when looking
4745 * up members. Otherwise, return the original type.
4746 *
4747 * @param type the type that is to be resolved if it is a type parameter
4748 * @return the type that should be used in place of the argument if it is a ty pe parameter, or the
4749 * original argument if it isn't a type parameter
4750 */
4751 Type2 resolveTypeParameter(Type2 type) {
4752 if (type is TypeParameterType) {
4753 Type2 bound = ((type as TypeParameterType)).element.bound;
4754 if (bound == null) {
4755 return _resolver.typeProvider.objectType;
4756 }
4757 return bound;
4758 }
4759 return type;
4760 }
4761
4762 /**
4763 * Return the propagated element if it is not `null`, or the static element if it is.
4764 *
4765 * @param staticElement the element computed using static type information
4766 * @param propagatedElement the element computed using propagated type informa tion
4767 * @return the more specific of the two elements
4768 */
4769 ExecutableElement select(ExecutableElement staticElement, ExecutableElement pr opagatedElement) => propagatedElement != null ? propagatedElement : staticElemen t;
4770
4771 /**
4772 * Given a node that can have annotations associated with it and the element t o which that node
4773 * has been resolved, create the annotations in the element model representing the annotations on
4774 * the node.
4775 *
4776 * @param element the element to which the node has been resolved
4777 * @param node the node that can have annotations associated with it
4778 */
4779 void setMetadata(Element element, AnnotatedNode node) {
4780 if (element is! ElementImpl) {
4781 return;
4782 }
4783 List<ElementAnnotationImpl> annotationList = new List<ElementAnnotationImpl> ();
4784 addAnnotations(annotationList, node.metadata);
4785 if (node is VariableDeclaration && node.parent is VariableDeclarationList) {
4786 VariableDeclarationList list = node.parent as VariableDeclarationList;
4787 addAnnotations(annotationList, list.metadata);
4788 if (list.parent is FieldDeclaration) {
4789 FieldDeclaration fieldDeclaration = list.parent as FieldDeclaration;
4790 addAnnotations(annotationList, fieldDeclaration.metadata);
4791 } else if (list.parent is TopLevelVariableDeclaration) {
4792 TopLevelVariableDeclaration variableDeclaration = list.parent as TopLeve lVariableDeclaration;
4793 addAnnotations(annotationList, variableDeclaration.metadata);
4794 }
4795 }
4796 if (!annotationList.isEmpty) {
4797 ((element as ElementImpl)).metadata = new List.from(annotationList);
4798 }
4799 }
4800
4801 /**
4802 * Return `true` if we should report an error as a result of looking up a memb er in the
4803 * given type and not finding any member.
4804 *
4805 * @param type the type in which we attempted to perform the look-up
4806 * @param member the result of the look-up
4807 * @return `true` if we should report an error
4808 */
4809 bool shouldReportMissingMember(Type2 type, ExecutableElement member) {
4810 if (member != null || type == null || type.isDynamic || type.isBottom) {
4811 return false;
4812 }
4813 return true;
4814 }
4815 }
4816 /**
4817 * Instances of the class `SyntheticIdentifier` implement an identifier that can be used to
4818 * look up names in the lexical scope when there is no identifier in the AST str ucture. There is
4819 * no identifier in the AST when the parser could not distinguish between a meth od invocation and
4820 * an invocation of a top-level function imported with a prefix.
4821 */
4822 class ElementResolver_SyntheticIdentifier extends Identifier {
4823
4824 /**
4825 * The name of the synthetic identifier.
4826 */
4827 String _name;
4828
4829 /**
4830 * Initialize a newly created synthetic identifier to have the given name.
4831 *
4832 * @param name the name of the synthetic identifier
4833 */
4834 ElementResolver_SyntheticIdentifier(String name) {
4835 this._name = name;
4836 }
4837 accept(ASTVisitor visitor) => null;
4838 sc.Token get beginToken => null;
4839 Element get bestElement => null;
4840 sc.Token get endToken => null;
4841 String get name => _name;
4842 Element get propagatedElement => null;
4843 Element get staticElement => null;
4844 void visitChildren(ASTVisitor visitor) {
4845 }
4846 }
4847 /**
4848 * Instances of the class `InheritanceManager` manage the knowledge of where cla ss members
4849 * (methods, getters & setters) are inherited from.
4850 *
4851 * @coverage dart.engine.resolver
4852 */
4853 class InheritanceManager {
4854
4855 /**
4856 * The [LibraryElement] that is managed by this manager.
4857 */
4858 LibraryElement _library;
4859
4860 /**
4861 * This is a mapping between each [ClassElement] and a map between the [String ] member
4862 * names and the associated [ExecutableElement] in the mixin and superclass ch ain.
4863 */
4864 Map<ClassElement, MemberMap> _classLookup;
4865
4866 /**
4867 * This is a mapping between each [ClassElement] and a map between the [String ] member
4868 * names and the associated [ExecutableElement] in the interface set.
4869 */
4870 Map<ClassElement, MemberMap> _interfaceLookup;
4871
4872 /**
4873 * A map between each visited [ClassElement] and the set of [AnalysisError]s f ound on
4874 * the class element.
4875 */
4876 Map<ClassElement, Set<AnalysisError>> _errorsInClassElement = new Map<ClassEle ment, Set<AnalysisError>>();
4877
4878 /**
4879 * Initialize a newly created inheritance manager.
4880 *
4881 * @param library the library element context that the inheritance mappings ar e being generated
4882 */
4883 InheritanceManager(LibraryElement library) {
4884 this._library = library;
4885 _classLookup = new Map<ClassElement, MemberMap>();
4886 _interfaceLookup = new Map<ClassElement, MemberMap>();
4887 }
4888
4889 /**
4890 * Return the set of [AnalysisError]s found on the passed [ClassElement], or
4891 * `null` if there are none.
4892 *
4893 * @param classElt the class element to query
4894 * @return the set of [AnalysisError]s found on the passed [ClassElement], or
4895 * `null` if there are none
4896 */
4897 Set<AnalysisError> getErrors(ClassElement classElt) => _errorsInClassElement[c lassElt];
4898
4899 /**
4900 * Get and return a mapping between the set of all string names of the members inherited from the
4901 * passed [ClassElement] superclass hierarchy, and the associated [ExecutableE lement].
4902 *
4903 * @param classElt the class element to query
4904 * @return a mapping between the set of all members inherited from the passed [ClassElement]
4905 * superclass hierarchy, and the associated [ExecutableElement]
4906 */
4907 MemberMap getMapOfMembersInheritedFromClasses(ClassElement classElt) => comput eClassChainLookupMap(classElt, new Set<ClassElement>());
4908
4909 /**
4910 * Get and return a mapping between the set of all string names of the members inherited from the
4911 * passed [ClassElement] interface hierarchy, and the associated [ExecutableEl ement].
4912 *
4913 * @param classElt the class element to query
4914 * @return a mapping between the set of all string names of the members inheri ted from the passed
4915 * [ClassElement] interface hierarchy, and the associated [ExecutableE lement].
4916 */
4917 MemberMap getMapOfMembersInheritedFromInterfaces(ClassElement classElt) => com puteInterfaceLookupMap(classElt, new Set<ClassElement>());
4918
4919 /**
4920 * Given some [ClassElement] and some member name, this returns the
4921 * [ExecutableElement] that the class inherits from the mixins,
4922 * superclasses or interfaces, that has the member name, if no member is inher ited `null` is
4923 * returned.
4924 *
4925 * @param classElt the class element to query
4926 * @param memberName the name of the executable element to find and return
4927 * @return the inherited executable element with the member name, or `null` if no such
4928 * member exists
4929 */
4930 ExecutableElement lookupInheritance(ClassElement classElt, String memberName) {
4931 if (memberName == null || memberName.isEmpty) {
4932 return null;
4933 }
4934 ExecutableElement executable = computeClassChainLookupMap(classElt, new Set< ClassElement>()).get(memberName);
4935 if (executable == null) {
4936 return computeInterfaceLookupMap(classElt, new Set<ClassElement>()).get(me mberName);
4937 }
4938 return executable;
4939 }
4940
4941 /**
4942 * Given some [ClassElement] and some member name, this returns the
4943 * [ExecutableElement] that the class either declares itself, or
4944 * inherits, that has the member name, if no member is inherited `null` is ret urned.
4945 *
4946 * @param classElt the class element to query
4947 * @param memberName the name of the executable element to find and return
4948 * @return the inherited executable element with the member name, or `null` if no such
4949 * member exists
4950 */
4951 ExecutableElement lookupMember(ClassElement classElt, String memberName) {
4952 ExecutableElement element = lookupMemberInClass(classElt, memberName);
4953 if (element != null) {
4954 return element;
4955 }
4956 return lookupInheritance(classElt, memberName);
4957 }
4958
4959 /**
4960 * Given some [InterfaceType] and some member name, this returns the
4961 * [FunctionType] of the [ExecutableElement] that the
4962 * class either declares itself, or inherits, that has the member name, if no member is inherited
4963 * `null` is returned. The returned [FunctionType] has all type
4964 * parameters substituted with corresponding type arguments from the given [In terfaceType].
4965 *
4966 * @param interfaceType the interface type to query
4967 * @param memberName the name of the executable element to find and return
4968 * @return the member's function type, or `null` if no such member exists
4969 */
4970 FunctionType lookupMemberType(InterfaceType interfaceType, String memberName) {
4971 ExecutableElement iteratorMember = lookupMember(interfaceType.element, membe rName);
4972 if (iteratorMember == null) {
4973 return null;
4974 }
4975 return substituteTypeArgumentsInMemberFromInheritance(iteratorMember.type, m emberName, interfaceType);
4976 }
4977
4978 /**
4979 * Set the new library element context.
4980 *
4981 * @param library the new library element
4982 */
4983 void set libraryElement(LibraryElement library) {
4984 this._library = library;
4985 }
4986
4987 /**
4988 * This method takes some inherited [FunctionType], and resolves all the param eterized types
4989 * in the function type, dependent on the class in which it is being overridde n.
4990 *
4991 * @param baseFunctionType the function type that is being overridden
4992 * @param memberName the name of the member, this is used to lookup the inheri tance path of the
4993 * override
4994 * @param definingType the type that is overriding the member
4995 * @return the passed function type with any parameterized types substituted
4996 */
4997 FunctionType substituteTypeArgumentsInMemberFromInheritance(FunctionType baseF unctionType, String memberName, InterfaceType definingType) {
4998 if (baseFunctionType == null) {
4999 return baseFunctionType;
5000 }
5001 Queue<InterfaceType> inheritancePath = new Queue<InterfaceType>();
5002 computeInheritancePath(inheritancePath, definingType, memberName);
5003 if (inheritancePath == null || inheritancePath.isEmpty) {
5004 return baseFunctionType;
5005 }
5006 FunctionType functionTypeToReturn = baseFunctionType;
5007 while (!inheritancePath.isEmpty) {
5008 InterfaceType lastType = inheritancePath.removeLast();
5009 List<Type2> parameterTypes = lastType.element.type.typeArguments;
5010 List<Type2> argumentTypes = lastType.typeArguments;
5011 functionTypeToReturn = functionTypeToReturn.substitute2(argumentTypes, par ameterTypes);
5012 }
5013 return functionTypeToReturn;
5014 }
5015
5016 /**
5017 * Compute and return a mapping between the set of all string names of the mem bers inherited from
5018 * the passed [ClassElement] superclass hierarchy, and the associated
5019 * [ExecutableElement].
5020 *
5021 * @param classElt the class element to query
5022 * @param visitedClasses a set of visited classes passed back into this method when it calls
5023 * itself recursively
5024 * @return a mapping between the set of all string names of the members inheri ted from the passed
5025 * [ClassElement] superclass hierarchy, and the associated [Executable Element]
5026 */
5027 MemberMap computeClassChainLookupMap(ClassElement classElt, Set<ClassElement> visitedClasses) {
5028 MemberMap resultMap = _classLookup[classElt];
5029 if (resultMap != null) {
5030 return resultMap;
5031 } else {
5032 resultMap = new MemberMap();
5033 }
5034 ClassElement superclassElt = null;
5035 InterfaceType supertype = classElt.supertype;
5036 if (supertype != null) {
5037 superclassElt = supertype.element;
5038 } else {
5039 _classLookup[classElt] = resultMap;
5040 return resultMap;
5041 }
5042 if (superclassElt != null) {
5043 if (!visitedClasses.contains(superclassElt)) {
5044 javaSetAdd(visitedClasses, classElt);
5045 resultMap = new MemberMap.con2(computeClassChainLookupMap(superclassElt, visitedClasses));
5046 } else {
5047 _classLookup[superclassElt] = resultMap;
5048 return resultMap;
5049 }
5050 substituteTypeParametersDownHierarchy(supertype, resultMap);
5051 recordMapWithClassMembers(resultMap, supertype);
5052 }
5053 List<InterfaceType> mixins = classElt.mixins;
5054 for (int i = mixins.length - 1; i >= 0; i--) {
5055 recordMapWithClassMembers(resultMap, mixins[i]);
5056 }
5057 _classLookup[classElt] = resultMap;
5058 return resultMap;
5059 }
5060
5061 /**
5062 * Compute and return the inheritance path given the context of a type and a m ember that is
5063 * overridden in the inheritance path (for which the type is in the path).
5064 *
5065 * @param chain the inheritance path that is built up as this method calls its elf recursively,
5066 * when this method is called an empty [LinkedList] should be provide d
5067 * @param currentType the current type in the inheritance path
5068 * @param memberName the name of the member that is being looked up the inheri tance path
5069 */
5070 void computeInheritancePath(Queue<InterfaceType> chain, InterfaceType currentT ype, String memberName) {
5071 chain.add(currentType);
5072 ClassElement classElt = currentType.element;
5073 InterfaceType supertype = classElt.supertype;
5074 if (supertype == null) {
5075 return;
5076 }
5077 if (chain.length != 1) {
5078 if (lookupMemberInClass(classElt, memberName) != null) {
5079 return;
5080 }
5081 }
5082 List<InterfaceType> mixins = classElt.mixins;
5083 for (int i = mixins.length - 1; i >= 0; i--) {
5084 ClassElement mixinElement = mixins[i].element;
5085 if (mixinElement != null) {
5086 ExecutableElement elt = lookupMemberInClass(mixinElement, memberName);
5087 if (elt != null) {
5088 chain.add(mixins[i]);
5089 return;
5090 }
5091 }
5092 }
5093 ClassElement superclassElt = supertype.element;
5094 if (lookupMember(superclassElt, memberName) != null) {
5095 computeInheritancePath(chain, supertype, memberName);
5096 return;
5097 }
5098 List<InterfaceType> interfaces = classElt.interfaces;
5099 for (InterfaceType interfaceType in interfaces) {
5100 ClassElement interfaceElement = interfaceType.element;
5101 if (interfaceElement != null && lookupMember(interfaceElement, memberName) != null) {
5102 computeInheritancePath(chain, interfaceType, memberName);
5103 return;
5104 }
5105 }
5106 }
5107
5108 /**
5109 * Compute and return a mapping between the set of all string names of the mem bers inherited from
5110 * the passed [ClassElement] interface hierarchy, and the associated
5111 * [ExecutableElement].
5112 *
5113 * @param classElt the class element to query
5114 * @param visitedInterfaces a set of visited classes passed back into this met hod when it calls
5115 * itself recursively
5116 * @return a mapping between the set of all string names of the members inheri ted from the passed
5117 * [ClassElement] interface hierarchy, and the associated [ExecutableE lement]
5118 */
5119 MemberMap computeInterfaceLookupMap(ClassElement classElt, Set<ClassElement> v isitedInterfaces) {
5120 MemberMap resultMap = _interfaceLookup[classElt];
5121 if (resultMap != null) {
5122 return resultMap;
5123 } else {
5124 resultMap = new MemberMap();
5125 }
5126 InterfaceType supertype = classElt.supertype;
5127 ClassElement superclassElement = supertype != null ? supertype.element : nul l;
5128 List<InterfaceType> mixins = classElt.mixins;
5129 List<InterfaceType> interfaces = classElt.interfaces;
5130 List<MemberMap> lookupMaps = new List<MemberMap>();
5131 if (superclassElement != null) {
5132 if (!visitedInterfaces.contains(superclassElement)) {
5133 try {
5134 javaSetAdd(visitedInterfaces, superclassElement);
5135 MemberMap map = computeInterfaceLookupMap(superclassElement, visitedIn terfaces);
5136 map = new MemberMap.con2(map);
5137 substituteTypeParametersDownHierarchy(supertype, map);
5138 recordMapWithClassMembers(map, supertype);
5139 lookupMaps.add(map);
5140 } finally {
5141 visitedInterfaces.remove(superclassElement);
5142 }
5143 } else {
5144 MemberMap map = _interfaceLookup[classElt];
5145 if (map != null) {
5146 lookupMaps.add(map);
5147 } else {
5148 _interfaceLookup[superclassElement] = resultMap;
5149 return resultMap;
5150 }
5151 }
5152 }
5153 for (InterfaceType mixinType in mixins) {
5154 MemberMap mapWithMixinMembers = new MemberMap();
5155 recordMapWithClassMembers(mapWithMixinMembers, mixinType);
5156 lookupMaps.add(mapWithMixinMembers);
5157 }
5158 for (InterfaceType interfaceType in interfaces) {
5159 ClassElement interfaceElement = interfaceType.element;
5160 if (interfaceElement != null) {
5161 if (!visitedInterfaces.contains(interfaceElement)) {
5162 try {
5163 javaSetAdd(visitedInterfaces, interfaceElement);
5164 MemberMap map = computeInterfaceLookupMap(interfaceElement, visitedI nterfaces);
5165 map = new MemberMap.con2(map);
5166 substituteTypeParametersDownHierarchy(interfaceType, map);
5167 recordMapWithClassMembers(map, interfaceType);
5168 lookupMaps.add(map);
5169 } finally {
5170 visitedInterfaces.remove(interfaceElement);
5171 }
5172 } else {
5173 MemberMap map = _interfaceLookup[classElt];
5174 if (map != null) {
5175 lookupMaps.add(map);
5176 } else {
5177 _interfaceLookup[interfaceElement] = resultMap;
5178 return resultMap;
5179 }
5180 }
5181 }
5182 }
5183 if (lookupMaps.length == 0) {
5184 _interfaceLookup[classElt] = resultMap;
5185 return resultMap;
5186 }
5187 Map<String, Set<ExecutableElement>> unionMap = new Map<String, Set<Executabl eElement>>();
5188 for (MemberMap lookupMap in lookupMaps) {
5189 for (int i = 0; i < lookupMap.size; i++) {
5190 String key = lookupMap.getKey(i);
5191 if (key == null) {
5192 break;
5193 }
5194 Set<ExecutableElement> set = unionMap[key];
5195 if (set == null) {
5196 set = new Set<ExecutableElement>();
5197 unionMap[key] = set;
5198 }
5199 javaSetAdd(set, lookupMap.getValue(i));
5200 }
5201 }
5202 for (MapEntry<String, Set<ExecutableElement>> entry in getMapEntrySet(unionM ap)) {
5203 String key = entry.getKey();
5204 Set<ExecutableElement> set = entry.getValue();
5205 int numOfEltsWithMatchingNames = set.length;
5206 if (numOfEltsWithMatchingNames == 1) {
5207 resultMap.put(key, new JavaIterator(set).next());
5208 } else {
5209 bool allMethods = true;
5210 bool allSetters = true;
5211 bool allGetters = true;
5212 for (ExecutableElement executableElement in set) {
5213 if (executableElement is PropertyAccessorElement) {
5214 allMethods = false;
5215 if (((executableElement as PropertyAccessorElement)).isSetter) {
5216 allGetters = false;
5217 } else {
5218 allSetters = false;
5219 }
5220 } else {
5221 allGetters = false;
5222 allSetters = false;
5223 }
5224 }
5225 if (allMethods || allGetters || allSetters) {
5226 List<ExecutableElement> elements = new List.from(set);
5227 List<FunctionType> executableElementTypes = new List<FunctionType>(num OfEltsWithMatchingNames);
5228 for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
5229 executableElementTypes[i] = elements[i].type;
5230 }
5231 bool foundSubtypeOfAllTypes = false;
5232 for (int i = 0; i < numOfEltsWithMatchingNames; i++) {
5233 FunctionType subtype = executableElementTypes[i];
5234 if (subtype == null) {
5235 continue;
5236 }
5237 bool subtypeOfAllTypes = true;
5238 for (int j = 0; j < numOfEltsWithMatchingNames && subtypeOfAllTypes; j++) {
5239 if (i != j) {
5240 if (!subtype.isSubtypeOf(executableElementTypes[j])) {
5241 subtypeOfAllTypes = false;
5242 break;
5243 }
5244 }
5245 }
5246 if (subtypeOfAllTypes) {
5247 foundSubtypeOfAllTypes = true;
5248 resultMap.put(key, elements[i]);
5249 break;
5250 }
5251 }
5252 if (!foundSubtypeOfAllTypes) {
5253 reportError(classElt, classElt.nameOffset, classElt.displayName.leng th, StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE, [key]);
5254 }
5255 } else {
5256 if (!allMethods && !allGetters) {
5257 reportError(classElt, classElt.nameOffset, classElt.displayName.leng th, StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD, [key]);
5258 }
5259 resultMap.remove(entry.getKey());
5260 }
5261 }
5262 }
5263 _interfaceLookup[classElt] = resultMap;
5264 return resultMap;
5265 }
5266
5267 /**
5268 * Given some [ClassElement], this method finds and returns the [ExecutableEle ment] of
5269 * the passed name in the class element. Static members, members in super type s and members not
5270 * accessible from the current library are not considered.
5271 *
5272 * @param classElt the class element to query
5273 * @param memberName the name of the member to lookup in the class
5274 * @return the found [ExecutableElement], or `null` if no such member was foun d
5275 */
5276 ExecutableElement lookupMemberInClass(ClassElement classElt, String memberName ) {
5277 List<MethodElement> methods = classElt.methods;
5278 for (MethodElement method in methods) {
5279 if (memberName == method.name && method.isAccessibleIn(_library) && !metho d.isStatic) {
5280 return method;
5281 }
5282 }
5283 List<PropertyAccessorElement> accessors = classElt.accessors;
5284 for (PropertyAccessorElement accessor in accessors) {
5285 if (memberName == accessor.name && accessor.isAccessibleIn(_library) && !a ccessor.isStatic) {
5286 return accessor;
5287 }
5288 }
5289 return null;
5290 }
5291
5292 /**
5293 * Record the passed map with the set of all members (methods, getters and set ters) in the type
5294 * into the passed map.
5295 *
5296 * @param map some non-`null` map to put the methods and accessors from the pa ssed
5297 * [ClassElement] into
5298 * @param type the type that will be recorded into the passed map
5299 */
5300 void recordMapWithClassMembers(MemberMap map, InterfaceType type) {
5301 List<MethodElement> methods = type.methods;
5302 for (MethodElement method in methods) {
5303 if (method.isAccessibleIn(_library) && !method.isStatic) {
5304 map.put(method.name, method);
5305 }
5306 }
5307 List<PropertyAccessorElement> accessors = type.accessors;
5308 for (PropertyAccessorElement accessor in accessors) {
5309 if (accessor.isAccessibleIn(_library) && !accessor.isStatic) {
5310 map.put(accessor.name, accessor);
5311 }
5312 }
5313 }
5314
5315 /**
5316 * This method is used to report errors on when they are found computing inher itance information.
5317 * See [ErrorVerifier#checkForInconsistentMethodInheritance] to see where thes e generated
5318 * error codes are reported back into the analysis engine.
5319 *
5320 * @param classElt the location of the source for which the exception occurred
5321 * @param offset the offset of the location of the error
5322 * @param length the length of the location of the error
5323 * @param errorCode the error code to be associated with this error
5324 * @param arguments the arguments used to build the error message
5325 */
5326 void reportError(ClassElement classElt, int offset, int length, ErrorCode erro rCode, List<Object> arguments) {
5327 Set<AnalysisError> errorSet = _errorsInClassElement[classElt];
5328 if (errorSet == null) {
5329 errorSet = new Set<AnalysisError>();
5330 _errorsInClassElement[classElt] = errorSet;
5331 }
5332 javaSetAdd(errorSet, new AnalysisError.con2(classElt.source, offset, length, errorCode, arguments));
5333 }
5334
5335 /**
5336 * Loop through all of the members in some [MemberMap], performing type parame ter
5337 * substitutions using a passed supertype.
5338 *
5339 * @param superType the supertype to substitute into the members of the [Membe rMap]
5340 * @param map the MemberMap to perform the substitutions on
5341 */
5342 void substituteTypeParametersDownHierarchy(InterfaceType superType, MemberMap map) {
5343 for (int i = 0; i < map.size; i++) {
5344 String key = map.getKey(i);
5345 ExecutableElement executableElement = map.getValue(i);
5346 if (executableElement is MethodMember) {
5347 executableElement = MethodMember.from(executableElement as MethodMember, superType);
5348 map.put(key, executableElement);
5349 } else if (executableElement is PropertyAccessorMember) {
5350 executableElement = PropertyAccessorMember.from(executableElement as Pro pertyAccessorMember, superType);
5351 map.put(key, executableElement);
5352 }
5353 }
5354 }
5355 }
5356 /**
5357 * Instances of the class `Library` represent the data about a single library du ring the
5358 * resolution of some (possibly different) library. They are not intended to be used except during
5359 * the resolution process.
5360 *
5361 * @coverage dart.engine.resolver
5362 */
5363 class Library {
5364
5365 /**
5366 * The analysis context in which this library is being analyzed.
5367 */
5368 InternalAnalysisContext _analysisContext;
5369
5370 /**
5371 * The inheritance manager which is used for this member lookups in this libra ry.
5372 */
5373 InheritanceManager _inheritanceManager;
5374
5375 /**
5376 * The listener to which analysis errors will be reported.
5377 */
5378 AnalysisErrorListener _errorListener;
5379
5380 /**
5381 * The source specifying the defining compilation unit of this library.
5382 */
5383 Source librarySource;
5384
5385 /**
5386 * The library element representing this library.
5387 */
5388 LibraryElementImpl _libraryElement;
5389
5390 /**
5391 * A list containing all of the libraries that are imported into this library.
5392 */
5393 List<Library> imports = _EMPTY_ARRAY;
5394
5395 /**
5396 * A table mapping URI-based directive to the actual URI value.
5397 */
5398 Map<UriBasedDirective, String> _directiveUris = new Map<UriBasedDirective, Str ing>();
5399
5400 /**
5401 * A flag indicating whether this library explicitly imports core.
5402 */
5403 bool explicitlyImportsCore = false;
5404
5405 /**
5406 * A list containing all of the libraries that are exported from this library.
5407 */
5408 List<Library> exports = _EMPTY_ARRAY;
5409
5410 /**
5411 * A table mapping the sources for the compilation units in this library to th eir corresponding
5412 * AST structures.
5413 */
5414 Map<Source, ResolvableCompilationUnit> _astMap = new Map<Source, ResolvableCom pilationUnit>();
5415
5416 /**
5417 * The library scope used when resolving elements within this library's compil ation units.
5418 */
5419 LibraryScope _libraryScope;
5420
5421 /**
5422 * An empty array that can be used to initialize lists of libraries.
5423 */
5424 static List<Library> _EMPTY_ARRAY = new List<Library>(0);
5425
5426 /**
5427 * Initialize a newly created data holder that can maintain the data associate d with a library.
5428 *
5429 * @param analysisContext the analysis context in which this library is being analyzed
5430 * @param errorListener the listener to which analysis errors will be reported
5431 * @param librarySource the source specifying the defining compilation unit of this library
5432 */
5433 Library(InternalAnalysisContext analysisContext, AnalysisErrorListener errorLi stener, Source librarySource) {
5434 this._analysisContext = analysisContext;
5435 this._errorListener = errorListener;
5436 this.librarySource = librarySource;
5437 this._libraryElement = analysisContext.getLibraryElement(librarySource) as L ibraryElementImpl;
5438 }
5439
5440 /**
5441 * Return the AST structure associated with the given source.
5442 *
5443 * @param source the source representing the compilation unit whose AST is to be returned
5444 * @return the AST structure associated with the given source
5445 * @throws AnalysisException if an AST structure could not be created for the compilation unit
5446 */
5447 CompilationUnit getAST(Source source) {
5448 ResolvableCompilationUnit holder = _astMap[source];
5449 if (holder == null) {
5450 holder = _analysisContext.computeResolvableCompilationUnit(source);
5451 _astMap[source] = holder;
5452 }
5453 return holder.compilationUnit;
5454 }
5455
5456 /**
5457 * Return an array of the [CompilationUnit]s that make up the library. The fir st unit is
5458 * always the defining unit.
5459 *
5460 * @return an array of the [CompilationUnit]s that make up the library. The fi rst unit is
5461 * always the defining unit
5462 */
5463 List<CompilationUnit> get compilationUnits {
5464 List<CompilationUnit> unitArrayList = new List<CompilationUnit>();
5465 unitArrayList.add(definingCompilationUnit);
5466 for (Source source in _astMap.keys.toSet()) {
5467 if (librarySource != source) {
5468 unitArrayList.add(getAST(source));
5469 }
5470 }
5471 return new List.from(unitArrayList);
5472 }
5473
5474 /**
5475 * Return a collection containing the sources for the compilation units in thi s library, including
5476 * the defining compilation unit.
5477 *
5478 * @return the sources for the compilation units in this library
5479 */
5480 Set<Source> get compilationUnitSources => _astMap.keys.toSet();
5481
5482 /**
5483 * Return the AST structure associated with the defining compilation unit for this library.
5484 *
5485 * @return the AST structure associated with the defining compilation unit for this library
5486 * @throws AnalysisException if an AST structure could not be created for the defining compilation
5487 * unit
5488 */
5489 CompilationUnit get definingCompilationUnit => getAST(librarySource);
5490
5491 /**
5492 * Return an array containing the libraries that are either imported or export ed from this
5493 * library.
5494 *
5495 * @return the libraries that are either imported or exported from this librar y
5496 */
5497 List<Library> get importsAndExports {
5498 Set<Library> libraries = new Set<Library>();
5499 for (Library library in imports) {
5500 javaSetAdd(libraries, library);
5501 }
5502 for (Library library in exports) {
5503 javaSetAdd(libraries, library);
5504 }
5505 return new List.from(libraries);
5506 }
5507
5508 /**
5509 * Return the inheritance manager for this library.
5510 *
5511 * @return the inheritance manager for this library
5512 */
5513 InheritanceManager get inheritanceManager {
5514 if (_inheritanceManager == null) {
5515 return _inheritanceManager = new InheritanceManager(_libraryElement);
5516 }
5517 return _inheritanceManager;
5518 }
5519
5520 /**
5521 * Return the library element representing this library, creating it if necess ary.
5522 *
5523 * @return the library element representing this library
5524 */
5525 LibraryElementImpl get libraryElement {
5526 if (_libraryElement == null) {
5527 try {
5528 _libraryElement = _analysisContext.computeLibraryElement(librarySource) as LibraryElementImpl;
5529 } on AnalysisException catch (exception) {
5530 AnalysisEngine.instance.logger.logError2("Could not compute library elem ent for ${librarySource.fullName}", exception);
5531 }
5532 }
5533 return _libraryElement;
5534 }
5535
5536 /**
5537 * Return the library scope used when resolving elements within this library's compilation units.
5538 *
5539 * @return the library scope used when resolving elements within this library' s compilation units
5540 */
5541 LibraryScope get libraryScope {
5542 if (_libraryScope == null) {
5543 _libraryScope = new LibraryScope(_libraryElement, _errorListener);
5544 }
5545 return _libraryScope;
5546 }
5547
5548 /**
5549 * Return the modification time associated with the given source.
5550 *
5551 * @param source the source representing the compilation unit whose modificati on time is to be
5552 * returned
5553 * @return the modification time associated with the given source
5554 * @throws AnalysisException if an AST structure could not be created for the compilation unit
5555 */
5556 int getModificationTime(Source source) {
5557 ResolvableCompilationUnit holder = _astMap[source];
5558 if (holder == null) {
5559 holder = _analysisContext.computeResolvableCompilationUnit(source);
5560 _astMap[source] = holder;
5561 }
5562 return holder.modificationTime;
5563 }
5564
5565 /**
5566 * Return the result of resolving the URI of the given URI-based directive aga inst the URI of the
5567 * library, or `null` if the URI is not valid. If the URI is not valid, report the error.
5568 *
5569 * @param directive the directive which URI should be resolved
5570 * @return the result of resolving the URI against the URI of the library
5571 */
5572 Source getSource(UriBasedDirective directive) {
5573 StringLiteral uriLiteral = directive.uri;
5574 if (uriLiteral is StringInterpolation) {
5575 _errorListener.onError(new AnalysisError.con2(librarySource, uriLiteral.of fset, uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION, []));
5576 return null;
5577 }
5578 String uriContent = uriLiteral.stringValue.trim();
5579 _directiveUris[directive] = uriContent;
5580 uriContent = Uri.encodeFull(uriContent);
5581 try {
5582 parseUriWithException(uriContent);
5583 Source source = _analysisContext.sourceFactory.resolveUri(librarySource, u riContent);
5584 if (source == null || !source.exists()) {
5585 _errorListener.onError(new AnalysisError.con2(librarySource, uriLiteral. offset, uriLiteral.length, CompileTimeErrorCode.URI_DOES_NOT_EXIST, [uriContent] ));
5586 }
5587 return source;
5588 } on URISyntaxException catch (exception) {
5589 _errorListener.onError(new AnalysisError.con2(librarySource, uriLiteral.of fset, uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriContent]));
5590 }
5591 return null;
5592 }
5593
5594 /**
5595 * Returns the URI value of the given directive.
5596 */
5597 String getUri(UriBasedDirective directive) => _directiveUris[directive];
5598
5599 /**
5600 * Set the AST structure associated with the defining compilation unit for thi s library to the
5601 * given AST structure.
5602 *
5603 * @param modificationStamp the modification time of the source from which the compilation unit
5604 * was created
5605 * @param unit the AST structure associated with the defining compilation unit for this library
5606 */
5607 void setDefiningCompilationUnit(int modificationStamp, CompilationUnit unit) {
5608 _astMap[librarySource] = new ResolvableCompilationUnit(modificationStamp, un it);
5609 }
5610
5611 /**
5612 * Set the libraries that are exported by this library to be those in the give n array.
5613 *
5614 * @param exportedLibraries the libraries that are exported by this library
5615 */
5616 void set exportedLibraries(List<Library> exportedLibraries) {
5617 this.exports = exportedLibraries;
5618 }
5619
5620 /**
5621 * Set the libraries that are imported into this library to be those in the gi ven array.
5622 *
5623 * @param importedLibraries the libraries that are imported into this library
5624 */
5625 void set importedLibraries(List<Library> importedLibraries) {
5626 this.imports = importedLibraries;
5627 }
5628
5629 /**
5630 * Set the library element representing this library to the given library elem ent.
5631 *
5632 * @param libraryElement the library element representing this library
5633 */
5634 void set libraryElement(LibraryElementImpl libraryElement) {
5635 this._libraryElement = libraryElement;
5636 if (_inheritanceManager != null) {
5637 _inheritanceManager.libraryElement = libraryElement;
5638 }
5639 }
5640 String toString() => librarySource.shortName;
5641 }
5642 /**
5643 * Instances of the class `LibraryElementBuilder` build an element model for a s ingle library.
5644 *
5645 * @coverage dart.engine.resolver
5646 */
5647 class LibraryElementBuilder {
5648
5649 /**
5650 * The analysis context in which the element model will be built.
5651 */
5652 InternalAnalysisContext _analysisContext;
5653
5654 /**
5655 * The listener to which errors will be reported.
5656 */
5657 AnalysisErrorListener _errorListener;
5658
5659 /**
5660 * The name of the function used as an entry point.
5661 */
5662 static String _ENTRY_POINT_NAME = "main";
5663
5664 /**
5665 * Initialize a newly created library element builder.
5666 *
5667 * @param resolver the resolver for which the element model is being built
5668 */
5669 LibraryElementBuilder(LibraryResolver resolver) {
5670 this._analysisContext = resolver.analysisContext;
5671 this._errorListener = resolver.errorListener;
5672 }
5673
5674 /**
5675 * Build the library element for the given library.
5676 *
5677 * @param library the library for which an element model is to be built
5678 * @return the library element that was built
5679 * @throws AnalysisException if the analysis could not be performed
5680 */
5681 LibraryElementImpl buildLibrary(Library library) {
5682 CompilationUnitBuilder builder = new CompilationUnitBuilder();
5683 Source librarySource = library.librarySource;
5684 CompilationUnit definingCompilationUnit = library.definingCompilationUnit;
5685 CompilationUnitElementImpl definingCompilationUnitElement = builder.buildCom pilationUnit(librarySource, definingCompilationUnit);
5686 NodeList<Directive> directives = definingCompilationUnit.directives;
5687 LibraryIdentifier libraryNameNode = null;
5688 bool hasPartDirective = false;
5689 FunctionElement entryPoint = findEntryPoint(definingCompilationUnitElement);
5690 List<Directive> directivesToResolve = new List<Directive>();
5691 List<CompilationUnitElementImpl> sourcedCompilationUnits = new List<Compilat ionUnitElementImpl>();
5692 for (Directive directive in directives) {
5693 if (directive is LibraryDirective) {
5694 if (libraryNameNode == null) {
5695 libraryNameNode = ((directive as LibraryDirective)).name;
5696 directivesToResolve.add(directive);
5697 }
5698 } else if (directive is PartDirective) {
5699 PartDirective partDirective = directive as PartDirective;
5700 StringLiteral partUri = partDirective.uri;
5701 Source partSource = library.getSource(partDirective);
5702 if (partSource != null && partSource.exists()) {
5703 hasPartDirective = true;
5704 CompilationUnitElementImpl part = builder.buildCompilationUnit(partSou rce, library.getAST(partSource));
5705 part.uri = library.getUri(partDirective);
5706 String partLibraryName = getPartLibraryName(library, partSource, direc tivesToResolve);
5707 if (partLibraryName == null) {
5708 _errorListener.onError(new AnalysisError.con2(librarySource, partUri .offset, partUri.length, CompileTimeErrorCode.PART_OF_NON_PART, [partUri.toSourc e()]));
5709 } else if (libraryNameNode == null) {
5710 } else if (libraryNameNode.name != partLibraryName) {
5711 _errorListener.onError(new AnalysisError.con2(librarySource, partUri .offset, partUri.length, StaticWarningCode.PART_OF_DIFFERENT_LIBRARY, [libraryNa meNode.name, partLibraryName]));
5712 }
5713 if (entryPoint == null) {
5714 entryPoint = findEntryPoint(part);
5715 }
5716 directive.element = part;
5717 sourcedCompilationUnits.add(part);
5718 }
5719 }
5720 }
5721 if (hasPartDirective && libraryNameNode == null) {
5722 _errorListener.onError(new AnalysisError.con1(librarySource, ResolverError Code.MISSING_LIBRARY_DIRECTIVE_WITH_PART, []));
5723 }
5724 LibraryElementImpl libraryElement = new LibraryElementImpl(_analysisContext, libraryNameNode);
5725 libraryElement.definingCompilationUnit = definingCompilationUnitElement;
5726 if (entryPoint != null) {
5727 libraryElement.entryPoint = entryPoint;
5728 }
5729 int sourcedUnitCount = sourcedCompilationUnits.length;
5730 libraryElement.parts = new List.from(sourcedCompilationUnits);
5731 for (Directive directive in directivesToResolve) {
5732 directive.element = libraryElement;
5733 }
5734 library.libraryElement = libraryElement;
5735 if (sourcedUnitCount > 0) {
5736 patchTopLevelAccessors(libraryElement);
5737 }
5738 return libraryElement;
5739 }
5740
5741 /**
5742 * Add all of the non-synthetic getters and setters defined in the given compi lation unit that
5743 * have no corresponding accessor to one of the given collections.
5744 *
5745 * @param getters the map to which getters are to be added
5746 * @param setters the list to which setters are to be added
5747 * @param unit the compilation unit defining the accessors that are potentiall y being added
5748 */
5749 void collectAccessors(Map<String, PropertyAccessorElement> getters, List<Prope rtyAccessorElement> setters, CompilationUnitElement unit) {
5750 for (PropertyAccessorElement accessor in unit.accessors) {
5751 if (accessor.isGetter) {
5752 if (!accessor.isSynthetic && accessor.correspondingSetter == null) {
5753 getters[accessor.displayName] = accessor;
5754 }
5755 } else {
5756 if (!accessor.isSynthetic && accessor.correspondingGetter == null) {
5757 setters.add(accessor);
5758 }
5759 }
5760 }
5761 }
5762
5763 /**
5764 * Search the top-level functions defined in the given compilation unit for th e entry point.
5765 *
5766 * @param element the compilation unit to be searched
5767 * @return the entry point that was found, or `null` if the compilation unit d oes not define
5768 * an entry point
5769 */
5770 FunctionElement findEntryPoint(CompilationUnitElementImpl element) {
5771 for (FunctionElement function in element.functions) {
5772 if (function.name == _ENTRY_POINT_NAME) {
5773 return function;
5774 }
5775 }
5776 return null;
5777 }
5778
5779 /**
5780 * Return the name of the library that the given part is declared to be a part of, or `null`
5781 * if the part does not contain a part-of directive.
5782 *
5783 * @param library the library containing the part
5784 * @param partSource the source representing the part
5785 * @param directivesToResolve a list of directives that should be resolved to the library being
5786 * built
5787 * @return the name of the library that the given part is declared to be a par t of
5788 */
5789 String getPartLibraryName(Library library, Source partSource, List<Directive> directivesToResolve) {
5790 try {
5791 CompilationUnit partUnit = library.getAST(partSource);
5792 for (Directive directive in partUnit.directives) {
5793 if (directive is PartOfDirective) {
5794 directivesToResolve.add(directive);
5795 LibraryIdentifier libraryName = ((directive as PartOfDirective)).libra ryName;
5796 if (libraryName != null) {
5797 return libraryName.name;
5798 }
5799 }
5800 }
5801 } on AnalysisException catch (exception) {
5802 }
5803 return null;
5804 }
5805
5806 /**
5807 * Look through all of the compilation units defined for the given library, lo oking for getters
5808 * and setters that are defined in different compilation units but that have t he same names. If
5809 * any are found, make sure that they have the same variable element.
5810 *
5811 * @param libraryElement the library defining the compilation units to be proc essed
5812 */
5813 void patchTopLevelAccessors(LibraryElementImpl libraryElement) {
5814 Map<String, PropertyAccessorElement> getters = new Map<String, PropertyAcces sorElement>();
5815 List<PropertyAccessorElement> setters = new List<PropertyAccessorElement>();
5816 collectAccessors(getters, setters, libraryElement.definingCompilationUnit);
5817 for (CompilationUnitElement unit in libraryElement.parts) {
5818 collectAccessors(getters, setters, unit);
5819 }
5820 for (PropertyAccessorElement setter in setters) {
5821 PropertyAccessorElement getter = getters[setter.displayName];
5822 if (getter != null) {
5823 PropertyInducingElementImpl variable = getter.variable as PropertyInduci ngElementImpl;
5824 variable.setter = setter;
5825 ((setter as PropertyAccessorElementImpl)).variable = variable;
5826 }
5827 }
5828 }
5829 }
5830 /**
5831 * Instances of the class `LibraryResolver` are used to resolve one or more mutu ally dependent
5832 * libraries within a single context.
5833 *
5834 * @coverage dart.engine.resolver
5835 */
5836 class LibraryResolver {
5837
5838 /**
5839 * The analysis context in which the libraries are being analyzed.
5840 */
5841 InternalAnalysisContext analysisContext;
5842
5843 /**
5844 * The listener to which analysis errors will be reported, this error listener is either
5845 * references [recordingErrorListener], or it unions the passed
5846 * [AnalysisErrorListener] with the [recordingErrorListener].
5847 */
5848 RecordingErrorListener errorListener;
5849
5850 /**
5851 * A source object representing the core library (dart:core).
5852 */
5853 Source _coreLibrarySource;
5854
5855 /**
5856 * The object representing the core library.
5857 */
5858 Library _coreLibrary;
5859
5860 /**
5861 * The object used to access the types from the core library.
5862 */
5863 TypeProvider _typeProvider;
5864
5865 /**
5866 * A table mapping library sources to the information being maintained for tho se libraries.
5867 */
5868 Map<Source, Library> _libraryMap = new Map<Source, Library>();
5869
5870 /**
5871 * A collection containing the libraries that are being resolved together.
5872 */
5873 Set<Library> resolvedLibraries;
5874
5875 /**
5876 * Initialize a newly created library resolver to resolve libraries within the given context.
5877 *
5878 * @param analysisContext the analysis context in which the library is being a nalyzed
5879 */
5880 LibraryResolver(InternalAnalysisContext analysisContext) {
5881 this.analysisContext = analysisContext;
5882 this.errorListener = new RecordingErrorListener();
5883 _coreLibrarySource = analysisContext.sourceFactory.forUri(DartSdk.DART_CORE) ;
5884 }
5885
5886 /**
5887 * Resolve the library specified by the given source in the given context. The library is assumed
5888 * to be embedded in the given source.
5889 *
5890 * @param librarySource the source specifying the defining compilation unit of the library to be
5891 * resolved
5892 * @param modificationStamp the time stamp of the source from which the compil ation unit was
5893 * created
5894 * @param unit the compilation unit representing the embedded library
5895 * @param fullAnalysis `true` if a full analysis should be performed
5896 * @return the element representing the resolved library
5897 * @throws AnalysisException if the library could not be resolved for some rea son
5898 */
5899 LibraryElement resolveEmbeddedLibrary(Source librarySource, int modificationSt amp, CompilationUnit unit, bool fullAnalysis) {
5900 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.LibraryResolver.resolveEmbeddedLibrary");
5901 try {
5902 instrumentation.metric("fullAnalysis", fullAnalysis);
5903 instrumentation.data3("fullName", librarySource.fullName);
5904 Library targetLibrary = createLibrary2(librarySource, modificationStamp, u nit);
5905 _coreLibrary = _libraryMap[_coreLibrarySource];
5906 if (_coreLibrary == null) {
5907 _coreLibrary = createLibrary(_coreLibrarySource);
5908 }
5909 instrumentation.metric3("createLibrary", "complete");
5910 computeLibraryDependencies2(targetLibrary, unit);
5911 resolvedLibraries = computeLibrariesInCycles(targetLibrary);
5912 buildElementModels();
5913 instrumentation.metric3("buildElementModels", "complete");
5914 LibraryElement coreElement = _coreLibrary.libraryElement;
5915 if (coreElement == null) {
5916 throw new AnalysisException.con1("Could not resolve dart:core");
5917 }
5918 buildDirectiveModels();
5919 instrumentation.metric3("buildDirectiveModels", "complete");
5920 _typeProvider = new TypeProviderImpl(coreElement);
5921 buildTypeHierarchies();
5922 instrumentation.metric3("buildTypeHierarchies", "complete");
5923 resolveReferencesAndTypes();
5924 instrumentation.metric3("resolveReferencesAndTypes", "complete");
5925 performConstantEvaluation();
5926 instrumentation.metric3("performConstantEvaluation", "complete");
5927 return targetLibrary.libraryElement;
5928 } finally {
5929 instrumentation.log();
5930 }
5931 }
5932
5933 /**
5934 * Resolve the library specified by the given source in the given context.
5935 *
5936 * Note that because Dart allows circular imports between libraries, it is pos sible that more than
5937 * one library will need to be resolved. In such cases the error listener can receive errors from
5938 * multiple libraries.
5939 *
5940 * @param librarySource the source specifying the defining compilation unit of the library to be
5941 * resolved
5942 * @param fullAnalysis `true` if a full analysis should be performed
5943 * @return the element representing the resolved library
5944 * @throws AnalysisException if the library could not be resolved for some rea son
5945 */
5946 LibraryElement resolveLibrary(Source librarySource, bool fullAnalysis) {
5947 InstrumentationBuilder instrumentation = Instrumentation.builder2("dart.engi ne.LibraryResolver.resolveLibrary");
5948 try {
5949 instrumentation.metric("fullAnalysis", fullAnalysis);
5950 instrumentation.data3("fullName", librarySource.fullName);
5951 Library targetLibrary = createLibrary(librarySource);
5952 _coreLibrary = _libraryMap[_coreLibrarySource];
5953 if (_coreLibrary == null) {
5954 _coreLibrary = createLibrary(_coreLibrarySource);
5955 }
5956 instrumentation.metric3("createLibrary", "complete");
5957 computeLibraryDependencies(targetLibrary);
5958 resolvedLibraries = computeLibrariesInCycles(targetLibrary);
5959 buildElementModels();
5960 instrumentation.metric3("buildElementModels", "complete");
5961 LibraryElement coreElement = _coreLibrary.libraryElement;
5962 if (coreElement == null) {
5963 throw new AnalysisException.con1("Could not resolve dart:core");
5964 }
5965 buildDirectiveModels();
5966 instrumentation.metric3("buildDirectiveModels", "complete");
5967 _typeProvider = new TypeProviderImpl(coreElement);
5968 buildTypeHierarchies();
5969 instrumentation.metric3("buildTypeHierarchies", "complete");
5970 resolveReferencesAndTypes();
5971 instrumentation.metric3("resolveReferencesAndTypes", "complete");
5972 performConstantEvaluation();
5973 instrumentation.metric3("performConstantEvaluation", "complete");
5974 instrumentation.metric2("librariesInCycles", resolvedLibraries.length);
5975 for (Library lib in resolvedLibraries) {
5976 instrumentation.metric2("librariesInCycles-CompilationUnitSources-Size", lib.compilationUnitSources.length);
5977 }
5978 return targetLibrary.libraryElement;
5979 } finally {
5980 instrumentation.log();
5981 }
5982 }
5983
5984 /**
5985 * Add a dependency to the given map from the referencing library to the refer enced library.
5986 *
5987 * @param dependencyMap the map to which the dependency is to be added
5988 * @param referencingLibrary the library that references the referenced librar y
5989 * @param referencedLibrary the library referenced by the referencing library
5990 */
5991 void addDependencyToMap(Map<Library, List<Library>> dependencyMap, Library ref erencingLibrary, Library referencedLibrary) {
5992 List<Library> dependentLibraries = dependencyMap[referencedLibrary];
5993 if (dependentLibraries == null) {
5994 dependentLibraries = new List<Library>();
5995 dependencyMap[referencedLibrary] = dependentLibraries;
5996 }
5997 dependentLibraries.add(referencingLibrary);
5998 }
5999
6000 /**
6001 * Given a library that is part of a cycle that includes the root library, add to the given set of
6002 * libraries all of the libraries reachable from the root library that are als o included in the
6003 * cycle.
6004 *
6005 * @param library the library to be added to the collection of libraries in cy cles
6006 * @param librariesInCycle a collection of the libraries that are in the cycle
6007 * @param dependencyMap a table mapping libraries to the collection of librari es from which those
6008 * libraries are referenced
6009 */
6010 void addLibrariesInCycle(Library library, Set<Library> librariesInCycle, Map<L ibrary, List<Library>> dependencyMap) {
6011 if (javaSetAdd(librariesInCycle, library)) {
6012 List<Library> dependentLibraries = dependencyMap[library];
6013 if (dependentLibraries != null) {
6014 for (Library dependentLibrary in dependentLibraries) {
6015 addLibrariesInCycle(dependentLibrary, librariesInCycle, dependencyMap) ;
6016 }
6017 }
6018 }
6019 }
6020
6021 /**
6022 * Add the given library, and all libraries reachable from it that have not al ready been visited,
6023 * to the given dependency map.
6024 *
6025 * @param library the library currently being added to the dependency map
6026 * @param dependencyMap the dependency map being computed
6027 * @param visitedLibraries the libraries that have already been visited, used to prevent infinite
6028 * recursion
6029 */
6030 void addToDependencyMap(Library library, Map<Library, List<Library>> dependenc yMap, Set<Library> visitedLibraries) {
6031 if (javaSetAdd(visitedLibraries, library)) {
6032 for (Library referencedLibrary in library.importsAndExports) {
6033 addDependencyToMap(dependencyMap, library, referencedLibrary);
6034 addToDependencyMap(referencedLibrary, dependencyMap, visitedLibraries);
6035 }
6036 if (!library.explicitlyImportsCore && library != _coreLibrary) {
6037 addDependencyToMap(dependencyMap, library, _coreLibrary);
6038 }
6039 }
6040 }
6041
6042 /**
6043 * Build the element model representing the combinators declared by the given directive.
6044 *
6045 * @param directive the directive that declares the combinators
6046 * @return an array containing the import combinators that were built
6047 */
6048 List<NamespaceCombinator> buildCombinators(NamespaceDirective directive) {
6049 List<NamespaceCombinator> combinators = new List<NamespaceCombinator>();
6050 for (Combinator combinator in directive.combinators) {
6051 if (combinator is HideCombinator) {
6052 HideElementCombinatorImpl hide = new HideElementCombinatorImpl();
6053 hide.hiddenNames = getIdentifiers(((combinator as HideCombinator)).hidde nNames);
6054 combinators.add(hide);
6055 } else {
6056 ShowElementCombinatorImpl show = new ShowElementCombinatorImpl();
6057 show.offset = combinator.offset;
6058 show.end = combinator.end;
6059 show.shownNames = getIdentifiers(((combinator as ShowCombinator)).shownN ames);
6060 combinators.add(show);
6061 }
6062 }
6063 return new List.from(combinators);
6064 }
6065
6066 /**
6067 * Every library now has a corresponding [LibraryElement], so it is now possib le to resolve
6068 * the import and export directives.
6069 *
6070 * @throws AnalysisException if the defining compilation unit for any of the l ibraries could not
6071 * be accessed
6072 */
6073 void buildDirectiveModels() {
6074 for (Library library in resolvedLibraries) {
6075 Map<String, PrefixElementImpl> nameToPrefixMap = new Map<String, PrefixEle mentImpl>();
6076 List<ImportElement> imports = new List<ImportElement>();
6077 List<ExportElement> exports = new List<ExportElement>();
6078 for (Directive directive in library.definingCompilationUnit.directives) {
6079 if (directive is ImportDirective) {
6080 ImportDirective importDirective = directive as ImportDirective;
6081 Source importedSource = library.getSource(importDirective);
6082 if (importedSource != null) {
6083 Library importedLibrary = _libraryMap[importedSource];
6084 if (importedLibrary != null) {
6085 ImportElementImpl importElement = new ImportElementImpl();
6086 importElement.offset = directive.offset;
6087 StringLiteral uriLiteral = importDirective.uri;
6088 if (uriLiteral != null) {
6089 importElement.uriEnd = uriLiteral.end;
6090 }
6091 importElement.uri = library.getUri(importDirective);
6092 importElement.combinators = buildCombinators(importDirective);
6093 LibraryElement importedLibraryElement = importedLibrary.libraryEle ment;
6094 if (importedLibraryElement != null) {
6095 importElement.importedLibrary = importedLibraryElement;
6096 }
6097 SimpleIdentifier prefixNode = ((directive as ImportDirective)).pre fix;
6098 if (prefixNode != null) {
6099 importElement.prefixOffset = prefixNode.offset;
6100 String prefixName = prefixNode.name;
6101 PrefixElementImpl prefix = nameToPrefixMap[prefixName];
6102 if (prefix == null) {
6103 prefix = new PrefixElementImpl(prefixNode);
6104 nameToPrefixMap[prefixName] = prefix;
6105 }
6106 importElement.prefix = prefix;
6107 prefixNode.staticElement = prefix;
6108 }
6109 directive.element = importElement;
6110 imports.add(importElement);
6111 if (doesCompilationUnitHavePartOfDirective(importedLibrary.getAST( importedSource))) {
6112 errorListener.onError(new AnalysisError.con2(library.librarySour ce, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.IMPORT_OF_NON_LIB RARY, [uriLiteral.toSource()]));
6113 }
6114 }
6115 }
6116 } else if (directive is ExportDirective) {
6117 ExportDirective exportDirective = directive as ExportDirective;
6118 Source exportedSource = library.getSource(exportDirective);
6119 if (exportedSource != null) {
6120 Library exportedLibrary = _libraryMap[exportedSource];
6121 if (exportedLibrary != null) {
6122 ExportElementImpl exportElement = new ExportElementImpl();
6123 exportElement.uri = library.getUri(exportDirective);
6124 exportElement.combinators = buildCombinators(exportDirective);
6125 LibraryElement exportedLibraryElement = exportedLibrary.libraryEle ment;
6126 if (exportedLibraryElement != null) {
6127 exportElement.exportedLibrary = exportedLibraryElement;
6128 }
6129 directive.element = exportElement;
6130 exports.add(exportElement);
6131 if (doesCompilationUnitHavePartOfDirective(exportedLibrary.getAST( exportedSource))) {
6132 StringLiteral uriLiteral = exportDirective.uri;
6133 errorListener.onError(new AnalysisError.con2(library.librarySour ce, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.EXPORT_OF_NON_LIB RARY, [uriLiteral.toSource()]));
6134 }
6135 }
6136 }
6137 }
6138 }
6139 Source librarySource = library.librarySource;
6140 if (!library.explicitlyImportsCore && _coreLibrarySource != librarySource) {
6141 ImportElementImpl importElement = new ImportElementImpl();
6142 importElement.importedLibrary = _coreLibrary.libraryElement;
6143 importElement.synthetic = true;
6144 imports.add(importElement);
6145 }
6146 LibraryElementImpl libraryElement = library.libraryElement;
6147 libraryElement.imports = new List.from(imports);
6148 libraryElement.exports = new List.from(exports);
6149 }
6150 }
6151
6152 /**
6153 * Build element models for all of the libraries in the current cycle.
6154 *
6155 * @throws AnalysisException if any of the element models cannot be built
6156 */
6157 void buildElementModels() {
6158 for (Library library in resolvedLibraries) {
6159 LibraryElementBuilder builder = new LibraryElementBuilder(this);
6160 LibraryElementImpl libraryElement = builder.buildLibrary(library);
6161 library.libraryElement = libraryElement;
6162 }
6163 }
6164
6165 /**
6166 * Resolve the type hierarchy across all of the types declared in the librarie s in the current
6167 * cycle.
6168 *
6169 * @throws AnalysisException if any of the type hierarchies could not be resol ved
6170 */
6171 void buildTypeHierarchies() {
6172 TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.st art();
6173 try {
6174 for (Library library in resolvedLibraries) {
6175 for (Source source in library.compilationUnitSources) {
6176 TypeResolverVisitor visitor = new TypeResolverVisitor.con1(library, so urce, _typeProvider);
6177 library.getAST(source).accept(visitor);
6178 }
6179 }
6180 } finally {
6181 timeCounter.stop();
6182 }
6183 }
6184
6185 /**
6186 * Compute a dependency map of libraries reachable from the given library. A d ependency map is a
6187 * table that maps individual libraries to a list of the libraries that either import or export
6188 * those libraries.
6189 *
6190 * This map is used to compute all of the libraries involved in a cycle that i nclude the root
6191 * library. Given that we only add libraries that are reachable from the root library, when we
6192 * work backward we are guaranteed to only get libraries in the cycle.
6193 *
6194 * @param library the library currently being added to the dependency map
6195 */
6196 Map<Library, List<Library>> computeDependencyMap(Library library) {
6197 Map<Library, List<Library>> dependencyMap = new Map<Library, List<Library>>( );
6198 addToDependencyMap(library, dependencyMap, new Set<Library>());
6199 return dependencyMap;
6200 }
6201
6202 /**
6203 * Return a collection containing all of the libraries reachable from the give n library that are
6204 * contained in a cycle that includes the given library.
6205 *
6206 * @param library the library that must be included in any cycles whose member s are to be returned
6207 * @return all of the libraries referenced by the given library that have a ci rcular reference
6208 * back to the given library
6209 */
6210 Set<Library> computeLibrariesInCycles(Library library) {
6211 Map<Library, List<Library>> dependencyMap = computeDependencyMap(library);
6212 Set<Library> librariesInCycle = new Set<Library>();
6213 addLibrariesInCycle(library, librariesInCycle, dependencyMap);
6214 return librariesInCycle;
6215 }
6216
6217 /**
6218 * Recursively traverse the libraries reachable from the given library, creati ng instances of the
6219 * class [Library] to represent them, and record the references in the library objects.
6220 *
6221 * @param library the library to be processed to find libraries that have not yet been traversed
6222 * @throws AnalysisException if some portion of the library graph could not be traversed
6223 */
6224 void computeLibraryDependencies(Library library) {
6225 Source librarySource = library.librarySource;
6226 computeLibraryDependencies3(library, analysisContext.computeImportedLibrarie s(librarySource), analysisContext.computeExportedLibraries(librarySource));
6227 }
6228
6229 /**
6230 * Recursively traverse the libraries reachable from the given library, creati ng instances of the
6231 * class [Library] to represent them, and record the references in the library objects.
6232 *
6233 * @param library the library to be processed to find libraries that have not yet been traversed
6234 * @throws AnalysisException if some portion of the library graph could not be traversed
6235 */
6236 void computeLibraryDependencies2(Library library, CompilationUnit unit) {
6237 Source librarySource = library.librarySource;
6238 Set<Source> exportedSources = new Set<Source>();
6239 Set<Source> importedSources = new Set<Source>();
6240 for (Directive directive in unit.directives) {
6241 if (directive is ExportDirective) {
6242 Source exportSource = resolveSource(librarySource, directive as ExportDi rective);
6243 if (exportSource != null) {
6244 javaSetAdd(exportedSources, exportSource);
6245 }
6246 } else if (directive is ImportDirective) {
6247 Source importSource = resolveSource(librarySource, directive as ImportDi rective);
6248 if (importSource != null) {
6249 javaSetAdd(importedSources, importSource);
6250 }
6251 }
6252 }
6253 computeLibraryDependencies3(library, new List.from(importedSources), new Lis t.from(exportedSources));
6254 }
6255
6256 /**
6257 * Recursively traverse the libraries reachable from the given library, creati ng instances of the
6258 * class [Library] to represent them, and record the references in the library objects.
6259 *
6260 * @param library the library to be processed to find libraries that have not yet been traversed
6261 * @param importedSources an array containing the sources that are imported in to the given library
6262 * @param exportedSources an array containing the sources that are exported fr om the given library
6263 * @throws AnalysisException if some portion of the library graph could not be traversed
6264 */
6265 void computeLibraryDependencies3(Library library, List<Source> importedSources , List<Source> exportedSources) {
6266 List<Library> importedLibraries = new List<Library>();
6267 bool explicitlyImportsCore = false;
6268 for (Source importedSource in importedSources) {
6269 if (importedSource == _coreLibrarySource) {
6270 explicitlyImportsCore = true;
6271 }
6272 Library importedLibrary = _libraryMap[importedSource];
6273 if (importedLibrary == null) {
6274 importedLibrary = createLibraryOrNull(importedSource);
6275 if (importedLibrary != null) {
6276 computeLibraryDependencies(importedLibrary);
6277 }
6278 }
6279 if (importedLibrary != null) {
6280 importedLibraries.add(importedLibrary);
6281 }
6282 }
6283 library.importedLibraries = new List.from(importedLibraries);
6284 List<Library> exportedLibraries = new List<Library>();
6285 for (Source exportedSource in exportedSources) {
6286 Library exportedLibrary = _libraryMap[exportedSource];
6287 if (exportedLibrary == null) {
6288 exportedLibrary = createLibraryOrNull(exportedSource);
6289 if (exportedLibrary != null) {
6290 computeLibraryDependencies(exportedLibrary);
6291 }
6292 }
6293 if (exportedLibrary != null) {
6294 exportedLibraries.add(exportedLibrary);
6295 }
6296 }
6297 library.exportedLibraries = new List.from(exportedLibraries);
6298 library.explicitlyImportsCore = explicitlyImportsCore;
6299 if (!explicitlyImportsCore && _coreLibrarySource != library.librarySource) {
6300 Library importedLibrary = _libraryMap[_coreLibrarySource];
6301 if (importedLibrary == null) {
6302 importedLibrary = createLibraryOrNull(_coreLibrarySource);
6303 if (importedLibrary != null) {
6304 computeLibraryDependencies(importedLibrary);
6305 }
6306 }
6307 }
6308 }
6309
6310 /**
6311 * Create an object to represent the information about the library defined by the compilation unit
6312 * with the given source.
6313 *
6314 * @param librarySource the source of the library's defining compilation unit
6315 * @return the library object that was created
6316 * @throws AnalysisException if the library source is not valid
6317 */
6318 Library createLibrary(Source librarySource) {
6319 Library library = new Library(analysisContext, errorListener, librarySource) ;
6320 library.definingCompilationUnit;
6321 _libraryMap[librarySource] = library;
6322 return library;
6323 }
6324
6325 /**
6326 * Create an object to represent the information about the library defined by the compilation unit
6327 * with the given source.
6328 *
6329 * @param librarySource the source of the library's defining compilation unit
6330 * @param modificationStamp the modification time of the source from which the compilation unit
6331 * was created
6332 * @param unit the compilation unit that defines the library
6333 * @return the library object that was created
6334 * @throws AnalysisException if the library source is not valid
6335 */
6336 Library createLibrary2(Source librarySource, int modificationStamp, Compilatio nUnit unit) {
6337 Library library = new Library(analysisContext, errorListener, librarySource) ;
6338 library.setDefiningCompilationUnit(modificationStamp, unit);
6339 _libraryMap[librarySource] = library;
6340 return library;
6341 }
6342
6343 /**
6344 * Create an object to represent the information about the library defined by the compilation unit
6345 * with the given source. Return the library object that was created, or `null ` if the
6346 * source is not valid.
6347 *
6348 * @param librarySource the source of the library's defining compilation unit
6349 * @return the library object that was created
6350 */
6351 Library createLibraryOrNull(Source librarySource) {
6352 if (!librarySource.exists()) {
6353 return null;
6354 }
6355 Library library = new Library(analysisContext, errorListener, librarySource) ;
6356 _libraryMap[librarySource] = library;
6357 return library;
6358 }
6359
6360 /**
6361 * Return `true` if and only if the passed [CompilationUnit] has a part-of dir ective.
6362 *
6363 * @param node the [CompilationUnit] to test
6364 * @return `true` if and only if the passed [CompilationUnit] has a part-of di rective
6365 */
6366 bool doesCompilationUnitHavePartOfDirective(CompilationUnit node) {
6367 NodeList<Directive> directives = node.directives;
6368 for (Directive directive in directives) {
6369 if (directive is PartOfDirective) {
6370 return true;
6371 }
6372 }
6373 return false;
6374 }
6375
6376 /**
6377 * Return an array containing the lexical identifiers associated with the node s in the given list.
6378 *
6379 * @param names the AST nodes representing the identifiers
6380 * @return the lexical identifiers associated with the nodes in the list
6381 */
6382 List<String> getIdentifiers(NodeList<SimpleIdentifier> names) {
6383 int count = names.length;
6384 List<String> identifiers = new List<String>(count);
6385 for (int i = 0; i < count; i++) {
6386 identifiers[i] = names[i].name;
6387 }
6388 return identifiers;
6389 }
6390
6391 /**
6392 * Compute a value for all of the constants in the libraries being analyzed.
6393 */
6394 void performConstantEvaluation() {
6395 TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.st art();
6396 try {
6397 ConstantValueComputer computer = new ConstantValueComputer();
6398 for (Library library in resolvedLibraries) {
6399 for (Source source in library.compilationUnitSources) {
6400 try {
6401 CompilationUnit unit = library.getAST(source);
6402 if (unit != null) {
6403 computer.add(unit);
6404 }
6405 } on AnalysisException catch (exception) {
6406 AnalysisEngine.instance.logger.logError2("Internal Error: Could not access AST for ${source.fullName} during constant evaluation", exception);
6407 }
6408 }
6409 }
6410 computer.computeValues();
6411 } finally {
6412 timeCounter.stop();
6413 }
6414 }
6415
6416 /**
6417 * Resolve the identifiers and perform type analysis in the libraries in the c urrent cycle.
6418 *
6419 * @throws AnalysisException if any of the identifiers could not be resolved o r if any of the
6420 * libraries could not have their types analyzed
6421 */
6422 void resolveReferencesAndTypes() {
6423 for (Library library in resolvedLibraries) {
6424 resolveReferencesAndTypes2(library);
6425 }
6426 }
6427
6428 /**
6429 * Resolve the identifiers and perform type analysis in the given library.
6430 *
6431 * @param library the library to be resolved
6432 * @throws AnalysisException if any of the identifiers could not be resolved o r if the types in
6433 * the library cannot be analyzed
6434 */
6435 void resolveReferencesAndTypes2(Library library) {
6436 TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.st art();
6437 try {
6438 for (Source source in library.compilationUnitSources) {
6439 CompilationUnit ast = library.getAST(source);
6440 ast.accept(new VariableResolverVisitor(library, source, _typeProvider));
6441 ResolverVisitor visitor = new ResolverVisitor.con1(library, source, _typ eProvider);
6442 ast.accept(visitor);
6443 for (ProxyConditionalAnalysisError conditionalCode in visitor.proxyCondi tionalAnalysisErrors) {
6444 if (conditionalCode.shouldIncludeErrorCode()) {
6445 visitor.reportError(conditionalCode.analysisError);
6446 }
6447 }
6448 }
6449 } finally {
6450 timeCounter.stop();
6451 }
6452 }
6453
6454 /**
6455 * Return the result of resolving the URI of the given URI-based directive aga inst the URI of the
6456 * given library, or `null` if the URI is not valid.
6457 *
6458 * @param librarySource the source representing the library containing the dir ective
6459 * @param directive the directive which URI should be resolved
6460 * @return the result of resolving the URI against the URI of the library
6461 */
6462 Source resolveSource(Source librarySource, UriBasedDirective directive) {
6463 StringLiteral uriLiteral = directive.uri;
6464 if (uriLiteral is StringInterpolation) {
6465 return null;
6466 }
6467 String uriContent = uriLiteral.stringValue.trim();
6468 if (uriContent == null || uriContent.isEmpty) {
6469 return null;
6470 }
6471 uriContent = Uri.encodeFull(uriContent);
6472 return analysisContext.sourceFactory.resolveUri(librarySource, uriContent);
6473 }
6474 }
6475 /**
6476 * This class is used to replace uses of `HashMap<String, ExecutableElement>` wh ich are not as
6477 * performant as this class.
6478 */
6479 class MemberMap {
6480
6481 /**
6482 * The current size of this map.
6483 */
6484 int size = 0;
6485
6486 /**
6487 * The array of keys.
6488 */
6489 List<String> _keys;
6490
6491 /**
6492 * The array of ExecutableElement values.
6493 */
6494 List<ExecutableElement> _values;
6495
6496 /**
6497 * Default constructor.
6498 */
6499 MemberMap() : this.con1(10);
6500
6501 /**
6502 * This constructor takes an initial capacity of the map.
6503 *
6504 * @param initialCapacity the initial capacity
6505 */
6506 MemberMap.con1(int initialCapacity) {
6507 initArrays(initialCapacity);
6508 }
6509
6510 /**
6511 * Copy constructor.
6512 */
6513 MemberMap.con2(MemberMap memberMap) {
6514 initArrays(memberMap.size + 5);
6515 for (int i = 0; i < memberMap.size; i++) {
6516 _keys[i] = memberMap._keys[i];
6517 _values[i] = memberMap._values[i];
6518 }
6519 size = memberMap.size;
6520 }
6521
6522 /**
6523 * Given some key, return the ExecutableElement value from the map, if the key does not exist in
6524 * the map, `null` is returned.
6525 *
6526 * @param key some key to look up in the map
6527 * @return the associated ExecutableElement value from the map, if the key doe s not exist in the
6528 * map, `null` is returned
6529 */
6530 ExecutableElement get(String key) {
6531 for (int i = 0; i < size; i++) {
6532 if (_keys[i] != null && _keys[i] == key) {
6533 return _values[i];
6534 }
6535 }
6536 return null;
6537 }
6538
6539 /**
6540 * Get and return the key at the specified location. If the key/value pair has been removed from
6541 * the set, then `null` is returned.
6542 *
6543 * @param i some non-zero value less than size
6544 * @return the key at the passed index
6545 * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passe d index is less than
6546 * zero or greater than or equal to the capacity of the arrays
6547 */
6548 String getKey(int i) => _keys[i];
6549
6550 /**
6551 * Get and return the ExecutableElement at the specified location. If the key/ value pair has been
6552 * removed from the set, then then `null` is returned.
6553 *
6554 * @param i some non-zero value less than size
6555 * @return the key at the passed index
6556 * @throw ArrayIndexOutOfBoundsException this exception is thrown if the passe d index is less than
6557 * zero or greater than or equal to the capacity of the arrays
6558 */
6559 ExecutableElement getValue(int i) => _values[i];
6560
6561 /**
6562 * Given some key/value pair, store the pair in the map. If the key exists alr eady, then the new
6563 * value overrides the old value.
6564 *
6565 * @param key the key to store in the map
6566 * @param value the ExecutableElement value to store in the map
6567 */
6568 void put(String key, ExecutableElement value) {
6569 for (int i = 0; i < size; i++) {
6570 if (_keys[i] != null && _keys[i] == key) {
6571 _values[i] = value;
6572 return;
6573 }
6574 }
6575 if (size == _keys.length) {
6576 int newArrayLength = size * 2;
6577 List<String> keys_new_array = new List<String>(newArrayLength);
6578 List<ExecutableElement> values_new_array = new List<ExecutableElement>(new ArrayLength);
6579 for (int i = 0; i < size; i++) {
6580 keys_new_array[i] = _keys[i];
6581 }
6582 for (int i = 0; i < size; i++) {
6583 values_new_array[i] = _values[i];
6584 }
6585 _keys = keys_new_array;
6586 _values = values_new_array;
6587 }
6588 _keys[size] = key;
6589 _values[size] = value;
6590 size++;
6591 }
6592
6593 /**
6594 * Given some String key, this method replaces the associated key and value pa ir with `null`
6595 * . The size is not decremented with this call, instead it is expected that t he users check for
6596 * `null`.
6597 *
6598 * @param key the key of the key/value pair to remove from the map
6599 */
6600 void remove(String key) {
6601 for (int i = 0; i < size; i++) {
6602 if (_keys[i] == key) {
6603 _keys[i] = null;
6604 _values[i] = null;
6605 return;
6606 }
6607 }
6608 }
6609
6610 /**
6611 * Initializes [keys] and [values].
6612 */
6613 void initArrays(int initialCapacity) {
6614 _keys = new List<String>(initialCapacity);
6615 _values = new List<ExecutableElement>(initialCapacity);
6616 }
6617 }
6618 /**
6619 * This class is a wrapper for an [AnalysisError] which can also be queried afte r resolution
6620 * to find out if the error should actually be reported. In this case, these err ors are conditional
6621 * on the non-existence of an `@proxy` annotation.
6622 *
6623 * If we have other conditional error codes in the future, we should have this c lass implement some
6624 * ConditionalErrorCode so that after resolution, a list of ConditionalErrorCode can be visited
6625 * instead of multiple lists of *ConditionalErrorCodes.
6626 */
6627 class ProxyConditionalAnalysisError {
6628
6629 /**
6630 * The name of the proxy annotation, from the meta pub package.
6631 */
6632 static String _PROXY_ANNOTATION_NAME = "proxy";
6633
6634 /**
6635 * The name of the meta library name, from the meta pub package.
6636 */
6637 static String _META_LIBRARY_NAME = "meta";
6638
6639 /**
6640 * Return `true` if the given element represents a class that has the proxy an notation.
6641 *
6642 * @param element the class being tested
6643 * @return `true` if the given element represents a class that has the proxy a nnotation
6644 */
6645 static bool classHasProxyAnnotation(Element element) {
6646 if (element is ClassElement) {
6647 ClassElement classElement = element as ClassElement;
6648 List<ElementAnnotation> annotations = classElement.metadata;
6649 for (ElementAnnotation annotation in annotations) {
6650 Element elementAnnotation = annotation.element;
6651 if (elementAnnotation != null) {
6652 LibraryElement lib = elementAnnotation.library;
6653 if (elementAnnotation.name == _PROXY_ANNOTATION_NAME && lib != null && lib.name == _META_LIBRARY_NAME) {
6654 return true;
6655 }
6656 }
6657 }
6658 }
6659 return false;
6660 }
6661
6662 /**
6663 * The enclosing [ClassElement], this is what will determine if the error code should, or
6664 * should not, be generated on the source.
6665 */
6666 Element _enclosingElement;
6667
6668 /**
6669 * The conditional analysis error.
6670 */
6671 AnalysisError analysisError;
6672
6673 /**
6674 * Instantiate a new ProxyConditionalErrorCode with some enclosing element and the conditional
6675 * analysis error.
6676 *
6677 * @param enclosingElement the enclosing element
6678 * @param analysisError the conditional analysis error
6679 */
6680 ProxyConditionalAnalysisError(Element enclosingElement, AnalysisError analysis Error) {
6681 this._enclosingElement = enclosingElement;
6682 this.analysisError = analysisError;
6683 }
6684
6685 /**
6686 * Return `true` iff the enclosing class has the proxy annotation.
6687 *
6688 * @return `true` iff the enclosing class has the proxy annotation
6689 */
6690 bool shouldIncludeErrorCode() => !classHasProxyAnnotation(_enclosingElement);
6691 }
6692 /**
6693 * Instances of the class `ResolverVisitor` are used to resolve the nodes within a single
6694 * compilation unit.
6695 *
6696 * @coverage dart.engine.resolver
6697 */
6698 class ResolverVisitor extends ScopedVisitor {
6699
6700 /**
6701 * The manager for the inheritance mappings.
6702 */
6703 InheritanceManager _inheritanceManager;
6704
6705 /**
6706 * The object used to resolve the element associated with the current node.
6707 */
6708 ElementResolver _elementResolver;
6709
6710 /**
6711 * The object used to compute the type associated with the current node.
6712 */
6713 StaticTypeAnalyzer _typeAnalyzer;
6714
6715 /**
6716 * The class element representing the class containing the current node, or `n ull` if the
6717 * current node is not contained in a class.
6718 */
6719 ClassElement enclosingClass = null;
6720
6721 /**
6722 * The element representing the function containing the current node, or `null ` if the
6723 * current node is not contained in a function.
6724 */
6725 ExecutableElement enclosingFunction = null;
6726
6727 /**
6728 * The object keeping track of which elements have had their types overridden.
6729 */
6730 final TypeOverrideManager overrideManager = new TypeOverrideManager();
6731
6732 /**
6733 * The object keeping track of which elements have had their types promoted.
6734 */
6735 final TypePromotionManager promoteManager = new TypePromotionManager();
6736
6737 /**
6738 * Proxy conditional error codes.
6739 */
6740 final List<ProxyConditionalAnalysisError> proxyConditionalAnalysisErrors = new List<ProxyConditionalAnalysisError>();
6741
6742 /**
6743 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
6744 *
6745 * @param library the library containing the compilation unit being resolved
6746 * @param source the source representing the compilation unit being visited
6747 * @param typeProvider the object used to access the types from the core libra ry
6748 */
6749 ResolverVisitor.con1(Library library, Source source, TypeProvider typeProvider ) : super.con1(library, source, typeProvider) {
6750 this._inheritanceManager = library.inheritanceManager;
6751 this._elementResolver = new ElementResolver(this);
6752 this._typeAnalyzer = new StaticTypeAnalyzer(this);
6753 }
6754
6755 /**
6756 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
6757 *
6758 * @param definingLibrary the element for the library containing the compilati on unit being
6759 * visited
6760 * @param source the source representing the compilation unit being visited
6761 * @param typeProvider the object used to access the types from the core libra ry
6762 * @param errorListener the error listener that will be informed of any errors that are found
6763 * during resolution
6764 */
6765 ResolverVisitor.con2(LibraryElement definingLibrary, Source source, TypeProvid er typeProvider, InheritanceManager inheritanceManager, AnalysisErrorListener er rorListener) : super.con2(definingLibrary, source, typeProvider, errorListener) {
6766 this._inheritanceManager = inheritanceManager;
6767 this._elementResolver = new ElementResolver(this);
6768 this._typeAnalyzer = new StaticTypeAnalyzer(this);
6769 }
6770 Object visitAsExpression(AsExpression node) {
6771 super.visitAsExpression(node);
6772 override(node.expression, node.type.type);
6773 return null;
6774 }
6775 Object visitAssertStatement(AssertStatement node) {
6776 super.visitAssertStatement(node);
6777 propagateTrueState(node.condition);
6778 return null;
6779 }
6780 Object visitBinaryExpression(BinaryExpression node) {
6781 sc.TokenType operatorType = node.operator.type;
6782 Expression leftOperand = node.leftOperand;
6783 Expression rightOperand = node.rightOperand;
6784 if (identical(operatorType, sc.TokenType.AMPERSAND_AMPERSAND)) {
6785 safelyVisit(leftOperand);
6786 if (rightOperand != null) {
6787 try {
6788 overrideManager.enterScope();
6789 promoteManager.enterScope();
6790 propagateTrueState(leftOperand);
6791 promoteTypes(leftOperand);
6792 clearTypePromotionsIfPotentiallyMutatedIn(leftOperand);
6793 clearTypePromotionsIfPotentiallyMutatedIn(rightOperand);
6794 clearTypePromotionsIfAccessedInScopeAndProtentiallyMutated(rightOperan d);
6795 rightOperand.accept(this);
6796 } finally {
6797 overrideManager.exitScope();
6798 promoteManager.exitScope();
6799 }
6800 }
6801 } else if (identical(operatorType, sc.TokenType.BAR_BAR)) {
6802 safelyVisit(leftOperand);
6803 if (rightOperand != null) {
6804 try {
6805 overrideManager.enterScope();
6806 propagateFalseState(leftOperand);
6807 rightOperand.accept(this);
6808 } finally {
6809 overrideManager.exitScope();
6810 }
6811 }
6812 } else {
6813 safelyVisit(leftOperand);
6814 safelyVisit(rightOperand);
6815 }
6816 node.accept(_elementResolver);
6817 node.accept(_typeAnalyzer);
6818 return null;
6819 }
6820 Object visitBlockFunctionBody(BlockFunctionBody node) {
6821 try {
6822 overrideManager.enterScope();
6823 super.visitBlockFunctionBody(node);
6824 } finally {
6825 overrideManager.exitScope();
6826 }
6827 return null;
6828 }
6829 Object visitBreakStatement(BreakStatement node) {
6830 node.accept(_elementResolver);
6831 node.accept(_typeAnalyzer);
6832 return null;
6833 }
6834 Object visitClassDeclaration(ClassDeclaration node) {
6835 ClassElement outerType = enclosingClass;
6836 try {
6837 enclosingClass = node.element;
6838 _typeAnalyzer.thisType = enclosingClass == null ? null : enclosingClass.ty pe;
6839 super.visitClassDeclaration(node);
6840 } finally {
6841 _typeAnalyzer.thisType = outerType == null ? null : outerType.type;
6842 enclosingClass = outerType;
6843 }
6844 return null;
6845 }
6846 Object visitCommentReference(CommentReference node) {
6847 node.accept(_elementResolver);
6848 node.accept(_typeAnalyzer);
6849 return null;
6850 }
6851 Object visitCompilationUnit(CompilationUnit node) {
6852 try {
6853 overrideManager.enterScope();
6854 for (Directive directive in node.directives) {
6855 directive.accept(this);
6856 }
6857 List<CompilationUnitMember> classes = new List<CompilationUnitMember>();
6858 for (CompilationUnitMember declaration in node.declarations) {
6859 if (declaration is ClassDeclaration) {
6860 classes.add(declaration);
6861 } else {
6862 declaration.accept(this);
6863 }
6864 }
6865 for (CompilationUnitMember declaration in classes) {
6866 declaration.accept(this);
6867 }
6868 } finally {
6869 overrideManager.exitScope();
6870 }
6871 node.accept(_elementResolver);
6872 node.accept(_typeAnalyzer);
6873 return null;
6874 }
6875 Object visitConditionalExpression(ConditionalExpression node) {
6876 Expression condition = node.condition;
6877 safelyVisit(condition);
6878 Expression thenExpression = node.thenExpression;
6879 if (thenExpression != null) {
6880 try {
6881 overrideManager.enterScope();
6882 promoteManager.enterScope();
6883 propagateTrueState(condition);
6884 promoteTypes(condition);
6885 clearTypePromotionsIfPotentiallyMutatedIn(thenExpression);
6886 clearTypePromotionsIfAccessedInScopeAndProtentiallyMutated(thenExpressio n);
6887 thenExpression.accept(this);
6888 } finally {
6889 overrideManager.exitScope();
6890 promoteManager.exitScope();
6891 }
6892 }
6893 Expression elseExpression = node.elseExpression;
6894 if (elseExpression != null) {
6895 try {
6896 overrideManager.enterScope();
6897 propagateFalseState(condition);
6898 elseExpression.accept(this);
6899 } finally {
6900 overrideManager.exitScope();
6901 }
6902 }
6903 node.accept(_elementResolver);
6904 node.accept(_typeAnalyzer);
6905 bool thenIsAbrupt = isAbruptTermination(thenExpression);
6906 bool elseIsAbrupt = isAbruptTermination(elseExpression);
6907 if (elseIsAbrupt && !thenIsAbrupt) {
6908 propagateTrueState(condition);
6909 propagateState(thenExpression);
6910 } else if (thenIsAbrupt && !elseIsAbrupt) {
6911 propagateFalseState(condition);
6912 propagateState(elseExpression);
6913 }
6914 return null;
6915 }
6916 Object visitConstructorDeclaration(ConstructorDeclaration node) {
6917 ExecutableElement outerFunction = enclosingFunction;
6918 try {
6919 enclosingFunction = node.element;
6920 super.visitConstructorDeclaration(node);
6921 } finally {
6922 enclosingFunction = outerFunction;
6923 }
6924 return null;
6925 }
6926 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
6927 safelyVisit(node.expression);
6928 node.accept(_elementResolver);
6929 node.accept(_typeAnalyzer);
6930 return null;
6931 }
6932 Object visitConstructorName(ConstructorName node) {
6933 node.accept(_elementResolver);
6934 node.accept(_typeAnalyzer);
6935 return null;
6936 }
6937 Object visitContinueStatement(ContinueStatement node) {
6938 node.accept(_elementResolver);
6939 node.accept(_typeAnalyzer);
6940 return null;
6941 }
6942 Object visitDoStatement(DoStatement node) {
6943 try {
6944 overrideManager.enterScope();
6945 super.visitDoStatement(node);
6946 } finally {
6947 overrideManager.exitScope();
6948 }
6949 return null;
6950 }
6951 Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
6952 try {
6953 overrideManager.enterScope();
6954 super.visitExpressionFunctionBody(node);
6955 } finally {
6956 overrideManager.exitScope();
6957 }
6958 return null;
6959 }
6960 Object visitFieldDeclaration(FieldDeclaration node) {
6961 try {
6962 overrideManager.enterScope();
6963 super.visitFieldDeclaration(node);
6964 } finally {
6965 Map<Element, Type2> overrides = overrideManager.captureOverrides(node.fiel ds);
6966 overrideManager.exitScope();
6967 overrideManager.applyOverrides(overrides);
6968 }
6969 return null;
6970 }
6971 Object visitForEachStatement(ForEachStatement node) {
6972 try {
6973 overrideManager.enterScope();
6974 super.visitForEachStatement(node);
6975 } finally {
6976 overrideManager.exitScope();
6977 }
6978 return null;
6979 }
6980 Object visitForStatement(ForStatement node) {
6981 try {
6982 overrideManager.enterScope();
6983 super.visitForStatement(node);
6984 } finally {
6985 overrideManager.exitScope();
6986 }
6987 return null;
6988 }
6989 Object visitFunctionDeclaration(FunctionDeclaration node) {
6990 ExecutableElement outerFunction = enclosingFunction;
6991 try {
6992 SimpleIdentifier functionName = node.name;
6993 enclosingFunction = functionName.staticElement as ExecutableElement;
6994 super.visitFunctionDeclaration(node);
6995 } finally {
6996 enclosingFunction = outerFunction;
6997 }
6998 return null;
6999 }
7000 Object visitFunctionExpression(FunctionExpression node) {
7001 ExecutableElement outerFunction = enclosingFunction;
7002 try {
7003 enclosingFunction = node.element;
7004 overrideManager.enterScope();
7005 super.visitFunctionExpression(node);
7006 } finally {
7007 overrideManager.exitScope();
7008 enclosingFunction = outerFunction;
7009 }
7010 return null;
7011 }
7012 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
7013 safelyVisit(node.function);
7014 node.accept(_elementResolver);
7015 inferFunctionExpressionsParametersTypes(node.argumentList);
7016 safelyVisit(node.argumentList);
7017 node.accept(_typeAnalyzer);
7018 return null;
7019 }
7020 Object visitHideCombinator(HideCombinator node) => null;
7021 Object visitIfStatement(IfStatement node) {
7022 Expression condition = node.condition;
7023 safelyVisit(condition);
7024 Map<Element, Type2> thenOverrides = null;
7025 Statement thenStatement = node.thenStatement;
7026 if (thenStatement != null) {
7027 try {
7028 overrideManager.enterScope();
7029 promoteManager.enterScope();
7030 propagateTrueState(condition);
7031 promoteTypes(condition);
7032 clearTypePromotionsIfPotentiallyMutatedIn(thenStatement);
7033 clearTypePromotionsIfAccessedInScopeAndProtentiallyMutated(thenStatement );
7034 visitStatementInScope(thenStatement);
7035 } finally {
7036 thenOverrides = overrideManager.captureLocalOverrides();
7037 overrideManager.exitScope();
7038 promoteManager.exitScope();
7039 }
7040 }
7041 Map<Element, Type2> elseOverrides = null;
7042 Statement elseStatement = node.elseStatement;
7043 if (elseStatement != null) {
7044 try {
7045 overrideManager.enterScope();
7046 propagateFalseState(condition);
7047 visitStatementInScope(elseStatement);
7048 } finally {
7049 elseOverrides = overrideManager.captureLocalOverrides();
7050 overrideManager.exitScope();
7051 }
7052 }
7053 node.accept(_elementResolver);
7054 node.accept(_typeAnalyzer);
7055 bool thenIsAbrupt = isAbruptTermination2(thenStatement);
7056 bool elseIsAbrupt = isAbruptTermination2(elseStatement);
7057 if (elseIsAbrupt && !thenIsAbrupt) {
7058 propagateTrueState(condition);
7059 if (thenOverrides != null) {
7060 overrideManager.applyOverrides(thenOverrides);
7061 }
7062 } else if (thenIsAbrupt && !elseIsAbrupt) {
7063 propagateFalseState(condition);
7064 if (elseOverrides != null) {
7065 overrideManager.applyOverrides(elseOverrides);
7066 }
7067 }
7068 return null;
7069 }
7070 Object visitLabel(Label node) => null;
7071 Object visitLibraryIdentifier(LibraryIdentifier node) => null;
7072 Object visitMethodDeclaration(MethodDeclaration node) {
7073 ExecutableElement outerFunction = enclosingFunction;
7074 try {
7075 enclosingFunction = node.element;
7076 super.visitMethodDeclaration(node);
7077 } finally {
7078 enclosingFunction = outerFunction;
7079 }
7080 return null;
7081 }
7082 Object visitMethodInvocation(MethodInvocation node) {
7083 safelyVisit(node.target);
7084 node.accept(_elementResolver);
7085 inferFunctionExpressionsParametersTypes(node.argumentList);
7086 safelyVisit(node.argumentList);
7087 node.accept(_typeAnalyzer);
7088 return null;
7089 }
7090 Object visitNode(ASTNode node) {
7091 node.visitChildren(this);
7092 node.accept(_elementResolver);
7093 node.accept(_typeAnalyzer);
7094 return null;
7095 }
7096 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
7097 safelyVisit(node.prefix);
7098 node.accept(_elementResolver);
7099 node.accept(_typeAnalyzer);
7100 return null;
7101 }
7102 Object visitPropertyAccess(PropertyAccess node) {
7103 safelyVisit(node.target);
7104 node.accept(_elementResolver);
7105 node.accept(_typeAnalyzer);
7106 return null;
7107 }
7108 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
7109 safelyVisit(node.argumentList);
7110 node.accept(_elementResolver);
7111 node.accept(_typeAnalyzer);
7112 return null;
7113 }
7114 Object visitShowCombinator(ShowCombinator node) => null;
7115 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
7116 safelyVisit(node.argumentList);
7117 node.accept(_elementResolver);
7118 node.accept(_typeAnalyzer);
7119 return null;
7120 }
7121 Object visitSwitchCase(SwitchCase node) {
7122 try {
7123 overrideManager.enterScope();
7124 super.visitSwitchCase(node);
7125 } finally {
7126 overrideManager.exitScope();
7127 }
7128 return null;
7129 }
7130 Object visitSwitchDefault(SwitchDefault node) {
7131 try {
7132 overrideManager.enterScope();
7133 super.visitSwitchDefault(node);
7134 } finally {
7135 overrideManager.exitScope();
7136 }
7137 return null;
7138 }
7139 Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
7140 try {
7141 overrideManager.enterScope();
7142 super.visitTopLevelVariableDeclaration(node);
7143 } finally {
7144 Map<Element, Type2> overrides = overrideManager.captureOverrides(node.vari ables);
7145 overrideManager.exitScope();
7146 overrideManager.applyOverrides(overrides);
7147 }
7148 return null;
7149 }
7150 Object visitTypeName(TypeName node) => null;
7151 Object visitWhileStatement(WhileStatement node) {
7152 Expression condition = node.condition;
7153 safelyVisit(condition);
7154 Statement body = node.body;
7155 if (body != null) {
7156 try {
7157 overrideManager.enterScope();
7158 propagateTrueState(condition);
7159 visitStatementInScope(body);
7160 } finally {
7161 overrideManager.exitScope();
7162 }
7163 }
7164 node.accept(_elementResolver);
7165 node.accept(_typeAnalyzer);
7166 return null;
7167 }
7168
7169 /**
7170 * Return the propagated element associated with the given expression whose ty pe can be
7171 * overridden, or `null` if there is no element whose type can be overridden.
7172 *
7173 * @param expression the expression with which the element is associated
7174 * @return the element associated with the given expression
7175 */
7176 VariableElement getOverridablePropagatedElement(Expression expression) {
7177 Element element = null;
7178 if (expression is SimpleIdentifier) {
7179 element = ((expression as SimpleIdentifier)).propagatedElement;
7180 } else if (expression is PrefixedIdentifier) {
7181 element = ((expression as PrefixedIdentifier)).propagatedElement;
7182 } else if (expression is PropertyAccess) {
7183 element = ((expression as PropertyAccess)).propertyName.propagatedElement;
7184 }
7185 if (element is VariableElement) {
7186 return element as VariableElement;
7187 }
7188 return null;
7189 }
7190
7191 /**
7192 * Return the static element associated with the given expression whose type c an be overridden, or
7193 * `null` if there is no element whose type can be overridden.
7194 *
7195 * @param expression the expression with which the element is associated
7196 * @return the element associated with the given expression
7197 */
7198 VariableElement getOverridableStaticElement(Expression expression) {
7199 Element element = null;
7200 if (expression is SimpleIdentifier) {
7201 element = ((expression as SimpleIdentifier)).staticElement;
7202 } else if (expression is PrefixedIdentifier) {
7203 element = ((expression as PrefixedIdentifier)).staticElement;
7204 } else if (expression is PropertyAccess) {
7205 element = ((expression as PropertyAccess)).propertyName.staticElement;
7206 }
7207 if (element is VariableElement) {
7208 return element as VariableElement;
7209 }
7210 return null;
7211 }
7212
7213 /**
7214 * Return the static element associated with the given expression whose type c an be promoted, or
7215 * `null` if there is no element whose type can be promoted.
7216 *
7217 * @param expression the expression with which the element is associated
7218 * @return the element associated with the given expression
7219 */
7220 VariableElement getPromotionStaticElement(Expression expression) {
7221 if (expression is! SimpleIdentifier) {
7222 return null;
7223 }
7224 SimpleIdentifier identifier = expression as SimpleIdentifier;
7225 Element element = identifier.staticElement;
7226 if (element is! VariableElement) {
7227 return null;
7228 }
7229 ElementKind kind = element.kind;
7230 if (identical(kind, ElementKind.LOCAL_VARIABLE)) {
7231 return element as VariableElement;
7232 }
7233 if (identical(kind, ElementKind.PARAMETER)) {
7234 return element as VariableElement;
7235 }
7236 return null;
7237 }
7238
7239 /**
7240 * If it is appropriate to do so, override the current type of the static and propagated elements
7241 * associated with the given expression with the given type. Generally speakin g, it is appropriate
7242 * if the given type is more specific than the current type.
7243 *
7244 * @param expression the expression used to access the static and propagated e lements whose types
7245 * might be overridden
7246 * @param potentialType the potential type of the elements
7247 */
7248 void override(Expression expression, Type2 potentialType) {
7249 VariableElement element = getOverridableStaticElement(expression);
7250 if (element != null) {
7251 override2(element, potentialType);
7252 }
7253 element = getOverridablePropagatedElement(expression);
7254 if (element != null) {
7255 override2(element, potentialType);
7256 }
7257 }
7258
7259 /**
7260 * If it is appropriate to do so, override the current type of the given eleme nt with the given
7261 * type. Generally speaking, it is appropriate if the given type is more speci fic than the current
7262 * type.
7263 *
7264 * @param element the element whose type might be overridden
7265 * @param potentialType the potential type of the element
7266 */
7267 void override2(VariableElement element, Type2 potentialType) {
7268 if (potentialType == null || potentialType.isBottom) {
7269 return;
7270 }
7271 if (element is PropertyInducingElement) {
7272 PropertyInducingElement variable = element as PropertyInducingElement;
7273 if (!variable.isConst && !variable.isFinal) {
7274 return;
7275 }
7276 }
7277 Type2 currentType = getBestType(element);
7278 if (currentType == null || !currentType.isMoreSpecificThan(potentialType)) {
7279 overrideManager.setType(element, potentialType);
7280 }
7281 }
7282
7283 /**
7284 * If it is appropriate to do so, promotes the current type of the static elem ent associated with
7285 * the given expression with the given type. Generally speaking, it is appropr iate if the given
7286 * type is more specific than the current type.
7287 *
7288 * @param expression the expression used to access the static element whose ty pes might be
7289 * promoted
7290 * @param potentialType the potential type of the elements
7291 */
7292 void promote(Expression expression, Type2 potentialType) {
7293 VariableElement element = getPromotionStaticElement(expression);
7294 if (element != null) {
7295 Type2 type = expression.staticType;
7296 if (type == null || type.isDynamic) {
7297 return;
7298 }
7299 if (potentialType == null || potentialType.isDynamic) {
7300 return;
7301 }
7302 if (!potentialType.isMoreSpecificThan(type)) {
7303 return;
7304 }
7305 promoteManager.setType(element, potentialType);
7306 }
7307 }
7308
7309 /**
7310 * Report a conditional analysis error with the given error code and arguments .
7311 *
7312 * @param enclosingElement the enclosing element
7313 * @param errorCode the error code of the error to be reported
7314 * @param node the node specifying the location of the error
7315 * @param arguments the arguments to the error, used to compose the error mess age
7316 */
7317 void reportErrorProxyConditionalAnalysisError(Element enclosingElement, ErrorC ode errorCode, ASTNode node, List<Object> arguments) {
7318 proxyConditionalAnalysisErrors.add(new ProxyConditionalAnalysisError(enclosi ngElement, new AnalysisError.con2(source, node.offset, node.length, errorCode, a rguments)));
7319 }
7320
7321 /**
7322 * Report a conditional analysis error with the given error code and arguments .
7323 *
7324 * @param enclosingElement the enclosing element
7325 * @param errorCode the error code of the error to be reported
7326 * @param offset the offset of the location of the error
7327 * @param length the length of the location of the error
7328 * @param arguments the arguments to the error, used to compose the error mess age
7329 */
7330 void reportErrorProxyConditionalAnalysisError2(Element enclosingElement, Error Code errorCode, int offset, int length, List<Object> arguments) {
7331 proxyConditionalAnalysisErrors.add(new ProxyConditionalAnalysisError(enclosi ngElement, new AnalysisError.con2(source, offset, length, errorCode, arguments)) );
7332 }
7333
7334 /**
7335 * Report a conditional analysis error with the given error code and arguments .
7336 *
7337 * @param enclosingElement the enclosing element
7338 * @param errorCode the error code of the error to be reported
7339 * @param token the token specifying the location of the error
7340 * @param arguments the arguments to the error, used to compose the error mess age
7341 */
7342 void reportErrorProxyConditionalAnalysisError3(Element enclosingElement, Error Code errorCode, sc.Token token, List<Object> arguments) {
7343 proxyConditionalAnalysisErrors.add(new ProxyConditionalAnalysisError(enclosi ngElement, new AnalysisError.con2(source, token.offset, token.length, errorCode, arguments)));
7344 }
7345 void visitForEachStatementInScope(ForEachStatement node) {
7346 Expression iterator = node.iterator;
7347 safelyVisit(iterator);
7348 DeclaredIdentifier loopVariable = node.loopVariable;
7349 SimpleIdentifier identifier = node.identifier;
7350 safelyVisit(loopVariable);
7351 safelyVisit(identifier);
7352 Statement body = node.body;
7353 if (body != null) {
7354 try {
7355 overrideManager.enterScope();
7356 if (loopVariable != null && iterator != null) {
7357 LocalVariableElement loopElement = loopVariable.element;
7358 if (loopElement != null) {
7359 Type2 iteratorElementType = getIteratorElementType(iterator);
7360 override2(loopElement, iteratorElementType);
7361 recordPropagatedType(loopVariable.identifier, iteratorElementType);
7362 }
7363 } else if (identifier != null && iterator != null) {
7364 Element identifierElement = identifier.staticElement;
7365 if (identifierElement is VariableElement) {
7366 Type2 iteratorElementType = getIteratorElementType(iterator);
7367 override2(identifierElement as VariableElement, iteratorElementType) ;
7368 recordPropagatedType(identifier, iteratorElementType);
7369 }
7370 }
7371 visitStatementInScope(body);
7372 } finally {
7373 overrideManager.exitScope();
7374 }
7375 }
7376 node.accept(_elementResolver);
7377 node.accept(_typeAnalyzer);
7378 }
7379 void visitForStatementInScope(ForStatement node) {
7380 safelyVisit(node.variables);
7381 safelyVisit(node.initialization);
7382 safelyVisit(node.condition);
7383 overrideManager.enterScope();
7384 try {
7385 propagateTrueState(node.condition);
7386 visitStatementInScope(node.body);
7387 node.updaters.accept(this);
7388 } finally {
7389 overrideManager.exitScope();
7390 }
7391 }
7392
7393 /**
7394 * Checks each promoted variable in the current scope for compliance with the following
7395 * specification statement:
7396 *
7397 * If the variable <i>v</i> is accessed by a closure in <i>s<sub>1</sub></i> t hen the variable
7398 * <i>v</i> is not potentially mutated anywhere in the scope of <i>v</i>.
7399 */
7400 void clearTypePromotionsIfAccessedInScopeAndProtentiallyMutated(ASTNode target ) {
7401 for (Element element in promoteManager.promotedElements) {
7402 if (((element as VariableElementImpl)).isPotentiallyMutated) {
7403 if (isVariableAccessedInClosure(element, target)) {
7404 promoteManager.setType(element, null);
7405 }
7406 }
7407 }
7408 }
7409
7410 /**
7411 * Checks each promoted variable in the current scope for compliance with the following
7412 * specification statement:
7413 *
7414 * <i>v</i> is not potentially mutated in <i>s<sub>1</sub></i> or within a clo sure.
7415 */
7416 void clearTypePromotionsIfPotentiallyMutatedIn(ASTNode target) {
7417 for (Element element in promoteManager.promotedElements) {
7418 if (isVariablePotentiallyMutatedIn(element, target)) {
7419 promoteManager.setType(element, null);
7420 }
7421 }
7422 }
7423
7424 /**
7425 * Return the best type information available for the given element. If the ty pe of the element
7426 * has been overridden, then return the overriding type. Otherwise, return the static type.
7427 *
7428 * @param element the element for which type information is to be returned
7429 * @return the best type information available for the given element
7430 */
7431 Type2 getBestType(Element element) {
7432 Type2 bestType = overrideManager.getType(element);
7433 if (bestType == null) {
7434 if (element is LocalVariableElement) {
7435 bestType = ((element as LocalVariableElement)).type;
7436 } else if (element is ParameterElement) {
7437 bestType = ((element as ParameterElement)).type;
7438 }
7439 }
7440 return bestType;
7441 }
7442
7443 /**
7444 * The given expression is the expression used to compute the iterator for a f or-each statement.
7445 * Attempt to compute the type of objects that will be assigned to the loop va riable and return
7446 * that type. Return `null` if the type could not be determined.
7447 *
7448 * @param iterator the iterator for a for-each statement
7449 * @return the type of objects that will be assigned to the loop variable
7450 */
7451 Type2 getIteratorElementType(Expression iteratorExpression) {
7452 Type2 expressionType = iteratorExpression.staticType;
7453 if (expressionType is InterfaceType) {
7454 InterfaceType interfaceType = expressionType as InterfaceType;
7455 FunctionType iteratorFunction = _inheritanceManager.lookupMemberType(inter faceType, "iterator");
7456 if (iteratorFunction == null) {
7457 return null;
7458 }
7459 Type2 iteratorType = iteratorFunction.returnType;
7460 if (iteratorType is InterfaceType) {
7461 InterfaceType iteratorInterfaceType = iteratorType as InterfaceType;
7462 FunctionType currentFunction = _inheritanceManager.lookupMemberType(iter atorInterfaceType, "current");
7463 if (currentFunction == null) {
7464 return null;
7465 }
7466 return currentFunction.returnType;
7467 }
7468 }
7469 return null;
7470 }
7471
7472 /**
7473 * If given "mayBeClosure" is [FunctionExpression] without explicit parameters types and its
7474 * required type is [FunctionType], then infer parameters types from [Function Type].
7475 */
7476 void inferFunctionExpressionParametersTypes(Expression mayBeClosure, Type2 may ByFunctionType) {
7477 if (mayBeClosure is! FunctionExpression) {
7478 return;
7479 }
7480 FunctionExpression closure = mayBeClosure as FunctionExpression;
7481 if (mayByFunctionType is! FunctionType) {
7482 return;
7483 }
7484 FunctionType expectedClosureType = mayByFunctionType as FunctionType;
7485 closure.propagatedType = expectedClosureType;
7486 NodeList<FormalParameter> parameters = closure.parameters.parameters;
7487 List<ParameterElement> expectedParameters = expectedClosureType.parameters;
7488 for (int i = 0; i < parameters.length && i < expectedParameters.length; i++) {
7489 FormalParameter parameter = parameters[i];
7490 ParameterElement element = parameter.element;
7491 Type2 currentType = getBestType(element);
7492 Type2 expectedType = expectedParameters[i].type;
7493 if (currentType == null || expectedType.isMoreSpecificThan(currentType)) {
7494 overrideManager.setType(element, expectedType);
7495 }
7496 }
7497 }
7498
7499 /**
7500 * Try to infer types of parameters of the [FunctionExpression] arguments.
7501 */
7502 void inferFunctionExpressionsParametersTypes(ArgumentList argumentList) {
7503 for (Expression argument in argumentList.arguments) {
7504 ParameterElement parameter = argument.propagatedParameterElement;
7505 if (parameter == null) {
7506 parameter = argument.staticParameterElement;
7507 }
7508 if (parameter != null) {
7509 inferFunctionExpressionParametersTypes(argument, parameter.type);
7510 }
7511 }
7512 }
7513
7514 /**
7515 * Return `true` if the given expression terminates abruptly (that is, if any expression
7516 * following the given expression will not be reached).
7517 *
7518 * @param expression the expression being tested
7519 * @return `true` if the given expression terminates abruptly
7520 */
7521 bool isAbruptTermination(Expression expression) {
7522 while (expression is ParenthesizedExpression) {
7523 expression = ((expression as ParenthesizedExpression)).expression;
7524 }
7525 return expression is ThrowExpression || expression is RethrowExpression;
7526 }
7527
7528 /**
7529 * Return `true` if the given statement terminates abruptly (that is, if any s tatement
7530 * following the given statement will not be reached).
7531 *
7532 * @param statement the statement being tested
7533 * @return `true` if the given statement terminates abruptly
7534 */
7535 bool isAbruptTermination2(Statement statement) {
7536 if (statement is ReturnStatement || statement is BreakStatement || statement is ContinueStatement) {
7537 return true;
7538 } else if (statement is ExpressionStatement) {
7539 return isAbruptTermination(((statement as ExpressionStatement)).expression );
7540 } else if (statement is Block) {
7541 NodeList<Statement> statements = ((statement as Block)).statements;
7542 int size = statements.length;
7543 if (size == 0) {
7544 return false;
7545 }
7546 return isAbruptTermination2(statements[size - 1]);
7547 }
7548 return false;
7549 }
7550
7551 /**
7552 * Return `true` if the given variable is accessed within a closure in the giv en
7553 * [ASTNode] and also mutated somewhere in variable scope. This information is only
7554 * available for local variables (including parameters).
7555 *
7556 * @param variable the variable to check
7557 * @param target the [ASTNode] to check within
7558 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode
7559 */
7560 bool isVariableAccessedInClosure(Element variable, ASTNode target) {
7561 List<bool> result = [false];
7562 target.accept(new RecursiveASTVisitor_7(result, variable));
7563 return result[0];
7564 }
7565
7566 /**
7567 * Return `true` if the given variable is potentially mutated somewhere in the given
7568 * [ASTNode]. This information is only available for local variables (includin g parameters).
7569 *
7570 * @param variable the variable to check
7571 * @param target the [ASTNode] to check within
7572 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode
7573 */
7574 bool isVariablePotentiallyMutatedIn(Element variable, ASTNode target) {
7575 List<bool> result = [false];
7576 target.accept(new RecursiveASTVisitor_8(result, variable));
7577 return result[0];
7578 }
7579
7580 /**
7581 * Promotes type information using given condition.
7582 */
7583 void promoteTypes(Expression condition) {
7584 if (condition is BinaryExpression) {
7585 BinaryExpression binary = condition as BinaryExpression;
7586 if (identical(binary.operator.type, sc.TokenType.AMPERSAND_AMPERSAND)) {
7587 Expression left = binary.leftOperand;
7588 Expression right = binary.rightOperand;
7589 promoteTypes(left);
7590 promoteTypes(right);
7591 clearTypePromotionsIfPotentiallyMutatedIn(right);
7592 }
7593 } else if (condition is IsExpression) {
7594 IsExpression is2 = condition as IsExpression;
7595 if (is2.notOperator == null) {
7596 promote(is2.expression, is2.type.type);
7597 }
7598 } else if (condition is ParenthesizedExpression) {
7599 promoteTypes(((condition as ParenthesizedExpression)).expression);
7600 }
7601 }
7602
7603 /**
7604 * Propagate any type information that results from knowing that the given con dition will have
7605 * been evaluated to 'false'.
7606 *
7607 * @param condition the condition that will have evaluated to 'false'
7608 */
7609 void propagateFalseState(Expression condition) {
7610 if (condition is BinaryExpression) {
7611 BinaryExpression binary = condition as BinaryExpression;
7612 if (identical(binary.operator.type, sc.TokenType.BAR_BAR)) {
7613 propagateFalseState(binary.leftOperand);
7614 propagateFalseState(binary.rightOperand);
7615 }
7616 } else if (condition is IsExpression) {
7617 IsExpression is2 = condition as IsExpression;
7618 if (is2.notOperator != null) {
7619 override(is2.expression, is2.type.type);
7620 }
7621 } else if (condition is PrefixExpression) {
7622 PrefixExpression prefix = condition as PrefixExpression;
7623 if (identical(prefix.operator.type, sc.TokenType.BANG)) {
7624 propagateTrueState(prefix.operand);
7625 }
7626 } else if (condition is ParenthesizedExpression) {
7627 propagateFalseState(((condition as ParenthesizedExpression)).expression);
7628 }
7629 }
7630
7631 /**
7632 * Propagate any type information that results from knowing that the given exp ression will have
7633 * been evaluated without altering the flow of execution.
7634 *
7635 * @param expression the expression that will have been evaluated
7636 */
7637 void propagateState(Expression expression) {
7638 }
7639
7640 /**
7641 * Propagate any type information that results from knowing that the given con dition will have
7642 * been evaluated to 'true'.
7643 *
7644 * @param condition the condition that will have evaluated to 'true'
7645 */
7646 void propagateTrueState(Expression condition) {
7647 if (condition is BinaryExpression) {
7648 BinaryExpression binary = condition as BinaryExpression;
7649 if (identical(binary.operator.type, sc.TokenType.AMPERSAND_AMPERSAND)) {
7650 propagateTrueState(binary.leftOperand);
7651 propagateTrueState(binary.rightOperand);
7652 }
7653 } else if (condition is IsExpression) {
7654 IsExpression is2 = condition as IsExpression;
7655 if (is2.notOperator == null) {
7656 override(is2.expression, is2.type.type);
7657 }
7658 } else if (condition is PrefixExpression) {
7659 PrefixExpression prefix = condition as PrefixExpression;
7660 if (identical(prefix.operator.type, sc.TokenType.BANG)) {
7661 propagateFalseState(prefix.operand);
7662 }
7663 } else if (condition is ParenthesizedExpression) {
7664 propagateTrueState(((condition as ParenthesizedExpression)).expression);
7665 }
7666 }
7667
7668 /**
7669 * Record that the propagated type of the given node is the given type.
7670 *
7671 * @param expression the node whose type is to be recorded
7672 * @param type the propagated type of the node
7673 */
7674 void recordPropagatedType(Expression expression, Type2 type) {
7675 if (type != null && !type.isDynamic) {
7676 expression.propagatedType = type;
7677 }
7678 }
7679 get elementResolver_J2DAccessor => _elementResolver;
7680 set elementResolver_J2DAccessor(__v) => _elementResolver = __v;
7681 get labelScope_J2DAccessor => labelScope;
7682 set labelScope_J2DAccessor(__v) => labelScope = __v;
7683 get nameScope_J2DAccessor => nameScope;
7684 set nameScope_J2DAccessor(__v) => nameScope = __v;
7685 get typeAnalyzer_J2DAccessor => _typeAnalyzer;
7686 set typeAnalyzer_J2DAccessor(__v) => _typeAnalyzer = __v;
7687 get enclosingClass_J2DAccessor => enclosingClass;
7688 set enclosingClass_J2DAccessor(__v) => enclosingClass = __v;
7689 }
7690 class RecursiveASTVisitor_7 extends RecursiveASTVisitor<Object> {
7691 List<bool> result;
7692 Element variable;
7693 RecursiveASTVisitor_7(this.result, this.variable) : super();
7694 bool _inClosure = false;
7695 Object visitFunctionExpression(FunctionExpression node) {
7696 bool inClosure = this._inClosure;
7697 try {
7698 this._inClosure = true;
7699 return super.visitFunctionExpression(node);
7700 } finally {
7701 this._inClosure = inClosure;
7702 }
7703 }
7704 Object visitSimpleIdentifier(SimpleIdentifier node) {
7705 if (result[0]) {
7706 return null;
7707 }
7708 if (_inClosure && identical(node.staticElement, variable)) {
7709 result[0] = javaBooleanOr(result[0], true);
7710 }
7711 return null;
7712 }
7713 }
7714 class RecursiveASTVisitor_8 extends RecursiveASTVisitor<Object> {
7715 List<bool> result;
7716 Element variable;
7717 RecursiveASTVisitor_8(this.result, this.variable) : super();
7718 Object visitSimpleIdentifier(SimpleIdentifier node) {
7719 if (result[0]) {
7720 return null;
7721 }
7722 if (identical(node.staticElement, variable)) {
7723 if (node.inSetterContext()) {
7724 result[0] = javaBooleanOr(result[0], true);
7725 }
7726 }
7727 return null;
7728 }
7729 }
7730 /**
7731 * The abstract class `ScopedVisitor` maintains name and label scopes as an AST structure is
7732 * being visited.
7733 *
7734 * @coverage dart.engine.resolver
7735 */
7736 abstract class ScopedVisitor extends UnifyingASTVisitor<Object> {
7737
7738 /**
7739 * The element for the library containing the compilation unit being visited.
7740 */
7741 LibraryElement definingLibrary;
7742
7743 /**
7744 * The source representing the compilation unit being visited.
7745 */
7746 Source source;
7747
7748 /**
7749 * The error listener that will be informed of any errors that are found durin g resolution.
7750 */
7751 AnalysisErrorListener _errorListener;
7752
7753 /**
7754 * The scope used to resolve identifiers.
7755 */
7756 Scope nameScope;
7757
7758 /**
7759 * The object used to access the types from the core library.
7760 */
7761 TypeProvider typeProvider;
7762
7763 /**
7764 * The scope used to resolve labels for `break` and `continue` statements, or
7765 * `null` if no labels have been defined in the current context.
7766 */
7767 LabelScope labelScope;
7768
7769 /**
7770 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
7771 *
7772 * @param library the library containing the compilation unit being resolved
7773 * @param source the source representing the compilation unit being visited
7774 * @param typeProvider the object used to access the types from the core libra ry
7775 */
7776 ScopedVisitor.con1(Library library, Source source, TypeProvider typeProvider) {
7777 this.definingLibrary = library.libraryElement;
7778 this.source = source;
7779 LibraryScope libraryScope = library.libraryScope;
7780 this._errorListener = libraryScope.errorListener;
7781 this.nameScope = libraryScope;
7782 this.typeProvider = typeProvider;
7783 }
7784
7785 /**
7786 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
7787 *
7788 * @param definingLibrary the element for the library containing the compilati on unit being
7789 * visited
7790 * @param source the source representing the compilation unit being visited
7791 * @param typeProvider the object used to access the types from the core libra ry
7792 * @param errorListener the error listener that will be informed of any errors that are found
7793 * during resolution
7794 */
7795 ScopedVisitor.con2(LibraryElement definingLibrary, Source source, TypeProvider typeProvider, AnalysisErrorListener errorListener) {
7796 this.definingLibrary = definingLibrary;
7797 this.source = source;
7798 this._errorListener = errorListener;
7799 this.nameScope = new LibraryScope(definingLibrary, errorListener);
7800 this.typeProvider = typeProvider;
7801 }
7802
7803 /**
7804 * Report an error with the given analysis error.
7805 *
7806 * @param errorCode analysis error
7807 */
7808 void reportError(AnalysisError analysisError) {
7809 _errorListener.onError(analysisError);
7810 }
7811 Object visitBlock(Block node) {
7812 Scope outerScope = nameScope;
7813 try {
7814 EnclosedScope enclosedScope = new EnclosedScope(nameScope);
7815 hideNamesDefinedInBlock(enclosedScope, node);
7816 nameScope = enclosedScope;
7817 super.visitBlock(node);
7818 } finally {
7819 nameScope = outerScope;
7820 }
7821 return null;
7822 }
7823 Object visitCatchClause(CatchClause node) {
7824 SimpleIdentifier exception = node.exceptionParameter;
7825 if (exception != null) {
7826 Scope outerScope = nameScope;
7827 try {
7828 nameScope = new EnclosedScope(nameScope);
7829 nameScope.define(exception.staticElement);
7830 SimpleIdentifier stackTrace = node.stackTraceParameter;
7831 if (stackTrace != null) {
7832 nameScope.define(stackTrace.staticElement);
7833 }
7834 super.visitCatchClause(node);
7835 } finally {
7836 nameScope = outerScope;
7837 }
7838 } else {
7839 super.visitCatchClause(node);
7840 }
7841 return null;
7842 }
7843 Object visitClassDeclaration(ClassDeclaration node) {
7844 Scope outerScope = nameScope;
7845 try {
7846 nameScope = new ClassScope(nameScope, node.element);
7847 super.visitClassDeclaration(node);
7848 } finally {
7849 nameScope = outerScope;
7850 }
7851 return null;
7852 }
7853 Object visitClassTypeAlias(ClassTypeAlias node) {
7854 Scope outerScope = nameScope;
7855 try {
7856 nameScope = new ClassScope(nameScope, node.element);
7857 super.visitClassTypeAlias(node);
7858 } finally {
7859 nameScope = outerScope;
7860 }
7861 return null;
7862 }
7863 Object visitConstructorDeclaration(ConstructorDeclaration node) {
7864 Scope outerScope = nameScope;
7865 try {
7866 nameScope = new FunctionScope(nameScope, node.element);
7867 super.visitConstructorDeclaration(node);
7868 } finally {
7869 nameScope = outerScope;
7870 }
7871 return null;
7872 }
7873 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
7874 VariableElement element = node.element;
7875 if (element != null) {
7876 nameScope.define(element);
7877 }
7878 super.visitDeclaredIdentifier(node);
7879 return null;
7880 }
7881 Object visitDoStatement(DoStatement node) {
7882 LabelScope outerLabelScope = labelScope;
7883 try {
7884 labelScope = new LabelScope.con1(labelScope, false, false);
7885 visitStatementInScope(node.body);
7886 safelyVisit(node.condition);
7887 } finally {
7888 labelScope = outerLabelScope;
7889 }
7890 return null;
7891 }
7892 Object visitForEachStatement(ForEachStatement node) {
7893 Scope outerNameScope = nameScope;
7894 LabelScope outerLabelScope = labelScope;
7895 try {
7896 nameScope = new EnclosedScope(nameScope);
7897 labelScope = new LabelScope.con1(outerLabelScope, false, false);
7898 visitForEachStatementInScope(node);
7899 } finally {
7900 labelScope = outerLabelScope;
7901 nameScope = outerNameScope;
7902 }
7903 return null;
7904 }
7905 Object visitFormalParameterList(FormalParameterList node) {
7906 super.visitFormalParameterList(node);
7907 if (nameScope is FunctionScope) {
7908 ((nameScope as FunctionScope)).defineParameters();
7909 }
7910 if (nameScope is FunctionTypeScope) {
7911 ((nameScope as FunctionTypeScope)).defineParameters();
7912 }
7913 return null;
7914 }
7915 Object visitForStatement(ForStatement node) {
7916 Scope outerNameScope = nameScope;
7917 LabelScope outerLabelScope = labelScope;
7918 try {
7919 nameScope = new EnclosedScope(nameScope);
7920 labelScope = new LabelScope.con1(outerLabelScope, false, false);
7921 visitForStatementInScope(node);
7922 } finally {
7923 labelScope = outerLabelScope;
7924 nameScope = outerNameScope;
7925 }
7926 return null;
7927 }
7928 Object visitFunctionDeclaration(FunctionDeclaration node) {
7929 ExecutableElement function = node.element;
7930 Scope outerScope = nameScope;
7931 try {
7932 nameScope = new FunctionScope(nameScope, function);
7933 super.visitFunctionDeclaration(node);
7934 } finally {
7935 nameScope = outerScope;
7936 }
7937 if (function.enclosingElement is! CompilationUnitElement) {
7938 nameScope.define(function);
7939 }
7940 return null;
7941 }
7942 Object visitFunctionExpression(FunctionExpression node) {
7943 if (node.parent is FunctionDeclaration) {
7944 super.visitFunctionExpression(node);
7945 } else {
7946 Scope outerScope = nameScope;
7947 try {
7948 ExecutableElement functionElement = node.element;
7949 if (functionElement == null) {
7950 } else {
7951 nameScope = new FunctionScope(nameScope, functionElement);
7952 }
7953 super.visitFunctionExpression(node);
7954 } finally {
7955 nameScope = outerScope;
7956 }
7957 }
7958 return null;
7959 }
7960 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
7961 Scope outerScope = nameScope;
7962 try {
7963 nameScope = new FunctionTypeScope(nameScope, node.element);
7964 super.visitFunctionTypeAlias(node);
7965 } finally {
7966 nameScope = outerScope;
7967 }
7968 return null;
7969 }
7970 Object visitIfStatement(IfStatement node) {
7971 safelyVisit(node.condition);
7972 visitStatementInScope(node.thenStatement);
7973 visitStatementInScope(node.elseStatement);
7974 return null;
7975 }
7976 Object visitLabeledStatement(LabeledStatement node) {
7977 LabelScope outerScope = addScopesFor(node.labels);
7978 try {
7979 super.visitLabeledStatement(node);
7980 } finally {
7981 labelScope = outerScope;
7982 }
7983 return null;
7984 }
7985 Object visitMethodDeclaration(MethodDeclaration node) {
7986 Scope outerScope = nameScope;
7987 try {
7988 nameScope = new FunctionScope(nameScope, node.element);
7989 super.visitMethodDeclaration(node);
7990 } finally {
7991 nameScope = outerScope;
7992 }
7993 return null;
7994 }
7995 Object visitSwitchCase(SwitchCase node) {
7996 node.expression.accept(this);
7997 Scope outerNameScope = nameScope;
7998 try {
7999 nameScope = new EnclosedScope(nameScope);
8000 node.statements.accept(this);
8001 } finally {
8002 nameScope = outerNameScope;
8003 }
8004 return null;
8005 }
8006 Object visitSwitchDefault(SwitchDefault node) {
8007 Scope outerNameScope = nameScope;
8008 try {
8009 nameScope = new EnclosedScope(nameScope);
8010 node.statements.accept(this);
8011 } finally {
8012 nameScope = outerNameScope;
8013 }
8014 return null;
8015 }
8016 Object visitSwitchStatement(SwitchStatement node) {
8017 LabelScope outerScope = labelScope;
8018 try {
8019 labelScope = new LabelScope.con1(outerScope, true, false);
8020 for (SwitchMember member in node.members) {
8021 for (Label label in member.labels) {
8022 SimpleIdentifier labelName = label.label;
8023 LabelElement labelElement = labelName.staticElement as LabelElement;
8024 labelScope = new LabelScope.con2(labelScope, labelName.name, labelElem ent);
8025 }
8026 }
8027 super.visitSwitchStatement(node);
8028 } finally {
8029 labelScope = outerScope;
8030 }
8031 return null;
8032 }
8033 Object visitVariableDeclaration(VariableDeclaration node) {
8034 if (node.parent.parent is! TopLevelVariableDeclaration && node.parent.parent is! FieldDeclaration) {
8035 VariableElement element = node.element;
8036 if (element != null) {
8037 nameScope.define(element);
8038 }
8039 }
8040 super.visitVariableDeclaration(node);
8041 return null;
8042 }
8043 Object visitWhileStatement(WhileStatement node) {
8044 LabelScope outerScope = labelScope;
8045 try {
8046 labelScope = new LabelScope.con1(outerScope, false, false);
8047 safelyVisit(node.condition);
8048 visitStatementInScope(node.body);
8049 } finally {
8050 labelScope = outerScope;
8051 }
8052 return null;
8053 }
8054
8055 /**
8056 * Report an error with the given error code and arguments.
8057 *
8058 * @param errorCode the error code of the error to be reported
8059 * @param node the node specifying the location of the error
8060 * @param arguments the arguments to the error, used to compose the error mess age
8061 */
8062 void reportError5(ErrorCode errorCode, ASTNode node, List<Object> arguments) {
8063 _errorListener.onError(new AnalysisError.con2(source, node.offset, node.leng th, errorCode, arguments));
8064 }
8065
8066 /**
8067 * Report an error with the given error code and arguments.
8068 *
8069 * @param errorCode the error code of the error to be reported
8070 * @param offset the offset of the location of the error
8071 * @param length the length of the location of the error
8072 * @param arguments the arguments to the error, used to compose the error mess age
8073 */
8074 void reportError6(ErrorCode errorCode, int offset, int length, List<Object> ar guments) {
8075 _errorListener.onError(new AnalysisError.con2(source, offset, length, errorC ode, arguments));
8076 }
8077
8078 /**
8079 * Report an error with the given error code and arguments.
8080 *
8081 * @param errorCode the error code of the error to be reported
8082 * @param token the token specifying the location of the error
8083 * @param arguments the arguments to the error, used to compose the error mess age
8084 */
8085 void reportError7(ErrorCode errorCode, sc.Token token, List<Object> arguments) {
8086 _errorListener.onError(new AnalysisError.con2(source, token.offset, token.le ngth, errorCode, arguments));
8087 }
8088
8089 /**
8090 * Visit the given AST node if it is not null.
8091 *
8092 * @param node the node to be visited
8093 */
8094 void safelyVisit(ASTNode node) {
8095 if (node != null) {
8096 node.accept(this);
8097 }
8098 }
8099
8100 /**
8101 * Visit the given statement after it's scope has been created. This replaces the normal call to
8102 * the inherited visit method so that ResolverVisitor can intervene when type propagation is
8103 * enabled.
8104 *
8105 * @param node the statement to be visited
8106 */
8107 void visitForEachStatementInScope(ForEachStatement node) {
8108 safelyVisit(node.identifier);
8109 safelyVisit(node.iterator);
8110 safelyVisit(node.loopVariable);
8111 visitStatementInScope(node.body);
8112 }
8113
8114 /**
8115 * Visit the given statement after it's scope has been created. This replaces the normal call to
8116 * the inherited visit method so that ResolverVisitor can intervene when type propagation is
8117 * enabled.
8118 *
8119 * @param node the statement to be visited
8120 */
8121 void visitForStatementInScope(ForStatement node) {
8122 safelyVisit(node.variables);
8123 safelyVisit(node.initialization);
8124 safelyVisit(node.condition);
8125 node.updaters.accept(this);
8126 visitStatementInScope(node.body);
8127 }
8128
8129 /**
8130 * Visit the given statement after it's scope has been created. This is used b y ResolverVisitor to
8131 * correctly visit the 'then' and 'else' statements of an 'if' statement.
8132 *
8133 * @param node the statement to be visited
8134 */
8135 void visitStatementInScope(Statement node) {
8136 if (node is Block) {
8137 visitBlock(node as Block);
8138 } else if (node != null) {
8139 Scope outerNameScope = nameScope;
8140 try {
8141 nameScope = new EnclosedScope(nameScope);
8142 node.accept(this);
8143 } finally {
8144 nameScope = outerNameScope;
8145 }
8146 }
8147 }
8148
8149 /**
8150 * Add scopes for each of the given labels.
8151 *
8152 * @param labels the labels for which new scopes are to be added
8153 * @return the scope that was in effect before the new scopes were added
8154 */
8155 LabelScope addScopesFor(NodeList<Label> labels) {
8156 LabelScope outerScope = labelScope;
8157 for (Label label in labels) {
8158 SimpleIdentifier labelNameNode = label.label;
8159 String labelName = labelNameNode.name;
8160 LabelElement labelElement = labelNameNode.staticElement as LabelElement;
8161 labelScope = new LabelScope.con2(labelScope, labelName, labelElement);
8162 }
8163 return outerScope;
8164 }
8165
8166 /**
8167 * Marks the local declarations of the given [Block] hidden in the enclosing s cope.
8168 * According to the scoping rules name is hidden if block defines it, but name is defined after
8169 * its declaration statement.
8170 */
8171 void hideNamesDefinedInBlock(EnclosedScope scope, Block block) {
8172 for (Statement statement in block.statements) {
8173 if (statement is VariableDeclarationStatement) {
8174 VariableDeclarationStatement vds = statement as VariableDeclarationState ment;
8175 for (VariableDeclaration variableDeclaration in vds.variables.variables) {
8176 Element element = variableDeclaration.element;
8177 scope.hide(element);
8178 }
8179 }
8180 if (statement is FunctionDeclarationStatement) {
8181 FunctionDeclarationStatement fds = statement as FunctionDeclarationState ment;
8182 Element element = fds.functionDeclaration.element;
8183 scope.hide(element);
8184 }
8185 }
8186 }
8187 }
8188 /**
8189 * Instances of the class `StaticTypeAnalyzer` perform two type-related tasks. F irst, they
8190 * compute the static type of every expression. Second, they look for any static type errors or
8191 * warnings that might need to be generated. The requirements for the type analy zer are:
8192 * <ol>
8193 * * Every element that refers to types should be fully populated.
8194 * * Every node representing an expression should be resolved to the Type of the expression.
8195 * </ol>
8196 *
8197 * @coverage dart.engine.resolver
8198 */
8199 class StaticTypeAnalyzer extends SimpleASTVisitor<Object> {
8200
8201 /**
8202 * Create a table mapping HTML tag names to the names of the classes (in 'dart :html') that
8203 * implement those tags.
8204 *
8205 * @return the table that was created
8206 */
8207 static Map<String, String> createHtmlTagToClassMap() {
8208 Map<String, String> map = new Map<String, String>();
8209 map["a"] = "AnchorElement";
8210 map["area"] = "AreaElement";
8211 map["br"] = "BRElement";
8212 map["base"] = "BaseElement";
8213 map["body"] = "BodyElement";
8214 map["button"] = "ButtonElement";
8215 map["canvas"] = "CanvasElement";
8216 map["content"] = "ContentElement";
8217 map["dl"] = "DListElement";
8218 map["datalist"] = "DataListElement";
8219 map["details"] = "DetailsElement";
8220 map["div"] = "DivElement";
8221 map["embed"] = "EmbedElement";
8222 map["fieldset"] = "FieldSetElement";
8223 map["form"] = "FormElement";
8224 map["hr"] = "HRElement";
8225 map["head"] = "HeadElement";
8226 map["h1"] = "HeadingElement";
8227 map["h2"] = "HeadingElement";
8228 map["h3"] = "HeadingElement";
8229 map["h4"] = "HeadingElement";
8230 map["h5"] = "HeadingElement";
8231 map["h6"] = "HeadingElement";
8232 map["html"] = "HtmlElement";
8233 map["iframe"] = "IFrameElement";
8234 map["img"] = "ImageElement";
8235 map["input"] = "InputElement";
8236 map["keygen"] = "KeygenElement";
8237 map["li"] = "LIElement";
8238 map["label"] = "LabelElement";
8239 map["legend"] = "LegendElement";
8240 map["link"] = "LinkElement";
8241 map["map"] = "MapElement";
8242 map["menu"] = "MenuElement";
8243 map["meter"] = "MeterElement";
8244 map["ol"] = "OListElement";
8245 map["object"] = "ObjectElement";
8246 map["optgroup"] = "OptGroupElement";
8247 map["output"] = "OutputElement";
8248 map["p"] = "ParagraphElement";
8249 map["param"] = "ParamElement";
8250 map["pre"] = "PreElement";
8251 map["progress"] = "ProgressElement";
8252 map["script"] = "ScriptElement";
8253 map["select"] = "SelectElement";
8254 map["source"] = "SourceElement";
8255 map["span"] = "SpanElement";
8256 map["style"] = "StyleElement";
8257 map["caption"] = "TableCaptionElement";
8258 map["td"] = "TableCellElement";
8259 map["col"] = "TableColElement";
8260 map["table"] = "TableElement";
8261 map["tr"] = "TableRowElement";
8262 map["textarea"] = "TextAreaElement";
8263 map["title"] = "TitleElement";
8264 map["track"] = "TrackElement";
8265 map["ul"] = "UListElement";
8266 map["video"] = "VideoElement";
8267 return map;
8268 }
8269
8270 /**
8271 * The resolver driving the resolution and type analysis.
8272 */
8273 ResolverVisitor _resolver;
8274
8275 /**
8276 * The object providing access to the types defined by the language.
8277 */
8278 TypeProvider _typeProvider;
8279
8280 /**
8281 * The type representing the type 'dynamic'.
8282 */
8283 Type2 _dynamicType;
8284
8285 /**
8286 * The type representing the class containing the nodes being analyzed, or `nu ll` if the
8287 * nodes are not within a class.
8288 */
8289 InterfaceType _thisType;
8290
8291 /**
8292 * The object keeping track of which elements have had their types overridden.
8293 */
8294 TypeOverrideManager _overrideManager;
8295
8296 /**
8297 * The object keeping track of which elements have had their types promoted.
8298 */
8299 TypePromotionManager _promoteManager;
8300
8301 /**
8302 * A table mapping [ExecutableElement]s to their propagated return types.
8303 */
8304 Map<ExecutableElement, Type2> _propagatedReturnTypes = new Map<ExecutableEleme nt, Type2>();
8305
8306 /**
8307 * A table mapping HTML tag names to the names of the classes (in 'dart:html') that implement
8308 * those tags.
8309 */
8310 static Map<String, String> _HTML_ELEMENT_TO_CLASS_MAP = createHtmlTagToClassMa p();
8311
8312 /**
8313 * Initialize a newly created type analyzer.
8314 *
8315 * @param resolver the resolver driving this participant
8316 */
8317 StaticTypeAnalyzer(ResolverVisitor resolver) {
8318 this._resolver = resolver;
8319 _typeProvider = resolver.typeProvider;
8320 _dynamicType = _typeProvider.dynamicType;
8321 _overrideManager = resolver.overrideManager;
8322 _promoteManager = resolver.promoteManager;
8323 }
8324
8325 /**
8326 * Set the type of the class being analyzed to the given type.
8327 *
8328 * @param thisType the type representing the class containing the nodes being analyzed
8329 */
8330 void set thisType(InterfaceType thisType) {
8331 this._thisType = thisType;
8332 }
8333
8334 /**
8335 * The Dart Language Specification, 12.5: <blockquote>The static type of a str ing literal is
8336 * `String`.</blockquote>
8337 */
8338 Object visitAdjacentStrings(AdjacentStrings node) {
8339 recordStaticType(node, _typeProvider.stringType);
8340 return null;
8341 }
8342
8343 /**
8344 * The Dart Language Specification, 12.33: <blockquote>The static type of an a rgument definition
8345 * test is `bool`.</blockquote>
8346 */
8347 Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
8348 recordStaticType(node, _typeProvider.boolType);
8349 return null;
8350 }
8351
8352 /**
8353 * The Dart Language Specification, 12.32: <blockquote>... the cast expression <i>e as T</i> ...
8354 *
8355 * It is a static warning if <i>T</i> does not denote a type available in the current lexical
8356 * scope.
8357 *
8358 * The static type of a cast expression <i>e as T</i> is <i>T</i>.</blockquote >
8359 */
8360 Object visitAsExpression(AsExpression node) {
8361 recordStaticType(node, getType2(node.type));
8362 return null;
8363 }
8364
8365 /**
8366 * The Dart Language Specification, 12.18: <blockquote>... an assignment <i>a< /i> of the form <i>v
8367 * = e</i> ...
8368 *
8369 * It is a static type warning if the static type of <i>e</i> may not be assig ned to the static
8370 * type of <i>v</i>.
8371 *
8372 * The static type of the expression <i>v = e</i> is the static type of <i>e</ i>.
8373 *
8374 * ... an assignment of the form <i>C.v = e</i> ...
8375 *
8376 * It is a static type warning if the static type of <i>e</i> may not be assig ned to the static
8377 * type of <i>C.v</i>.
8378 *
8379 * The static type of the expression <i>C.v = e</i> is the static type of <i>e </i>.
8380 *
8381 * ... an assignment of the form <i>e<sub>1</sub>.v = e<sub>2</sub></i> ...
8382 *
8383 * Let <i>T</i> be the static type of <i>e<sub>1</sub></i>. It is a static typ e warning if
8384 * <i>T</i> does not have an accessible instance setter named <i>v=</i>. It is a static type
8385 * warning if the static type of <i>e<sub>2</sub></i> may not be assigned to < i>T</i>.
8386 *
8387 * The static type of the expression <i>e<sub>1</sub>.v = e<sub>2</sub></i> is the static type of
8388 * <i>e<sub>2</sub></i>.
8389 *
8390 * ... an assignment of the form <i>e<sub>1</sub>[e<sub>2</sub>] = e<sub>3</su b></i> ...
8391 *
8392 * The static type of the expression <i>e<sub>1</sub>[e<sub>2</sub>] = e<sub>3 </sub></i> is the
8393 * static type of <i>e<sub>3</sub></i>.
8394 *
8395 * A compound assignment of the form <i>v op= e</i> is equivalent to <i>v = v op e</i>. A compound
8396 * assignment of the form <i>C.v op= e</i> is equivalent to <i>C.v = C.v op e< /i>. A compound
8397 * assignment of the form <i>e<sub>1</sub>.v op= e<sub>2</sub></i> is equivale nt to <i>((x) => x.v
8398 * = x.v op e<sub>2</sub>)(e<sub>1</sub>)</i> where <i>x</i> is a variable tha t is not used in
8399 * <i>e<sub>2</sub></i>. A compound assignment of the form <i>e<sub>1</sub>[e< sub>2</sub>] op=
8400 * e<sub>3</sub></i> is equivalent to <i>((a, i) => a[i] = a[i] op e<sub>3</su b>)(e<sub>1</sub>,
8401 * e<sub>2</sub>)</i> where <i>a</i> and <i>i</i> are a variables that are not used in
8402 * <i>e<sub>3</sub></i>.</blockquote>
8403 */
8404 Object visitAssignmentExpression(AssignmentExpression node) {
8405 sc.TokenType operator = node.operator.type;
8406 if (identical(operator, sc.TokenType.EQ)) {
8407 Expression rightHandSide = node.rightHandSide;
8408 Type2 staticType = getStaticType(rightHandSide);
8409 recordStaticType(node, staticType);
8410 Type2 overrideType = staticType;
8411 Type2 propagatedType = rightHandSide.propagatedType;
8412 if (propagatedType != null) {
8413 if (propagatedType.isMoreSpecificThan(staticType)) {
8414 recordPropagatedType2(node, propagatedType);
8415 }
8416 overrideType = propagatedType;
8417 }
8418 _resolver.override(node.leftHandSide, overrideType);
8419 } else {
8420 ExecutableElement staticMethodElement = node.staticElement;
8421 Type2 staticType = computeStaticReturnType(staticMethodElement);
8422 recordStaticType(node, staticType);
8423 MethodElement propagatedMethodElement = node.propagatedElement;
8424 if (propagatedMethodElement != staticMethodElement) {
8425 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement);
8426 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) {
8427 recordPropagatedType2(node, propagatedType);
8428 }
8429 }
8430 }
8431 return null;
8432 }
8433
8434 /**
8435 * The Dart Language Specification, 12.20: <blockquote>The static type of a lo gical boolean
8436 * expression is `bool`.</blockquote>
8437 *
8438 * The Dart Language Specification, 12.21:<blockquote>A bitwise expression of the form
8439 * <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocatio n
8440 * <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A bitwise expression of the form <i >super op
8441 * e<sub>2</sub></i> is equivalent to the method invocation
8442 * <i>super.op(e<sub>2</sub>)</i>.</blockquote>
8443 *
8444 * The Dart Language Specification, 12.22: <blockquote>The static type of an e quality expression
8445 * is `bool`.</blockquote>
8446 *
8447 * The Dart Language Specification, 12.23: <blockquote>A relational expression of the form
8448 * <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocatio n
8449 * <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A relational expression of the form <i>super op
8450 * e<sub>2</sub></i> is equivalent to the method invocation
8451 * <i>super.op(e<sub>2</sub>)</i>.</blockquote>
8452 *
8453 * The Dart Language Specification, 12.24: <blockquote>A shift expression of t he form
8454 * <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocatio n
8455 * <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A shift expression of the form <i>s uper op
8456 * e<sub>2</sub></i> is equivalent to the method invocation
8457 * <i>super.op(e<sub>2</sub>)</i>.</blockquote>
8458 *
8459 * The Dart Language Specification, 12.25: <blockquote>An additive expression of the form
8460 * <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocatio n
8461 * <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. An additive expression of the form <i>super op
8462 * e<sub>2</sub></i> is equivalent to the method invocation
8463 * <i>super.op(e<sub>2</sub>)</i>.</blockquote>
8464 *
8465 * The Dart Language Specification, 12.26: <blockquote>A multiplicative expres sion of the form
8466 * <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocatio n
8467 * <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A multiplicative expression of the form <i>super op
8468 * e<sub>2</sub></i> is equivalent to the method invocation
8469 * <i>super.op(e<sub>2</sub>)</i>.</blockquote>
8470 */
8471 Object visitBinaryExpression(BinaryExpression node) {
8472 ExecutableElement staticMethodElement = node.staticElement;
8473 Type2 staticType = computeStaticReturnType(staticMethodElement);
8474 staticType = refineBinaryExpressionType(node, staticType);
8475 recordStaticType(node, staticType);
8476 MethodElement propagatedMethodElement = node.propagatedElement;
8477 if (propagatedMethodElement != staticMethodElement) {
8478 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement);
8479 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType )) {
8480 recordPropagatedType2(node, propagatedType);
8481 }
8482 }
8483 return null;
8484 }
8485
8486 /**
8487 * The Dart Language Specification, 12.4: <blockquote>The static type of a boo lean literal is
8488 * bool.</blockquote>
8489 */
8490 Object visitBooleanLiteral(BooleanLiteral node) {
8491 recordStaticType(node, _typeProvider.boolType);
8492 return null;
8493 }
8494
8495 /**
8496 * The Dart Language Specification, 12.15.2: <blockquote>A cascaded method inv ocation expression
8497 * of the form <i>e..suffix</i> is equivalent to the expression <i>(t) {t.suff ix; return
8498 * t;}(e)</i>.</blockquote>
8499 */
8500 Object visitCascadeExpression(CascadeExpression node) {
8501 recordStaticType(node, getStaticType(node.target));
8502 recordPropagatedType2(node, node.target.propagatedType);
8503 return null;
8504 }
8505
8506 /**
8507 * The Dart Language Specification, 12.19: <blockquote> ... a conditional expr ession <i>c</i> of
8508 * the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub></i> ...
8509 *
8510 * It is a static type warning if the type of e<sub>1</sub> may not be assigne d to `bool`.
8511 *
8512 * The static type of <i>c</i> is the least upper bound of the static type of <i>e<sub>2</sub></i>
8513 * and the static type of <i>e<sub>3</sub></i>.</blockquote>
8514 */
8515 Object visitConditionalExpression(ConditionalExpression node) {
8516 Type2 staticThenType = getStaticType(node.thenExpression);
8517 Type2 staticElseType = getStaticType(node.elseExpression);
8518 if (staticThenType == null) {
8519 staticThenType = _dynamicType;
8520 }
8521 if (staticElseType == null) {
8522 staticElseType = _dynamicType;
8523 }
8524 Type2 staticType = staticThenType.getLeastUpperBound(staticElseType);
8525 if (staticType == null) {
8526 staticType = _dynamicType;
8527 }
8528 recordStaticType(node, staticType);
8529 Type2 propagatedThenType = node.thenExpression.propagatedType;
8530 Type2 propagatedElseType = node.elseExpression.propagatedType;
8531 if (propagatedThenType != null || propagatedElseType != null) {
8532 if (propagatedThenType == null) {
8533 propagatedThenType = staticThenType;
8534 }
8535 if (propagatedElseType == null) {
8536 propagatedElseType = staticElseType;
8537 }
8538 Type2 propagatedType = propagatedThenType.getLeastUpperBound(propagatedEls eType);
8539 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType )) {
8540 recordPropagatedType2(node, propagatedType);
8541 }
8542 }
8543 return null;
8544 }
8545
8546 /**
8547 * The Dart Language Specification, 12.3: <blockquote>The static type of a lit eral double is
8548 * double.</blockquote>
8549 */
8550 Object visitDoubleLiteral(DoubleLiteral node) {
8551 recordStaticType(node, _typeProvider.doubleType);
8552 return null;
8553 }
8554 Object visitFunctionDeclaration(FunctionDeclaration node) {
8555 FunctionExpression function = node.functionExpression;
8556 ExecutableElementImpl functionElement = node.element as ExecutableElementImp l;
8557 functionElement.returnType = computeStaticReturnType2(node);
8558 recordPropagatedType(functionElement, function.body);
8559 recordStaticType(function, functionElement.type);
8560 return null;
8561 }
8562
8563 /**
8564 * The Dart Language Specification, 12.9: <blockquote>The static type of a fun ction literal of the
8565 * form <i>(T<sub>1</sub> a<sub>1</sub>, &hellip;, T<sub>n</sub> a<sub>n</sub> , [T<sub>n+1</sub>
8566 * x<sub>n+1</sub> = d1, &hellip;, T<sub>n+k</sub> x<sub>n+k</sub> = dk]) => e </i> is
8567 * <i>(T<sub>1</sub>, &hellip;, Tn, [T<sub>n+1</sub> x<sub>n+1</sub>, &hellip; , T<sub>n+k</sub>
8568 * x<sub>n+k</sub>]) &rarr; T<sub>0</sub></i>, where <i>T<sub>0</sub></i> is t he static type of
8569 * <i>e</i>. In any case where <i>T<sub>i</sub>, 1 &lt;= i &lt;= n</i>, is not specified, it is
8570 * considered to have been specified as dynamic.
8571 *
8572 * The static type of a function literal of the form <i>(T<sub>1</sub> a<sub>1 </sub>, &hellip;,
8573 * 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>
8574 * x<sub>n+k</sub> : dk}) => e</i> is <i>(T<sub>1</sub>, &hellip;, T<sub>n</su b>, {T<sub>n+1</sub>
8575 * x<sub>n+1</sub>, &hellip;, T<sub>n+k</sub> x<sub>n+k</sub>}) &rarr; T<sub>0 </sub></i>, where
8576 * <i>T<sub>0</sub></i> is the static type of <i>e</i>. In any case where <i>T <sub>i</sub>, 1
8577 * &lt;= i &lt;= n</i>, is not specified, it is considered to have been specif ied as dynamic.
8578 *
8579 * The static type of a function literal of the form <i>(T<sub>1</sub> a<sub>1 </sub>, &hellip;,
8580 * 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>
8581 * x<sub>n+k</sub> = dk]) {s}</i> is <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub >, [T<sub>n+1</sub>
8582 * x<sub>n+1</sub>, &hellip;, T<sub>n+k</sub> x<sub>n+k</sub>]) &rarr; dynamic </i>. In any case
8583 * where <i>T<sub>i</sub>, 1 &lt;= i &lt;= n</i>, is not specified, it is cons idered to have been
8584 * specified as dynamic.
8585 *
8586 * The static type of a function literal of the form <i>(T<sub>1</sub> a<sub>1 </sub>, &hellip;,
8587 * 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>
8588 * x<sub>n+k</sub> : dk}) {s}</i> is <i>(T<sub>1</sub>, &hellip;, T<sub>n</sub >, {T<sub>n+1</sub>
8589 * x<sub>n+1</sub>, &hellip;, T<sub>n+k</sub> x<sub>n+k</sub>}) &rarr; dynamic </i>. In any case
8590 * where <i>T<sub>i</sub>, 1 &lt;= i &lt;= n</i>, is not specified, it is cons idered to have been
8591 * specified as dynamic.</blockquote>
8592 */
8593 Object visitFunctionExpression(FunctionExpression node) {
8594 if (node.parent is FunctionDeclaration) {
8595 return null;
8596 }
8597 ExecutableElementImpl functionElement = node.element as ExecutableElementImp l;
8598 functionElement.returnType = computeStaticReturnType3(node);
8599 recordPropagatedType(functionElement, node.body);
8600 recordStaticType(node, node.element.type);
8601 return null;
8602 }
8603
8604 /**
8605 * The Dart Language Specification, 12.14.4: <blockquote>A function expression invocation <i>i</i>
8606 * has the form <i>e<sub>f</sub>(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub >n+1</sub>:
8607 * 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
8608 * an expression.
8609 *
8610 * It is a static type warning if the static type <i>F</i> of <i>e<sub>f</sub> </i> may not be
8611 * assigned to a function type.
8612 *
8613 * If <i>F</i> is not a function type, the static type of <i>i</i> is dynamic. Otherwise the
8614 * static type of <i>i</i> is the declared return type of <i>F</i>.</blockquot e>
8615 */
8616 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
8617 ExecutableElement staticMethodElement = node.staticElement;
8618 Type2 staticStaticType = computeStaticReturnType(staticMethodElement);
8619 recordStaticType(node, staticStaticType);
8620 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement );
8621 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) {
8622 recordPropagatedType2(node, staticPropagatedType);
8623 }
8624 ExecutableElement propagatedMethodElement = node.propagatedElement;
8625 if (propagatedMethodElement != staticMethodElement) {
8626 Type2 propagatedStaticType = computeStaticReturnType(propagatedMethodEleme nt);
8627 if (propagatedStaticType != null && (staticStaticType == null || propagate dStaticType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedType == nu ll || propagatedStaticType.isMoreSpecificThan(staticPropagatedType))) {
8628 recordPropagatedType2(node, propagatedStaticType);
8629 }
8630 Type2 propagatedPropagatedType = computePropagatedReturnType(propagatedMet hodElement);
8631 if (propagatedPropagatedType != null && (staticStaticType == null || propa gatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedTy pe == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType)) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificThan (propagatedStaticType))) {
8632 recordPropagatedType2(node, propagatedPropagatedType);
8633 }
8634 }
8635 return null;
8636 }
8637
8638 /**
8639 * The Dart Language Specification, 12.29: <blockquote>An assignable expressio n of the form
8640 * <i>e<sub>1</sub>[e<sub>2</sub>]</i> is evaluated as a method invocation of the operator method
8641 * <i>[]</i> on <i>e<sub>1</sub></i> with argument <i>e<sub>2</sub></i>.</bloc kquote>
8642 */
8643 Object visitIndexExpression(IndexExpression node) {
8644 if (node.inSetterContext()) {
8645 ExecutableElement staticMethodElement = node.staticElement;
8646 Type2 staticType = computeArgumentType(staticMethodElement);
8647 recordStaticType(node, staticType);
8648 MethodElement propagatedMethodElement = node.propagatedElement;
8649 if (propagatedMethodElement != staticMethodElement) {
8650 Type2 propagatedType = computeArgumentType(propagatedMethodElement);
8651 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) {
8652 recordPropagatedType2(node, propagatedType);
8653 }
8654 }
8655 } else {
8656 ExecutableElement staticMethodElement = node.staticElement;
8657 Type2 staticType = computeStaticReturnType(staticMethodElement);
8658 recordStaticType(node, staticType);
8659 MethodElement propagatedMethodElement = node.propagatedElement;
8660 if (propagatedMethodElement != staticMethodElement) {
8661 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement);
8662 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) {
8663 recordPropagatedType2(node, propagatedType);
8664 }
8665 }
8666 }
8667 return null;
8668 }
8669
8670 /**
8671 * The Dart Language Specification, 12.11.1: <blockquote>The static type of a new expression of
8672 * either the form <i>new T.id(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> or the form <i>new
8673 * T(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> is <i>T</i>.</blockquote>
8674 *
8675 * The Dart Language Specification, 12.11.2: <blockquote>The static type of a constant object
8676 * expression of either the form <i>const T.id(a<sub>1</sub>, &hellip;, a<sub> n</sub>)</i> or the
8677 * form <i>const T(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> is <i>T</i>. </ blockquote>
8678 */
8679 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
8680 recordStaticType(node, node.constructorName.type.type);
8681 ConstructorElement element = node.staticElement;
8682 if (element != null && "Element" == element.enclosingElement.name) {
8683 LibraryElement library = element.library;
8684 if (isHtmlLibrary(library)) {
8685 String constructorName = element.name;
8686 if ("tag" == constructorName) {
8687 Type2 returnType = getFirstArgumentAsType2(library, node.argumentList, _HTML_ELEMENT_TO_CLASS_MAP);
8688 if (returnType != null) {
8689 recordPropagatedType2(node, returnType);
8690 }
8691 } else {
8692 Type2 returnType = getElementNameAsType(library, constructorName, _HTM L_ELEMENT_TO_CLASS_MAP);
8693 if (returnType != null) {
8694 recordPropagatedType2(node, returnType);
8695 }
8696 }
8697 }
8698 }
8699 return null;
8700 }
8701
8702 /**
8703 * The Dart Language Specification, 12.3: <blockquote>The static type of an in teger literal is
8704 * `int`.</blockquote>
8705 */
8706 Object visitIntegerLiteral(IntegerLiteral node) {
8707 recordStaticType(node, _typeProvider.intType);
8708 return null;
8709 }
8710
8711 /**
8712 * The Dart Language Specification, 12.31: <blockquote>It is a static warning if <i>T</i> does not
8713 * denote a type available in the current lexical scope.
8714 *
8715 * The static type of an is-expression is `bool`.</blockquote>
8716 */
8717 Object visitIsExpression(IsExpression node) {
8718 recordStaticType(node, _typeProvider.boolType);
8719 return null;
8720 }
8721
8722 /**
8723 * The Dart Language Specification, 12.6: <blockquote>The static type of a lis t literal of the
8724 * form <i><b>const</b> &lt;E&gt;[e<sub>1</sub>, &hellip;, e<sub>n</sub>]</i> or the form
8725 * <i>&lt;E&gt;[e<sub>1</sub>, &hellip;, e<sub>n</sub>]</i> is `List&lt;E&gt;` . The static
8726 * type a list literal of the form <i><b>const</b> [e<sub>1</sub>, &hellip;, e <sub>n</sub>]</i> or
8727 * the form <i>[e<sub>1</sub>, &hellip;, e<sub>n</sub>]</i> is `List&lt;dynami c&gt;`
8728 * .</blockquote>
8729 */
8730 Object visitListLiteral(ListLiteral node) {
8731 Type2 staticType = _dynamicType;
8732 TypeArgumentList typeArguments = node.typeArguments;
8733 if (typeArguments != null) {
8734 NodeList<TypeName> arguments = typeArguments.arguments;
8735 if (arguments != null && arguments.length == 1) {
8736 TypeName argumentTypeName = arguments[0];
8737 Type2 argumentType = getType2(argumentTypeName);
8738 if (argumentType != null) {
8739 staticType = argumentType;
8740 }
8741 }
8742 }
8743 recordStaticType(node, _typeProvider.listType.substitute4(<Type2> [staticTyp e]));
8744 NodeList<Expression> elements = node.elements;
8745 int count = elements.length;
8746 if (count > 0) {
8747 Type2 propagatedType = elements[0].bestType;
8748 for (int i = 1; i < count; i++) {
8749 Type2 elementType = elements[i].bestType;
8750 if (propagatedType != elementType) {
8751 propagatedType = _dynamicType;
8752 } else {
8753 propagatedType = propagatedType.getLeastUpperBound(elementType);
8754 if (propagatedType == null) {
8755 propagatedType = _dynamicType;
8756 }
8757 }
8758 }
8759 if (propagatedType.isMoreSpecificThan(staticType)) {
8760 recordPropagatedType2(node, _typeProvider.listType.substitute4(<Type2> [ propagatedType]));
8761 }
8762 }
8763 return null;
8764 }
8765
8766 /**
8767 * The Dart Language Specification, 12.7: <blockquote>The static type of a map literal of the form
8768 * <i><b>const</b> &lt;String, V&gt; {k<sub>1</sub>:e<sub>1</sub>, &hellip;,
8769 * k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i>&lt;String, V&gt; {k<sub>1< /sub>:e<sub>1</sub>,
8770 * &hellip;, k<sub>n</sub>:e<sub>n</sub>}</i> is `Map&lt;String, V&gt;`. The s tatic type a
8771 * map literal of the form <i><b>const</b> {k<sub>1</sub>:e<sub>1</sub>, &hell ip;,
8772 * k<sub>n</sub>:e<sub>n</sub>}</i> or the form <i>{k<sub>1</sub>:e<sub>1</sub >, &hellip;,
8773 * k<sub>n</sub>:e<sub>n</sub>}</i> is `Map&lt;String, dynamic&gt;`.
8774 *
8775 * It is a compile-time error if the first type argument to a map literal is n ot
8776 * <i>String</i>.</blockquote>
8777 */
8778 Object visitMapLiteral(MapLiteral node) {
8779 Type2 staticKeyType = _dynamicType;
8780 Type2 staticValueType = _dynamicType;
8781 TypeArgumentList typeArguments = node.typeArguments;
8782 if (typeArguments != null) {
8783 NodeList<TypeName> arguments = typeArguments.arguments;
8784 if (arguments != null && arguments.length == 2) {
8785 TypeName entryKeyTypeName = arguments[0];
8786 Type2 entryKeyType = getType2(entryKeyTypeName);
8787 if (entryKeyType != null) {
8788 staticKeyType = entryKeyType;
8789 }
8790 TypeName entryValueTypeName = arguments[1];
8791 Type2 entryValueType = getType2(entryValueTypeName);
8792 if (entryValueType != null) {
8793 staticValueType = entryValueType;
8794 }
8795 }
8796 }
8797 recordStaticType(node, _typeProvider.mapType.substitute4(<Type2> [staticKeyT ype, staticValueType]));
8798 NodeList<MapLiteralEntry> entries = node.entries;
8799 int count = entries.length;
8800 if (count > 0) {
8801 MapLiteralEntry entry = entries[0];
8802 Type2 propagatedKeyType = entry.key.bestType;
8803 Type2 propagatedValueType = entry.value.bestType;
8804 for (int i = 1; i < count; i++) {
8805 entry = entries[i];
8806 Type2 elementKeyType = entry.key.bestType;
8807 if (propagatedKeyType != elementKeyType) {
8808 propagatedKeyType = _dynamicType;
8809 } else {
8810 propagatedKeyType = propagatedKeyType.getLeastUpperBound(elementKeyTyp e);
8811 if (propagatedKeyType == null) {
8812 propagatedKeyType = _dynamicType;
8813 }
8814 }
8815 Type2 elementValueType = entry.value.bestType;
8816 if (propagatedValueType != elementValueType) {
8817 propagatedValueType = _dynamicType;
8818 } else {
8819 propagatedValueType = propagatedValueType.getLeastUpperBound(elementVa lueType);
8820 if (propagatedValueType == null) {
8821 propagatedValueType = _dynamicType;
8822 }
8823 }
8824 }
8825 bool betterKey = propagatedKeyType != null && propagatedKeyType.isMoreSpec ificThan(staticKeyType);
8826 bool betterValue = propagatedValueType != null && propagatedValueType.isMo reSpecificThan(staticValueType);
8827 if (betterKey || betterValue) {
8828 if (!betterKey) {
8829 propagatedKeyType = staticKeyType;
8830 }
8831 if (!betterValue) {
8832 propagatedValueType = staticValueType;
8833 }
8834 recordPropagatedType2(node, _typeProvider.mapType.substitute4(<Type2> [p ropagatedKeyType, propagatedValueType]));
8835 }
8836 }
8837 return null;
8838 }
8839
8840 /**
8841 * The Dart Language Specification, 12.15.1: <blockquote>An ordinary method in vocation <i>i</i>
8842 * has the form <i>o.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub> : a<sub>n+1</sub>,
8843 * &hellip;, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
8844 *
8845 * Let <i>T</i> be the static type of <i>o</i>. It is a static type warning if <i>T</i> does not
8846 * have an accessible instance member named <i>m</i>. If <i>T.m</i> exists, it is a static warning
8847 * if the type <i>F</i> of <i>T.m</i> may not be assigned to a function type.
8848 *
8849 * If <i>T.m</i> does not exist, or if <i>F</i> is not a function type, the st atic type of
8850 * <i>i</i> is dynamic. Otherwise the static type of <i>i</i> is the declared return type of
8851 * <i>F</i>.</blockquote>
8852 *
8853 * The Dart Language Specification, 11.15.3: <blockquote>A static method invoc ation <i>i</i> has
8854 * the form <i>C.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub>: a< sub>n+1</sub>,
8855 * &hellip;, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
8856 *
8857 * It is a static type warning if the type <i>F</i> of <i>C.m</i> may not be a ssigned to a
8858 * function type.
8859 *
8860 * If <i>F</i> is not a function type, or if <i>C.m</i> does not exist, the st atic type of i is
8861 * dynamic. Otherwise the static type of <i>i</i> is the declared return type of
8862 * <i>F</i>.</blockquote>
8863 *
8864 * The Dart Language Specification, 11.15.4: <blockquote>A super method invoca tion <i>i</i> has
8865 * the form <i>super.m(a<sub>1</sub>, &hellip;, a<sub>n</sub>, x<sub>n+1</sub> : a<sub>n+1</sub>,
8866 * &hellip;, x<sub>n+k</sub>: a<sub>n+k</sub>)</i>.
8867 *
8868 * It is a static type warning if <i>S</i> does not have an accessible instanc e member named m. If
8869 * <i>S.m</i> exists, it is a static warning if the type <i>F</i> of <i>S.m</i > may not be
8870 * assigned to a function type.
8871 *
8872 * If <i>S.m</i> does not exist, or if <i>F</i> is not a function type, the st atic type of
8873 * <i>i</i> is dynamic. Otherwise the static type of <i>i</i> is the declared return type of
8874 * <i>F</i>.</blockquote>
8875 */
8876 Object visitMethodInvocation(MethodInvocation node) {
8877 SimpleIdentifier methodNameNode = node.methodName;
8878 Element staticMethodElement = methodNameNode.staticElement;
8879 Type2 staticStaticType = computeStaticReturnType(staticMethodElement);
8880 recordStaticType(node, staticStaticType);
8881 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement );
8882 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) {
8883 recordPropagatedType2(node, staticPropagatedType);
8884 }
8885 String methodName = methodNameNode.name;
8886 if (methodName == "then") {
8887 Expression target = node.realTarget;
8888 Type2 targetType = target == null ? null : target.bestType;
8889 if (isAsyncFutureType(targetType)) {
8890 NodeList<Expression> arguments = node.argumentList.arguments;
8891 if (arguments.length == 1) {
8892 Expression closureArg = arguments[0];
8893 if (closureArg is FunctionExpression) {
8894 FunctionExpression closureExpr = closureArg as FunctionExpression;
8895 Type2 returnType = computePropagatedReturnType(closureExpr.element);
8896 if (returnType != null) {
8897 InterfaceTypeImpl newFutureType;
8898 if (isAsyncFutureType(returnType)) {
8899 newFutureType = returnType as InterfaceTypeImpl;
8900 } else {
8901 InterfaceType futureType = targetType as InterfaceType;
8902 newFutureType = new InterfaceTypeImpl.con1(futureType.element);
8903 newFutureType.typeArguments = <Type2> [returnType];
8904 }
8905 recordPropagatedType2(node, newFutureType);
8906 return null;
8907 }
8908 }
8909 }
8910 }
8911 }
8912 if (methodName == "\$dom_createEvent") {
8913 Expression target = node.realTarget;
8914 if (target != null) {
8915 Type2 targetType = target.bestType;
8916 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || targetType.name == "Document")) {
8917 LibraryElement library = targetType.element.library;
8918 if (isHtmlLibrary(library)) {
8919 Type2 returnType = getFirstArgumentAsType(library, node.argumentList );
8920 if (returnType != null) {
8921 recordPropagatedType2(node, returnType);
8922 }
8923 }
8924 }
8925 }
8926 } else if (methodName == "query") {
8927 Expression target = node.realTarget;
8928 if (target == null) {
8929 Element methodElement = methodNameNode.bestElement;
8930 if (methodElement != null) {
8931 LibraryElement library = methodElement.library;
8932 if (isHtmlLibrary(library)) {
8933 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentLis t);
8934 if (returnType != null) {
8935 recordPropagatedType2(node, returnType);
8936 }
8937 }
8938 }
8939 } else {
8940 Type2 targetType = target.bestType;
8941 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || targetType.name == "Document")) {
8942 LibraryElement library = targetType.element.library;
8943 if (isHtmlLibrary(library)) {
8944 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentLis t);
8945 if (returnType != null) {
8946 recordPropagatedType2(node, returnType);
8947 }
8948 }
8949 }
8950 }
8951 } else if (methodName == "\$dom_createElement") {
8952 Expression target = node.realTarget;
8953 Type2 targetType = target.bestType;
8954 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || t argetType.name == "Document")) {
8955 LibraryElement library = targetType.element.library;
8956 if (isHtmlLibrary(library)) {
8957 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentList) ;
8958 if (returnType != null) {
8959 recordPropagatedType2(node, returnType);
8960 }
8961 }
8962 }
8963 } else if (methodName == "JS") {
8964 Type2 returnType = getFirstArgumentAsType(_typeProvider.objectType.element .library, node.argumentList);
8965 if (returnType != null) {
8966 recordPropagatedType2(node, returnType);
8967 }
8968 } else {
8969 Element propagatedElement = methodNameNode.propagatedElement;
8970 if (propagatedElement != staticMethodElement) {
8971 Type2 propagatedStaticType = computeStaticReturnType(propagatedElement);
8972 if (propagatedStaticType != null && (staticStaticType == null || propaga tedStaticType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedType == null || propagatedStaticType.isMoreSpecificThan(staticPropagatedType))) {
8973 recordPropagatedType2(node, propagatedStaticType);
8974 }
8975 Type2 propagatedPropagatedType = computePropagatedReturnType(propagatedE lement);
8976 if (propagatedPropagatedType != null && (staticStaticType == null || pro pagatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagated Type == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType )) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificTh an(propagatedStaticType))) {
8977 recordPropagatedType2(node, propagatedPropagatedType);
8978 }
8979 }
8980 }
8981 return null;
8982 }
8983 Object visitNamedExpression(NamedExpression node) {
8984 Expression expression = node.expression;
8985 recordStaticType(node, getStaticType(expression));
8986 recordPropagatedType2(node, expression.propagatedType);
8987 return null;
8988 }
8989
8990 /**
8991 * The Dart Language Specification, 12.2: <blockquote>The static type of `null ` is bottom.
8992 * </blockquote>
8993 */
8994 Object visitNullLiteral(NullLiteral node) {
8995 recordStaticType(node, _typeProvider.bottomType);
8996 return null;
8997 }
8998 Object visitParenthesizedExpression(ParenthesizedExpression node) {
8999 Expression expression = node.expression;
9000 recordStaticType(node, getStaticType(expression));
9001 recordPropagatedType2(node, expression.propagatedType);
9002 return null;
9003 }
9004
9005 /**
9006 * The Dart Language Specification, 12.28: <blockquote>A postfix expression of the form
9007 * <i>v++</i>, where <i>v</i> is an identifier, is equivalent to <i>(){var r = v; v = r + 1;
9008 * return r}()</i>.
9009 *
9010 * A postfix expression of the form <i>C.v++</i> is equivalent to <i>(){var r = C.v; C.v = r + 1;
9011 * return r}()</i>.
9012 *
9013 * A postfix expression of the form <i>e1.v++</i> is equivalent to <i>(x){var r = x.v; x.v = r +
9014 * 1; return r}(e1)</i>.
9015 *
9016 * A postfix expression of the form <i>e1[e2]++</i> is equivalent to <i>(a, i) {var r = a[i]; a[i]
9017 * = r + 1; return r}(e1, e2)</i>
9018 *
9019 * A postfix expression of the form <i>v--</i>, where <i>v</i> is an identifie r, is equivalent to
9020 * <i>(){var r = v; v = r - 1; return r}()</i>.
9021 *
9022 * A postfix expression of the form <i>C.v--</i> is equivalent to <i>(){var r = C.v; C.v = r - 1;
9023 * return r}()</i>.
9024 *
9025 * A postfix expression of the form <i>e1.v--</i> is equivalent to <i>(x){var r = x.v; x.v = r -
9026 * 1; return r}(e1)</i>.
9027 *
9028 * A postfix expression of the form <i>e1[e2]--</i> is equivalent to <i>(a, i) {var r = a[i]; a[i]
9029 * = r - 1; return r}(e1, e2)</i></blockquote>
9030 */
9031 Object visitPostfixExpression(PostfixExpression node) {
9032 Expression operand = node.operand;
9033 Type2 staticType = getStaticType(operand);
9034 sc.TokenType operator = node.operator.type;
9035 if (identical(operator, sc.TokenType.MINUS_MINUS) || identical(operator, sc. TokenType.PLUS_PLUS)) {
9036 Type2 intType = _typeProvider.intType;
9037 if (identical(getStaticType(node.operand), intType)) {
9038 staticType = intType;
9039 }
9040 }
9041 recordStaticType(node, staticType);
9042 recordPropagatedType2(node, operand.propagatedType);
9043 return null;
9044 }
9045
9046 /**
9047 * See [visitSimpleIdentifier].
9048 */
9049 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
9050 SimpleIdentifier prefixedIdentifier = node.identifier;
9051 Element staticElement = prefixedIdentifier.staticElement;
9052 Type2 staticType = _dynamicType;
9053 if (staticElement is ClassElement) {
9054 if (isNotTypeLiteral(node)) {
9055 staticType = ((staticElement as ClassElement)).type;
9056 } else {
9057 staticType = _typeProvider.typeType;
9058 }
9059 } else if (staticElement is FunctionTypeAliasElement) {
9060 staticType = ((staticElement as FunctionTypeAliasElement)).type;
9061 } else if (staticElement is MethodElement) {
9062 staticType = ((staticElement as MethodElement)).type;
9063 } else if (staticElement is PropertyAccessorElement) {
9064 staticType = getType(staticElement as PropertyAccessorElement, node.prefix .staticType);
9065 } else if (staticElement is ExecutableElement) {
9066 staticType = ((staticElement as ExecutableElement)).type;
9067 } else if (staticElement is TypeParameterElement) {
9068 staticType = ((staticElement as TypeParameterElement)).type;
9069 } else if (staticElement is VariableElement) {
9070 staticType = ((staticElement as VariableElement)).type;
9071 }
9072 recordStaticType(prefixedIdentifier, staticType);
9073 recordStaticType(node, staticType);
9074 Element propagatedElement = prefixedIdentifier.propagatedElement;
9075 Type2 propagatedType = null;
9076 if (propagatedElement is ClassElement) {
9077 if (isNotTypeLiteral(node)) {
9078 propagatedType = ((propagatedElement as ClassElement)).type;
9079 } else {
9080 propagatedType = _typeProvider.typeType;
9081 }
9082 } else if (propagatedElement is FunctionTypeAliasElement) {
9083 propagatedType = ((propagatedElement as FunctionTypeAliasElement)).type;
9084 } else if (propagatedElement is MethodElement) {
9085 propagatedType = ((propagatedElement as MethodElement)).type;
9086 } else if (propagatedElement is PropertyAccessorElement) {
9087 propagatedType = getType(propagatedElement as PropertyAccessorElement, nod e.prefix.staticType);
9088 } else if (propagatedElement is ExecutableElement) {
9089 propagatedType = ((propagatedElement as ExecutableElement)).type;
9090 } else if (propagatedElement is TypeParameterElement) {
9091 propagatedType = ((propagatedElement as TypeParameterElement)).type;
9092 } else if (propagatedElement is VariableElement) {
9093 propagatedType = ((propagatedElement as VariableElement)).type;
9094 }
9095 Type2 overriddenType = _overrideManager.getType(propagatedElement);
9096 if (propagatedType == null || (overriddenType != null && overriddenType.isMo reSpecificThan(propagatedType))) {
9097 propagatedType = overriddenType;
9098 }
9099 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType)) {
9100 recordPropagatedType2(prefixedIdentifier, propagatedType);
9101 recordPropagatedType2(node, propagatedType);
9102 }
9103 return null;
9104 }
9105
9106 /**
9107 * The Dart Language Specification, 12.27: <blockquote>A unary expression <i>u </i> of the form
9108 * <i>op e</i> is equivalent to a method invocation <i>expression e.op()</i>. An expression of the
9109 * form <i>op super</i> is equivalent to the method invocation <i>super.op()<i >.</blockquote>
9110 */
9111 Object visitPrefixExpression(PrefixExpression node) {
9112 sc.TokenType operator = node.operator.type;
9113 if (identical(operator, sc.TokenType.BANG)) {
9114 recordStaticType(node, _typeProvider.boolType);
9115 } else {
9116 ExecutableElement staticMethodElement = node.staticElement;
9117 Type2 staticType = computeStaticReturnType(staticMethodElement);
9118 if (identical(operator, sc.TokenType.MINUS_MINUS) || identical(operator, s c.TokenType.PLUS_PLUS)) {
9119 Type2 intType = _typeProvider.intType;
9120 if (identical(getStaticType(node.operand), intType)) {
9121 staticType = intType;
9122 }
9123 }
9124 recordStaticType(node, staticType);
9125 MethodElement propagatedMethodElement = node.propagatedElement;
9126 if (propagatedMethodElement != staticMethodElement) {
9127 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement);
9128 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) {
9129 recordPropagatedType2(node, propagatedType);
9130 }
9131 }
9132 }
9133 return null;
9134 }
9135
9136 /**
9137 * The Dart Language Specification, 12.13: <blockquote> Property extraction al lows for a member of
9138 * an object to be concisely extracted from the object. If <i>o</i> is an obje ct, and if <i>m</i>
9139 * is the name of a method member of <i>o</i>, then
9140 *
9141 * * <i>o.m</i> is defined to be equivalent to: <i>(r<sub>1</sub>, &hellip;, r <sub>n</sub>,
9142 * {p<sub>1</sub> : d<sub>1</sub>, &hellip;, p<sub>k</sub> : d<sub>k</sub>}){r eturn
9143 * o.m(r<sub>1</sub>, &hellip;, r<sub>n</sub>, p<sub>1</sub>: p<sub>1</sub>, & hellip;,
9144 * p<sub>k</sub>: p<sub>k</sub>);}</i> if <i>m</i> has required parameters <i> r<sub>1</sub>,
9145 * &hellip;, r<sub>n</sub></i>, and named parameters <i>p<sub>1</sub> &hellip; p<sub>k</sub></i>
9146 * with defaults <i>d<sub>1</sub>, &hellip;, d<sub>k</sub></i>.
9147 * * <i>(r<sub>1</sub>, &hellip;, r<sub>n</sub>, [p<sub>1</sub> = d<sub>1</sub >, &hellip;,
9148 * p<sub>k</sub> = d<sub>k</sub>]){return o.m(r<sub>1</sub>, &hellip;, r<sub>n </sub>,
9149 * p<sub>1</sub>, &hellip;, p<sub>k</sub>);}</i> if <i>m</i> has required para meters
9150 * <i>r<sub>1</sub>, &hellip;, r<sub>n</sub></i>, and optional positional para meters
9151 * <i>p<sub>1</sub> &hellip; p<sub>k</sub></i> with defaults <i>d<sub>1</sub>, &hellip;,
9152 * d<sub>k</sub></i>.
9153 *
9154 * Otherwise, if <i>m</i> is the name of a getter member of <i>o</i> (declared implicitly or
9155 * explicitly) then <i>o.m</i> evaluates to the result of invoking the getter. </blockquote>
9156 *
9157 * The Dart Language Specification, 12.17: <blockquote> ... a getter invocatio n <i>i</i> of the
9158 * form <i>e.m</i> ...
9159 *
9160 * Let <i>T</i> be the static type of <i>e</i>. It is a static type warning if <i>T</i> does not
9161 * have a getter named <i>m</i>.
9162 *
9163 * The static type of <i>i</i> is the declared return type of <i>T.m</i>, if < i>T.m</i> exists;
9164 * otherwise the static type of <i>i</i> is dynamic.
9165 *
9166 * ... a getter invocation <i>i</i> of the form <i>C.m</i> ...
9167 *
9168 * It is a static warning if there is no class <i>C</i> in the enclosing lexic al scope of
9169 * <i>i</i>, or if <i>C</i> does not declare, implicitly or explicitly, a gett er named <i>m</i>.
9170 *
9171 * The static type of <i>i</i> is the declared return type of <i>C.m</i> if it exists or dynamic
9172 * otherwise.
9173 *
9174 * ... a top-level getter invocation <i>i</i> of the form <i>m</i>, where <i>m </i> is an
9175 * identifier ...
9176 *
9177 * The static type of <i>i</i> is the declared return type of <i>m</i>.</block quote>
9178 */
9179 Object visitPropertyAccess(PropertyAccess node) {
9180 SimpleIdentifier propertyName = node.propertyName;
9181 Element element = propertyName.staticElement;
9182 Type2 staticType = _dynamicType;
9183 if (element is MethodElement) {
9184 staticType = ((element as MethodElement)).type;
9185 } else if (element is PropertyAccessorElement) {
9186 staticType = getType(element as PropertyAccessorElement, node.target != nu ll ? getStaticType(node.target) : null);
9187 } else {
9188 }
9189 recordStaticType(propertyName, staticType);
9190 recordStaticType(node, staticType);
9191 Type2 propagatedType = _overrideManager.getType(element);
9192 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType)) {
9193 recordPropagatedType2(node, propagatedType);
9194 }
9195 return null;
9196 }
9197
9198 /**
9199 * The Dart Language Specification, 12.9: <blockquote>The static type of a ret hrow expression is
9200 * bottom.</blockquote>
9201 */
9202 Object visitRethrowExpression(RethrowExpression node) {
9203 recordStaticType(node, _typeProvider.bottomType);
9204 return null;
9205 }
9206
9207 /**
9208 * The Dart Language Specification, 12.30: <blockquote>Evaluation of an identi fier expression
9209 * <i>e</i> of the form <i>id</i> proceeds as follows:
9210 *
9211 * Let <i>d</i> be the innermost declaration in the enclosing lexical scope wh ose name is
9212 * <i>id</i>. If no such declaration exists in the lexical scope, let <i>d</i> be the declaration
9213 * of the inherited member named <i>id</i> if it exists.
9214 *
9215 * * If <i>d</i> is a class or type alias <i>T</i>, the value of <i>e</i> is t he unique instance
9216 * of class `Type` reifying <i>T</i>.
9217 * * If <i>d</i> is a type parameter <i>T</i>, then the value of <i>e</i> is t he value of the
9218 * actual type argument corresponding to <i>T</i> that was passed to the gener ative constructor
9219 * that created the current binding of this. We are assured that this is well defined, because if
9220 * we were in a static member the reference to <i>T</i> would be a compile-tim e error.
9221 * * If <i>d</i> is a library variable then:
9222 *
9223 * * If <i>d</i> is of one of the forms <i>var v = e<sub>i</sub>;</i>, <i>T v =
9224 * e<sub>i</sub>;</i>, <i>final v = e<sub>i</sub>;</i>, <i>final T v = e<sub>i </sub>;</i>, and no
9225 * value has yet been stored into <i>v</i> then the initializer expression <i> e<sub>i</sub></i> is
9226 * evaluated. If, during the evaluation of <i>e<sub>i</sub></i>, the getter fo r <i>v</i> is
9227 * referenced, a CyclicInitializationError is thrown. If the evaluation succee ded yielding an
9228 * object <i>o</i>, let <i>r = o</i>, otherwise let <i>r = null</i>. In any ca se, <i>r</i> is
9229 * stored into <i>v</i>. The value of <i>e</i> is <i>r</i>.
9230 * * If <i>d</i> is of one of the forms <i>const v = e;</i> or <i>const T v = e;</i> the result
9231 * of the getter is the value of the compile time constant <i>e</i>. Otherwise
9232 * * <i>e</i> evaluates to the current binding of <i>id</i>.
9233 *
9234 * * If <i>d</i> is a local variable or formal parameter then <i>e</i> evaluat es to the current
9235 * binding of <i>id</i>.
9236 * * If <i>d</i> is a static method, top level function or local function then <i>e</i>
9237 * evaluates to the function defined by <i>d</i>.
9238 * * If <i>d</i> is the declaration of a static variable or static getter decl ared in class
9239 * <i>C</i>, then <i>e</i> is equivalent to the getter invocation <i>C.id</i>.
9240 * * If <i>d</i> is the declaration of a top level getter, then <i>e</i> is eq uivalent to the
9241 * getter invocation <i>id</i>.
9242 * * Otherwise, if <i>e</i> occurs inside a top level or static function (be i t function,
9243 * method, getter, or setter) or variable initializer, evaluation of e causes a NoSuchMethodError
9244 * to be thrown.
9245 * * Otherwise <i>e</i> is equivalent to the property extraction <i>this.id</i >.
9246 *
9247 * </blockquote>
9248 */
9249 Object visitSimpleIdentifier(SimpleIdentifier node) {
9250 Element element = node.staticElement;
9251 Type2 staticType = _dynamicType;
9252 if (element is ClassElement) {
9253 if (isNotTypeLiteral(node)) {
9254 staticType = ((element as ClassElement)).type;
9255 } else {
9256 staticType = _typeProvider.typeType;
9257 }
9258 } else if (element is FunctionTypeAliasElement) {
9259 staticType = ((element as FunctionTypeAliasElement)).type;
9260 } else if (element is MethodElement) {
9261 staticType = ((element as MethodElement)).type;
9262 } else if (element is PropertyAccessorElement) {
9263 staticType = getType(element as PropertyAccessorElement, null);
9264 } else if (element is ExecutableElement) {
9265 staticType = ((element as ExecutableElement)).type;
9266 } else if (element is TypeParameterElement) {
9267 staticType = ((element as TypeParameterElement)).type;
9268 } else if (element is VariableElement) {
9269 VariableElement variable = element as VariableElement;
9270 staticType = _promoteManager.getStaticType(variable);
9271 } else if (element is PrefixElement) {
9272 return null;
9273 } else {
9274 staticType = _dynamicType;
9275 }
9276 recordStaticType(node, staticType);
9277 Type2 propagatedType = _overrideManager.getType(element);
9278 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType)) {
9279 recordPropagatedType2(node, propagatedType);
9280 }
9281 return null;
9282 }
9283
9284 /**
9285 * The Dart Language Specification, 12.5: <blockquote>The static type of a str ing literal is
9286 * `String`.</blockquote>
9287 */
9288 Object visitSimpleStringLiteral(SimpleStringLiteral node) {
9289 recordStaticType(node, _typeProvider.stringType);
9290 return null;
9291 }
9292
9293 /**
9294 * The Dart Language Specification, 12.5: <blockquote>The static type of a str ing literal is
9295 * `String`.</blockquote>
9296 */
9297 Object visitStringInterpolation(StringInterpolation node) {
9298 recordStaticType(node, _typeProvider.stringType);
9299 return null;
9300 }
9301 Object visitSuperExpression(SuperExpression node) {
9302 if (_thisType == null) {
9303 recordStaticType(node, _dynamicType);
9304 } else {
9305 recordStaticType(node, _thisType);
9306 }
9307 return null;
9308 }
9309 Object visitSymbolLiteral(SymbolLiteral node) {
9310 recordStaticType(node, _typeProvider.symbolType);
9311 return null;
9312 }
9313
9314 /**
9315 * The Dart Language Specification, 12.10: <blockquote>The static type of `thi s` is the
9316 * interface of the immediately enclosing class.</blockquote>
9317 */
9318 Object visitThisExpression(ThisExpression node) {
9319 if (_thisType == null) {
9320 recordStaticType(node, _dynamicType);
9321 } else {
9322 recordStaticType(node, _thisType);
9323 }
9324 return null;
9325 }
9326
9327 /**
9328 * The Dart Language Specification, 12.8: <blockquote>The static type of a thr ow expression is
9329 * bottom.</blockquote>
9330 */
9331 Object visitThrowExpression(ThrowExpression node) {
9332 recordStaticType(node, _typeProvider.bottomType);
9333 return null;
9334 }
9335 Object visitVariableDeclaration(VariableDeclaration node) {
9336 Expression initializer = node.initializer;
9337 if (initializer != null) {
9338 Type2 rightType = initializer.bestType;
9339 SimpleIdentifier name = node.name;
9340 recordPropagatedType2(name, rightType);
9341 VariableElement element = name.staticElement as VariableElement;
9342 if (element != null) {
9343 _resolver.override2(element, rightType);
9344 }
9345 }
9346 return null;
9347 }
9348
9349 /**
9350 * Record that the static type of the given node is the type of the second arg ument to the method
9351 * represented by the given element.
9352 *
9353 * @param element the element representing the method invoked by the given nod e
9354 */
9355 Type2 computeArgumentType(ExecutableElement element) {
9356 if (element != null) {
9357 List<ParameterElement> parameters = element.parameters;
9358 if (parameters != null && parameters.length == 2) {
9359 return parameters[1].type;
9360 }
9361 }
9362 return _dynamicType;
9363 }
9364
9365 /**
9366 * Compute the propagated return type of the method or function represented by the given element.
9367 *
9368 * @param element the element representing the method or function invoked by t he given node
9369 * @return the propagated return type that was computed
9370 */
9371 Type2 computePropagatedReturnType(Element element) {
9372 if (element is ExecutableElement) {
9373 return _propagatedReturnTypes[element];
9374 }
9375 return null;
9376 }
9377
9378 /**
9379 * Given a function body, compute the propagated return type of the function. The propagated
9380 * return type of functions with a block body is the least upper bound of all
9381 * [ReturnStatement] expressions, with an expression body it is the type of th e expression.
9382 *
9383 * @param body the boy of the function whose propagated return type is to be c omputed
9384 * @return the propagated return type that was computed
9385 */
9386 Type2 computePropagatedReturnType2(FunctionBody body) {
9387 if (body is ExpressionFunctionBody) {
9388 ExpressionFunctionBody expressionBody = body as ExpressionFunctionBody;
9389 return expressionBody.expression.bestType;
9390 }
9391 if (body is BlockFunctionBody) {
9392 List<Type2> result = [null];
9393 body.accept(new GeneralizingASTVisitor_9(result));
9394 return result[0];
9395 }
9396 return null;
9397 }
9398
9399 /**
9400 * Compute the static return type of the method or function represented by the given element.
9401 *
9402 * @param element the element representing the method or function invoked by t he given node
9403 * @return the static return type that was computed
9404 */
9405 Type2 computeStaticReturnType(Element element) {
9406 if (element is PropertyAccessorElement) {
9407 FunctionType propertyType = ((element as PropertyAccessorElement)).type;
9408 if (propertyType != null) {
9409 Type2 returnType = propertyType.returnType;
9410 if (returnType.isDartCoreFunction) {
9411 return _dynamicType;
9412 } else if (returnType is InterfaceType) {
9413 MethodElement callMethod = ((returnType as InterfaceType)).lookUpMetho d(ElementResolver.CALL_METHOD_NAME, _resolver.definingLibrary);
9414 if (callMethod != null) {
9415 return callMethod.type.returnType;
9416 }
9417 } else if (returnType is FunctionType) {
9418 Type2 innerReturnType = ((returnType as FunctionType)).returnType;
9419 if (innerReturnType != null) {
9420 return innerReturnType;
9421 }
9422 }
9423 if (returnType != null) {
9424 return returnType;
9425 }
9426 }
9427 } else if (element is ExecutableElement) {
9428 FunctionType type = ((element as ExecutableElement)).type;
9429 if (type != null) {
9430 return type.returnType;
9431 }
9432 } else if (element is VariableElement) {
9433 VariableElement variable = element as VariableElement;
9434 Type2 variableType = _promoteManager.getStaticType(variable);
9435 if (variableType is FunctionType) {
9436 return ((variableType as FunctionType)).returnType;
9437 }
9438 }
9439 return _dynamicType;
9440 }
9441
9442 /**
9443 * Given a function declaration, compute the return static type of the functio n. The return type
9444 * of functions with a block body is `dynamicType`, with an expression body it is the type
9445 * of the expression.
9446 *
9447 * @param node the function expression whose static return type is to be compu ted
9448 * @return the static return type that was computed
9449 */
9450 Type2 computeStaticReturnType2(FunctionDeclaration node) {
9451 TypeName returnType = node.returnType;
9452 if (returnType == null) {
9453 return _dynamicType;
9454 }
9455 return returnType.type;
9456 }
9457
9458 /**
9459 * Given a function expression, compute the return type of the function. The r eturn type of
9460 * functions with a block body is `dynamicType`, with an expression body it is the type of
9461 * the expression.
9462 *
9463 * @param node the function expression whose return type is to be computed
9464 * @return the return type that was computed
9465 */
9466 Type2 computeStaticReturnType3(FunctionExpression node) {
9467 FunctionBody body = node.body;
9468 if (body is ExpressionFunctionBody) {
9469 return getStaticType(((body as ExpressionFunctionBody)).expression);
9470 }
9471 return _dynamicType;
9472 }
9473
9474 /**
9475 * If the given element name can be mapped to the name of a class defined with in the given
9476 * library, return the type specified by the argument.
9477 *
9478 * @param library the library in which the specified type would be defined
9479 * @param elementName the name of the element for which a type is being sought
9480 * @param nameMap an optional map used to map the element name to a type name
9481 * @return the type specified by the first argument in the argument list
9482 */
9483 Type2 getElementNameAsType(LibraryElement library, String elementName, Map<Str ing, String> nameMap) {
9484 if (elementName != null) {
9485 if (nameMap != null) {
9486 elementName = nameMap[elementName.toLowerCase()];
9487 }
9488 ClassElement returnType = library.getType(elementName);
9489 if (returnType != null) {
9490 return returnType.type;
9491 }
9492 }
9493 return null;
9494 }
9495
9496 /**
9497 * If the given argument list contains at least one argument, and if the argum ent is a simple
9498 * string literal, then parse that argument as a query string and return the t ype specified by the
9499 * argument.
9500 *
9501 * @param library the library in which the specified type would be defined
9502 * @param argumentList the list of arguments from which a type is to be extrac ted
9503 * @return the type specified by the first argument in the argument list
9504 */
9505 Type2 getFirstArgumentAsQuery(LibraryElement library, ArgumentList argumentLis t) {
9506 String argumentValue = getFirstArgumentAsString(argumentList);
9507 if (argumentValue != null) {
9508 if (argumentValue.contains(" ")) {
9509 return null;
9510 }
9511 String tag = argumentValue;
9512 tag = StringUtilities.substringBefore(tag, ":");
9513 tag = StringUtilities.substringBefore(tag, "[");
9514 tag = StringUtilities.substringBefore(tag, ".");
9515 tag = StringUtilities.substringBefore(tag, "#");
9516 tag = _HTML_ELEMENT_TO_CLASS_MAP[tag.toLowerCase()];
9517 ClassElement returnType = library.getType(tag);
9518 if (returnType != null) {
9519 return returnType.type;
9520 }
9521 }
9522 return null;
9523 }
9524
9525 /**
9526 * If the given argument list contains at least one argument, and if the argum ent is a simple
9527 * string literal, return the String value of the argument.
9528 *
9529 * @param argumentList the list of arguments from which a string value is to b e extracted
9530 * @return the string specified by the first argument in the argument list
9531 */
9532 String getFirstArgumentAsString(ArgumentList argumentList) {
9533 NodeList<Expression> arguments = argumentList.arguments;
9534 if (arguments.length > 0) {
9535 Expression argument = arguments[0];
9536 if (argument is SimpleStringLiteral) {
9537 return ((argument as SimpleStringLiteral)).value;
9538 }
9539 }
9540 return null;
9541 }
9542
9543 /**
9544 * If the given argument list contains at least one argument, and if the argum ent is a simple
9545 * string literal, and if the value of the argument is the name of a class def ined within the
9546 * given library, return the type specified by the argument.
9547 *
9548 * @param library the library in which the specified type would be defined
9549 * @param argumentList the list of arguments from which a type is to be extrac ted
9550 * @return the type specified by the first argument in the argument list
9551 */
9552 Type2 getFirstArgumentAsType(LibraryElement library, ArgumentList argumentList ) => getFirstArgumentAsType2(library, argumentList, null);
9553
9554 /**
9555 * If the given argument list contains at least one argument, and if the argum ent is a simple
9556 * string literal, and if the value of the argument is the name of a class def ined within the
9557 * given library, return the type specified by the argument.
9558 *
9559 * @param library the library in which the specified type would be defined
9560 * @param argumentList the list of arguments from which a type is to be extrac ted
9561 * @param nameMap an optional map used to map the element name to a type name
9562 * @return the type specified by the first argument in the argument list
9563 */
9564 Type2 getFirstArgumentAsType2(LibraryElement library, ArgumentList argumentLis t, Map<String, String> nameMap) => getElementNameAsType(library, getFirstArgumen tAsString(argumentList), nameMap);
9565
9566 /**
9567 * Return the static type of the given expression.
9568 *
9569 * @param expression the expression whose type is to be returned
9570 * @return the static type of the given expression
9571 */
9572 Type2 getStaticType(Expression expression) {
9573 Type2 type = expression.staticType;
9574 if (type == null) {
9575 return _dynamicType;
9576 }
9577 return type;
9578 }
9579
9580 /**
9581 * Return the type that should be recorded for a node that resolved to the giv en accessor.
9582 *
9583 * @param accessor the accessor that the node resolved to
9584 * @param context if the accessor element has context [by being the RHS of a
9585 * [PrefixedIdentifier] or [PropertyAccess]], and the return type of the
9586 * accessor is a parameter type, then the type of the LHS can be used to get more
9587 * specific type information
9588 * @return the type that should be recorded for a node that resolved to the gi ven accessor
9589 */
9590 Type2 getType(PropertyAccessorElement accessor, Type2 context) {
9591 FunctionType functionType = accessor.type;
9592 if (functionType == null) {
9593 return _dynamicType;
9594 }
9595 if (accessor.isSetter) {
9596 List<Type2> parameterTypes = functionType.normalParameterTypes;
9597 if (parameterTypes != null && parameterTypes.length > 0) {
9598 return parameterTypes[0];
9599 }
9600 PropertyAccessorElement getter = accessor.variable.getter;
9601 if (getter != null) {
9602 functionType = getter.type;
9603 if (functionType != null) {
9604 return functionType.returnType;
9605 }
9606 }
9607 return _dynamicType;
9608 }
9609 Type2 returnType = functionType.returnType;
9610 if (returnType is TypeParameterType && context is InterfaceType) {
9611 InterfaceType interfaceTypeContext = context as InterfaceType;
9612 List<TypeParameterElement> typeParameterElements = interfaceTypeContext.el ement != null ? interfaceTypeContext.element.typeParameters : null;
9613 if (typeParameterElements != null) {
9614 for (int i = 0; i < typeParameterElements.length; i++) {
9615 TypeParameterElement typeParameterElement = typeParameterElements[i];
9616 if (returnType.name == typeParameterElement.name) {
9617 return interfaceTypeContext.typeArguments[i];
9618 }
9619 }
9620 }
9621 }
9622 return returnType;
9623 }
9624
9625 /**
9626 * Return the type represented by the given type name.
9627 *
9628 * @param typeName the type name representing the type to be returned
9629 * @return the type represented by the type name
9630 */
9631 Type2 getType2(TypeName typeName) {
9632 Type2 type = typeName.type;
9633 if (type == null) {
9634 return _dynamicType;
9635 }
9636 return type;
9637 }
9638
9639 /**
9640 * Return `true` if the given [Type] is the `Future` form the 'dart:async'
9641 * library.
9642 */
9643 bool isAsyncFutureType(Type2 type) => type is InterfaceType && type.name == "F uture" && isAsyncLibrary(type.element.library);
9644
9645 /**
9646 * Return `true` if the given library is the 'dart:async' library.
9647 *
9648 * @param library the library being tested
9649 * @return `true` if the library is 'dart:async'
9650 */
9651 bool isAsyncLibrary(LibraryElement library) => library.name == "dart.async";
9652
9653 /**
9654 * Return `true` if the given library is the 'dart:html' library.
9655 *
9656 * @param library the library being tested
9657 * @return `true` if the library is 'dart:html'
9658 */
9659 bool isHtmlLibrary(LibraryElement library) => library != null && "dart.dom.htm l" == library.name;
9660
9661 /**
9662 * Return `true` if the given node is not a type literal.
9663 *
9664 * @param node the node being tested
9665 * @return `true` if the given node is not a type literal
9666 */
9667 bool isNotTypeLiteral(Identifier node) {
9668 ASTNode parent = node.parent;
9669 return parent is TypeName || (parent is PrefixedIdentifier && (parent.parent is TypeName || identical(((parent as PrefixedIdentifier)).prefix, node))) || (p arent is PropertyAccess && identical(((parent as PropertyAccess)).target, node)) || (parent is MethodInvocation && identical(node, ((parent as MethodInvocation) ).target));
9670 }
9671
9672 /**
9673 * Given a function element and its body, compute and record the propagated re turn type of the
9674 * function.
9675 *
9676 * @param functionElement the function element to record propagated return typ e for
9677 * @param body the boy of the function whose propagated return type is to be c omputed
9678 * @return the propagated return type that was computed, may be `null` if it i s not more
9679 * specific than the static return type.
9680 */
9681 void recordPropagatedType(ExecutableElement functionElement, FunctionBody body ) {
9682 Type2 propagatedReturnType = computePropagatedReturnType2(body);
9683 if (propagatedReturnType == null) {
9684 return;
9685 }
9686 if (propagatedReturnType.isBottom) {
9687 return;
9688 }
9689 Type2 staticReturnType = functionElement.returnType;
9690 if (!propagatedReturnType.isMoreSpecificThan(staticReturnType)) {
9691 return;
9692 }
9693 _propagatedReturnTypes[functionElement] = propagatedReturnType;
9694 }
9695
9696 /**
9697 * Record that the propagated type of the given node is the given type.
9698 *
9699 * @param expression the node whose type is to be recorded
9700 * @param type the propagated type of the node
9701 */
9702 void recordPropagatedType2(Expression expression, Type2 type) {
9703 if (type != null && !type.isDynamic) {
9704 expression.propagatedType = type;
9705 }
9706 }
9707
9708 /**
9709 * Record that the static type of the given node is the given type.
9710 *
9711 * @param expression the node whose type is to be recorded
9712 * @param type the static type of the node
9713 */
9714 void recordStaticType(Expression expression, Type2 type) {
9715 if (type == null) {
9716 expression.staticType = _dynamicType;
9717 } else {
9718 expression.staticType = type;
9719 }
9720 }
9721
9722 /**
9723 * Attempts to make a better guess for the static type of the given binary exp ression.
9724 *
9725 * @param node the binary expression to analyze
9726 * @param staticType the static type of the expression as resolved
9727 * @return the better type guess, or the same static type as given
9728 */
9729 Type2 refineBinaryExpressionType(BinaryExpression node, Type2 staticType) {
9730 sc.TokenType operator = node.operator.type;
9731 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)) {
9732 return _typeProvider.boolType;
9733 }
9734 Type2 intType = _typeProvider.intType;
9735 if (getStaticType(node.leftOperand) == intType) {
9736 if (identical(operator, sc.TokenType.MINUS) || identical(operator, sc.Toke nType.PERCENT) || identical(operator, sc.TokenType.PLUS) || identical(operator, sc.TokenType.STAR)) {
9737 Type2 doubleType = _typeProvider.doubleType;
9738 if (getStaticType(node.rightOperand) == doubleType) {
9739 return doubleType;
9740 }
9741 }
9742 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)) {
9743 if (getStaticType(node.rightOperand) == intType) {
9744 staticType = intType;
9745 }
9746 }
9747 }
9748 return staticType;
9749 }
9750 get thisType_J2DAccessor => _thisType;
9751 set thisType_J2DAccessor(__v) => _thisType = __v;
9752 }
9753 class GeneralizingASTVisitor_9 extends GeneralizingASTVisitor<Object> {
9754 List<Type2> result;
9755 GeneralizingASTVisitor_9(this.result) : super();
9756 Object visitExpression(Expression node) => null;
9757 Object visitReturnStatement(ReturnStatement node) {
9758 Type2 type;
9759 Expression expression = node.expression;
9760 if (expression != null) {
9761 type = expression.bestType;
9762 } else {
9763 type = BottomTypeImpl.instance;
9764 }
9765 if (result[0] == null) {
9766 result[0] = type;
9767 } else {
9768 result[0] = result[0].getLeastUpperBound(type);
9769 }
9770 return null;
9771 }
9772 }
9773 /**
9774 * Instances of this class manage the knowledge of what the set of subtypes are for a given type.
9775 */
9776 class SubtypeManager {
9777
9778 /**
9779 * A map between [ClassElement]s and a set of [ClassElement]s that are subtype s of the
9780 * key.
9781 */
9782 Map<ClassElement, Set<ClassElement>> _subtypeMap = new Map<ClassElement, Set<C lassElement>>();
9783
9784 /**
9785 * The set of all [LibraryElement]s that have been visited by the manager. Thi s is used both
9786 * to prevent infinite loops in the recursive methods, and also as a marker fo r the scope of the
9787 * libraries visited by this manager.
9788 */
9789 Set<LibraryElement> _visitedLibraries = new Set<LibraryElement>();
9790
9791 /**
9792 * Given some [ClassElement], return the set of all subtypes, and subtypes of subtypes.
9793 *
9794 * @param classElement the class to recursively return the set of subtypes of
9795 */
9796 Set<ClassElement> computeAllSubtypes(ClassElement classElement) {
9797 computeSubtypesInLibrary(classElement.library);
9798 Set<ClassElement> allSubtypes = new Set<ClassElement>();
9799 computeAllSubtypes2(classElement, new Set<ClassElement>(), allSubtypes);
9800 return allSubtypes;
9801 }
9802
9803 /**
9804 * Given some [LibraryElement], visit all of the types in the library, the pas sed library,
9805 * and any imported libraries, will be in the [visitedLibraries] set.
9806 *
9807 * @param libraryElement the library to visit, it it hasn't been visited alrea dy
9808 */
9809 void ensureLibraryVisited(LibraryElement libraryElement) {
9810 computeSubtypesInLibrary(libraryElement);
9811 }
9812
9813 /**
9814 * Given some [ClassElement] and a [HashSet<ClassElement>], this method recurs ively
9815 * adds all of the subtypes of the [ClassElement] to the passed array.
9816 *
9817 * @param classElement the type to compute the set of subtypes of
9818 * @param visitedClasses the set of class elements that this method has alread y recursively seen
9819 * @param allSubtypes the computed set of subtypes of the passed class element
9820 */
9821 void computeAllSubtypes2(ClassElement classElement, Set<ClassElement> visitedC lasses, Set<ClassElement> allSubtypes) {
9822 if (!javaSetAdd(visitedClasses, classElement)) {
9823 return;
9824 }
9825 Set<ClassElement> subtypes = _subtypeMap[classElement];
9826 if (subtypes == null) {
9827 return;
9828 }
9829 for (ClassElement subtype in subtypes) {
9830 computeAllSubtypes2(subtype, visitedClasses, allSubtypes);
9831 }
9832 allSubtypes.addAll(subtypes);
9833 }
9834
9835 /**
9836 * Given some [ClassElement], this method adds all of the pairs combinations o f itself and
9837 * all of its supertypes to the [subtypeMap] map.
9838 *
9839 * @param classElement the class element
9840 */
9841 void computeSubtypesInClass(ClassElement classElement) {
9842 InterfaceType supertypeType = classElement.supertype;
9843 if (supertypeType != null) {
9844 ClassElement supertypeElement = supertypeType.element;
9845 if (supertypeElement != null) {
9846 putInSubtypeMap(supertypeElement, classElement);
9847 }
9848 }
9849 List<InterfaceType> interfaceTypes = classElement.interfaces;
9850 for (InterfaceType interfaceType in interfaceTypes) {
9851 ClassElement interfaceElement = interfaceType.element;
9852 if (interfaceElement != null) {
9853 putInSubtypeMap(interfaceElement, classElement);
9854 }
9855 }
9856 List<InterfaceType> mixinTypes = classElement.mixins;
9857 for (InterfaceType mixinType in mixinTypes) {
9858 ClassElement mixinElement = mixinType.element;
9859 if (mixinElement != null) {
9860 putInSubtypeMap(mixinElement, classElement);
9861 }
9862 }
9863 }
9864
9865 /**
9866 * Given some [CompilationUnitElement], this method calls
9867 * [computeAllSubtypes] on all of the [ClassElement]s in the
9868 * compilation unit.
9869 *
9870 * @param unitElement the compilation unit element
9871 */
9872 void computeSubtypesInCompilationUnit(CompilationUnitElement unitElement) {
9873 List<ClassElement> classElements = unitElement.types;
9874 for (ClassElement classElement in classElements) {
9875 computeSubtypesInClass(classElement);
9876 }
9877 }
9878
9879 /**
9880 * Given some [LibraryElement], this method calls
9881 * [computeAllSubtypes] on all of the [ClassElement]s in the
9882 * compilation unit, and itself for all imported and exported libraries. All v isited libraries are
9883 * added to the [visitedLibraries] set.
9884 *
9885 * @param libraryElement the library element
9886 */
9887 void computeSubtypesInLibrary(LibraryElement libraryElement) {
9888 if (libraryElement == null || _visitedLibraries.contains(libraryElement)) {
9889 return;
9890 }
9891 javaSetAdd(_visitedLibraries, libraryElement);
9892 computeSubtypesInCompilationUnit(libraryElement.definingCompilationUnit);
9893 List<CompilationUnitElement> parts = libraryElement.parts;
9894 for (CompilationUnitElement part in parts) {
9895 computeSubtypesInCompilationUnit(part);
9896 }
9897 List<LibraryElement> imports = libraryElement.importedLibraries;
9898 for (LibraryElement importElt in imports) {
9899 computeSubtypesInLibrary(importElt.library);
9900 }
9901 List<LibraryElement> exports = libraryElement.exportedLibraries;
9902 for (LibraryElement exportElt in exports) {
9903 computeSubtypesInLibrary(exportElt.library);
9904 }
9905 }
9906
9907 /**
9908 * Add some key/ value pair into the [subtypeMap] map.
9909 *
9910 * @param supertypeElement the key for the [subtypeMap] map
9911 * @param subtypeElement the value for the [subtypeMap] map
9912 */
9913 void putInSubtypeMap(ClassElement supertypeElement, ClassElement subtypeElemen t) {
9914 Set<ClassElement> subtypes = _subtypeMap[supertypeElement];
9915 if (subtypes == null) {
9916 subtypes = new Set<ClassElement>();
9917 _subtypeMap[supertypeElement] = subtypes;
9918 }
9919 javaSetAdd(subtypes, subtypeElement);
9920 }
9921 }
9922 /**
9923 * Instances of the class `TypeOverrideManager` manage the ability to override t he type of an
9924 * element within a given context.
9925 */
9926 class TypeOverrideManager {
9927
9928 /**
9929 * The current override scope, or `null` if no scope has been entered.
9930 */
9931 TypeOverrideManager_TypeOverrideScope _currentScope;
9932
9933 /**
9934 * Apply a set of overrides that were previously captured.
9935 *
9936 * @param overrides the overrides to be applied
9937 */
9938 void applyOverrides(Map<Element, Type2> overrides) {
9939 if (_currentScope == null) {
9940 throw new IllegalStateException("Cannot apply overrides without a scope");
9941 }
9942 _currentScope.applyOverrides(overrides);
9943 }
9944
9945 /**
9946 * Return a table mapping the elements whose type is overridden in the current scope to the
9947 * overriding type.
9948 *
9949 * @return the overrides in the current scope
9950 */
9951 Map<Element, Type2> captureLocalOverrides() {
9952 if (_currentScope == null) {
9953 throw new IllegalStateException("Cannot capture local overrides without a scope");
9954 }
9955 return _currentScope.captureLocalOverrides();
9956 }
9957
9958 /**
9959 * Return a map from the elements for the variables in the given list that hav e their types
9960 * overridden to the overriding type.
9961 *
9962 * @param variableList the list of variables whose overriding types are to be captured
9963 * @return a table mapping elements to their overriding types
9964 */
9965 Map<Element, Type2> captureOverrides(VariableDeclarationList variableList) {
9966 if (_currentScope == null) {
9967 throw new IllegalStateException("Cannot capture overrides without a scope" );
9968 }
9969 return _currentScope.captureOverrides(variableList);
9970 }
9971
9972 /**
9973 * Enter a new override scope.
9974 */
9975 void enterScope() {
9976 _currentScope = new TypeOverrideManager_TypeOverrideScope(_currentScope);
9977 }
9978
9979 /**
9980 * Exit the current override scope.
9981 */
9982 void exitScope() {
9983 if (_currentScope == null) {
9984 throw new IllegalStateException("No scope to exit");
9985 }
9986 _currentScope = _currentScope._outerScope;
9987 }
9988
9989 /**
9990 * Return the overridden type of the given element, or `null` if the type of t he element has
9991 * not been overridden.
9992 *
9993 * @param element the element whose type might have been overridden
9994 * @return the overridden type of the given element
9995 */
9996 Type2 getType(Element element) {
9997 if (_currentScope == null) {
9998 return null;
9999 }
10000 return _currentScope.getType(element);
10001 }
10002
10003 /**
10004 * Set the overridden type of the given element to the given type
10005 *
10006 * @param element the element whose type might have been overridden
10007 * @param type the overridden type of the given element
10008 */
10009 void setType(Element element, Type2 type) {
10010 if (_currentScope == null) {
10011 throw new IllegalStateException("Cannot override without a scope");
10012 }
10013 _currentScope.setType(element, type);
10014 }
10015 }
10016 /**
10017 * Instances of the class `TypeOverrideScope` represent a scope in which the typ es of
10018 * elements can be overridden.
10019 */
10020 class TypeOverrideManager_TypeOverrideScope {
10021
10022 /**
10023 * The outer scope in which types might be overridden.
10024 */
10025 TypeOverrideManager_TypeOverrideScope _outerScope;
10026
10027 /**
10028 * A table mapping elements to the overridden type of that element.
10029 */
10030 Map<Element, Type2> _overridenTypes = new Map<Element, Type2>();
10031
10032 /**
10033 * Initialize a newly created scope to be an empty child of the given scope.
10034 *
10035 * @param outerScope the outer scope in which types might be overridden
10036 */
10037 TypeOverrideManager_TypeOverrideScope(TypeOverrideManager_TypeOverrideScope ou terScope) {
10038 this._outerScope = outerScope;
10039 }
10040
10041 /**
10042 * Apply a set of overrides that were previously captured.
10043 *
10044 * @param overrides the overrides to be applied
10045 */
10046 void applyOverrides(Map<Element, Type2> overrides) {
10047 for (MapEntry<Element, Type2> entry in getMapEntrySet(overrides)) {
10048 _overridenTypes[entry.getKey()] = entry.getValue();
10049 }
10050 }
10051
10052 /**
10053 * Return a table mapping the elements whose type is overridden in the current scope to the
10054 * overriding type.
10055 *
10056 * @return the overrides in the current scope
10057 */
10058 Map<Element, Type2> captureLocalOverrides() => _overridenTypes;
10059
10060 /**
10061 * Return a map from the elements for the variables in the given list that hav e their types
10062 * overridden to the overriding type.
10063 *
10064 * @param variableList the list of variables whose overriding types are to be captured
10065 * @return a table mapping elements to their overriding types
10066 */
10067 Map<Element, Type2> captureOverrides(VariableDeclarationList variableList) {
10068 Map<Element, Type2> overrides = new Map<Element, Type2>();
10069 if (variableList.isConst || variableList.isFinal) {
10070 for (VariableDeclaration variable in variableList.variables) {
10071 Element element = variable.element;
10072 if (element != null) {
10073 Type2 type = _overridenTypes[element];
10074 if (type != null) {
10075 overrides[element] = type;
10076 }
10077 }
10078 }
10079 }
10080 return overrides;
10081 }
10082
10083 /**
10084 * Return the overridden type of the given element, or `null` if the type of t he element
10085 * has not been overridden.
10086 *
10087 * @param element the element whose type might have been overridden
10088 * @return the overridden type of the given element
10089 */
10090 Type2 getType(Element element) {
10091 Type2 type = _overridenTypes[element];
10092 if (type == null && element is PropertyAccessorElement) {
10093 type = _overridenTypes[((element as PropertyAccessorElement)).variable];
10094 }
10095 if (type != null) {
10096 return type;
10097 } else if (_outerScope != null) {
10098 return _outerScope.getType(element);
10099 }
10100 return null;
10101 }
10102
10103 /**
10104 * Set the overridden type of the given element to the given type
10105 *
10106 * @param element the element whose type might have been overridden
10107 * @param type the overridden type of the given element
10108 */
10109 void setType(Element element, Type2 type) {
10110 _overridenTypes[element] = type;
10111 }
10112 }
10113 /**
10114 * Instances of the class `TypePromotionManager` manage the ability to promote t ypes of local
10115 * variables and formal parameters from their declared types based on control fl ow.
10116 */
10117 class TypePromotionManager {
10118
10119 /**
10120 * The current promotion scope, or `null` if no scope has been entered.
10121 */
10122 TypePromotionManager_TypePromoteScope _currentScope;
10123
10124 /**
10125 * Enter a new promotions scope.
10126 */
10127 void enterScope() {
10128 _currentScope = new TypePromotionManager_TypePromoteScope(_currentScope);
10129 }
10130
10131 /**
10132 * Exit the current promotion scope.
10133 */
10134 void exitScope() {
10135 if (_currentScope == null) {
10136 throw new IllegalStateException("No scope to exit");
10137 }
10138 _currentScope = _currentScope._outerScope;
10139 }
10140
10141 /**
10142 * Returns the elements with promoted types.
10143 */
10144 Iterable<Element> get promotedElements => _currentScope.promotedElements;
10145
10146 /**
10147 * Returns static type of the given variable - declared or promoted.
10148 *
10149 * @return the static type of the given variable - declared or promoted
10150 */
10151 Type2 getStaticType(VariableElement variable) {
10152 Type2 staticType = getType(variable);
10153 if (staticType == null) {
10154 staticType = variable.type;
10155 }
10156 return staticType;
10157 }
10158
10159 /**
10160 * Return the promoted type of the given element, or `null` if the type of the element has
10161 * not been promoted.
10162 *
10163 * @param element the element whose type might have been promoted
10164 * @return the promoted type of the given element
10165 */
10166 Type2 getType(Element element) {
10167 if (_currentScope == null) {
10168 return null;
10169 }
10170 return _currentScope.getType(element);
10171 }
10172
10173 /**
10174 * Set the promoted type of the given element to the given type.
10175 *
10176 * @param element the element whose type might have been promoted
10177 * @param type the promoted type of the given element
10178 */
10179 void setType(Element element, Type2 type) {
10180 if (_currentScope == null) {
10181 throw new IllegalStateException("Cannot promote without a scope");
10182 }
10183 _currentScope.setType(element, type);
10184 }
10185 }
10186 /**
10187 * Instances of the class `TypePromoteScope` represent a scope in which the type s of
10188 * elements can be promoted.
10189 */
10190 class TypePromotionManager_TypePromoteScope {
10191
10192 /**
10193 * The outer scope in which types might be promoter.
10194 */
10195 TypePromotionManager_TypePromoteScope _outerScope;
10196
10197 /**
10198 * A table mapping elements to the promoted type of that element.
10199 */
10200 Map<Element, Type2> _promotedTypes = new Map<Element, Type2>();
10201
10202 /**
10203 * Initialize a newly created scope to be an empty child of the given scope.
10204 *
10205 * @param outerScope the outer scope in which types might be promoted
10206 */
10207 TypePromotionManager_TypePromoteScope(TypePromotionManager_TypePromoteScope ou terScope) {
10208 this._outerScope = outerScope;
10209 }
10210
10211 /**
10212 * Returns the elements with promoted types.
10213 */
10214 Iterable<Element> get promotedElements => _promotedTypes.keys.toSet();
10215
10216 /**
10217 * Return the promoted type of the given element, or `null` if the type of the element has
10218 * not been promoted.
10219 *
10220 * @param element the element whose type might have been promoted
10221 * @return the promoted type of the given element
10222 */
10223 Type2 getType(Element element) {
10224 Type2 type = _promotedTypes[element];
10225 if (type == null && element is PropertyAccessorElement) {
10226 type = _promotedTypes[((element as PropertyAccessorElement)).variable];
10227 }
10228 if (type != null) {
10229 return type;
10230 } else if (_outerScope != null) {
10231 return _outerScope.getType(element);
10232 }
10233 return null;
10234 }
10235
10236 /**
10237 * Set the promoted type of the given element to the given type.
10238 *
10239 * @param element the element whose type might have been promoted
10240 * @param type the promoted type of the given element
10241 */
10242 void setType(Element element, Type2 type) {
10243 _promotedTypes[element] = type;
10244 }
10245 }
10246 /**
10247 * The interface `TypeProvider` defines the behavior of objects that provide acc ess to types
10248 * defined by the language.
10249 *
10250 * @coverage dart.engine.resolver
10251 */
10252 abstract class TypeProvider {
10253
10254 /**
10255 * Return the type representing the built-in type 'Null'.
10256 *
10257 * @return the type representing the built-in type 'null'
10258 */
10259 InterfaceType get nullType;
10260
10261 /**
10262 * Return the type representing the built-in type 'bool'.
10263 *
10264 * @return the type representing the built-in type 'bool'
10265 */
10266 InterfaceType get boolType;
10267
10268 /**
10269 * Return the type representing the type 'bottom'.
10270 *
10271 * @return the type representing the type 'bottom'
10272 */
10273 Type2 get bottomType;
10274
10275 /**
10276 * Return the type representing the built-in type 'double'.
10277 *
10278 * @return the type representing the built-in type 'double'
10279 */
10280 InterfaceType get doubleType;
10281
10282 /**
10283 * Return the type representing the built-in type 'dynamic'.
10284 *
10285 * @return the type representing the built-in type 'dynamic'
10286 */
10287 Type2 get dynamicType;
10288
10289 /**
10290 * Return the type representing the built-in type 'Function'.
10291 *
10292 * @return the type representing the built-in type 'Function'
10293 */
10294 InterfaceType get functionType;
10295
10296 /**
10297 * Return the type representing the built-in type 'int'.
10298 *
10299 * @return the type representing the built-in type 'int'
10300 */
10301 InterfaceType get intType;
10302
10303 /**
10304 * Return the type representing the built-in type 'List'.
10305 *
10306 * @return the type representing the built-in type 'List'
10307 */
10308 InterfaceType get listType;
10309
10310 /**
10311 * Return the type representing the built-in type 'Map'.
10312 *
10313 * @return the type representing the built-in type 'Map'
10314 */
10315 InterfaceType get mapType;
10316
10317 /**
10318 * Return the type representing the built-in type 'num'.
10319 *
10320 * @return the type representing the built-in type 'num'
10321 */
10322 InterfaceType get numType;
10323
10324 /**
10325 * Return the type representing the built-in type 'Object'.
10326 *
10327 * @return the type representing the built-in type 'Object'
10328 */
10329 InterfaceType get objectType;
10330
10331 /**
10332 * Return the type representing the built-in type 'StackTrace'.
10333 *
10334 * @return the type representing the built-in type 'StackTrace'
10335 */
10336 InterfaceType get stackTraceType;
10337
10338 /**
10339 * Return the type representing the built-in type 'String'.
10340 *
10341 * @return the type representing the built-in type 'String'
10342 */
10343 InterfaceType get stringType;
10344
10345 /**
10346 * Return the type representing the built-in type 'Symbol'.
10347 *
10348 * @return the type representing the built-in type 'Symbol'
10349 */
10350 InterfaceType get symbolType;
10351
10352 /**
10353 * Return the type representing the built-in type 'Type'.
10354 *
10355 * @return the type representing the built-in type 'Type'
10356 */
10357 InterfaceType get typeType;
10358 }
10359 /**
10360 * Instances of the class `TypeProviderImpl` provide access to types defined by the language
10361 * by looking for those types in the element model for the core library.
10362 *
10363 * @coverage dart.engine.resolver
10364 */
10365 class TypeProviderImpl implements TypeProvider {
10366
10367 /**
10368 * The type representing the built-in type 'bool'.
10369 */
10370 InterfaceType _boolType;
10371
10372 /**
10373 * The type representing the type 'bottom'.
10374 */
10375 Type2 _bottomType;
10376
10377 /**
10378 * The type representing the built-in type 'double'.
10379 */
10380 InterfaceType _doubleType;
10381
10382 /**
10383 * The type representing the built-in type 'dynamic'.
10384 */
10385 Type2 _dynamicType;
10386
10387 /**
10388 * The type representing the built-in type 'Function'.
10389 */
10390 InterfaceType _functionType;
10391
10392 /**
10393 * The type representing the built-in type 'int'.
10394 */
10395 InterfaceType _intType;
10396
10397 /**
10398 * The type representing the built-in type 'List'.
10399 */
10400 InterfaceType _listType;
10401
10402 /**
10403 * The type representing the built-in type 'Map'.
10404 */
10405 InterfaceType _mapType;
10406
10407 /**
10408 * The type representing the type 'Null'.
10409 */
10410 InterfaceType _nullType;
10411
10412 /**
10413 * The type representing the built-in type 'num'.
10414 */
10415 InterfaceType _numType;
10416
10417 /**
10418 * The type representing the built-in type 'Object'.
10419 */
10420 InterfaceType _objectType;
10421
10422 /**
10423 * The type representing the built-in type 'StackTrace'.
10424 */
10425 InterfaceType _stackTraceType;
10426
10427 /**
10428 * The type representing the built-in type 'String'.
10429 */
10430 InterfaceType _stringType;
10431
10432 /**
10433 * The type representing the built-in type 'Symbol'.
10434 */
10435 InterfaceType _symbolType;
10436
10437 /**
10438 * The type representing the built-in type 'Type'.
10439 */
10440 InterfaceType _typeType;
10441
10442 /**
10443 * Initialize a newly created type provider to provide the types defined in th e given library.
10444 *
10445 * @param coreLibrary the element representing the core library (dart:core).
10446 */
10447 TypeProviderImpl(LibraryElement coreLibrary) {
10448 initializeFrom(coreLibrary);
10449 }
10450 InterfaceType get boolType => _boolType;
10451 Type2 get bottomType => _bottomType;
10452 InterfaceType get doubleType => _doubleType;
10453 Type2 get dynamicType => _dynamicType;
10454 InterfaceType get functionType => _functionType;
10455 InterfaceType get intType => _intType;
10456 InterfaceType get listType => _listType;
10457 InterfaceType get mapType => _mapType;
10458 InterfaceType get nullType => _nullType;
10459 InterfaceType get numType => _numType;
10460 InterfaceType get objectType => _objectType;
10461 InterfaceType get stackTraceType => _stackTraceType;
10462 InterfaceType get stringType => _stringType;
10463 InterfaceType get symbolType => _symbolType;
10464 InterfaceType get typeType => _typeType;
10465
10466 /**
10467 * Return the type with the given name from the given namespace, or `null` if there is no
10468 * class with the given name.
10469 *
10470 * @param namespace the namespace in which to search for the given name
10471 * @param typeName the name of the type being searched for
10472 * @return the type that was found
10473 */
10474 InterfaceType getType(Namespace namespace, String typeName) {
10475 Element element = namespace.get(typeName);
10476 if (element == null) {
10477 AnalysisEngine.instance.logger.logInformation("No definition of type ${typ eName}");
10478 return null;
10479 }
10480 return ((element as ClassElement)).type;
10481 }
10482
10483 /**
10484 * Initialize the types provided by this type provider from the given library.
10485 *
10486 * @param library the library containing the definitions of the core types
10487 */
10488 void initializeFrom(LibraryElement library) {
10489 Namespace namespace = new NamespaceBuilder().createPublicNamespace(library);
10490 _boolType = getType(namespace, "bool");
10491 _bottomType = BottomTypeImpl.instance;
10492 _doubleType = getType(namespace, "double");
10493 _dynamicType = DynamicTypeImpl.instance;
10494 _functionType = getType(namespace, "Function");
10495 _intType = getType(namespace, "int");
10496 _listType = getType(namespace, "List");
10497 _mapType = getType(namespace, "Map");
10498 _nullType = getType(namespace, "Null");
10499 _numType = getType(namespace, "num");
10500 _objectType = getType(namespace, "Object");
10501 _stackTraceType = getType(namespace, "StackTrace");
10502 _stringType = getType(namespace, "String");
10503 _symbolType = getType(namespace, "Symbol");
10504 _typeType = getType(namespace, "Type");
10505 }
10506 }
10507 /**
10508 * Instances of the class `TypeResolverVisitor` are used to resolve the types as sociated with
10509 * the elements in the element model. This includes the types of superclasses, m ixins, interfaces,
10510 * fields, methods, parameters, and local variables. As a side-effect, this also finishes building
10511 * the type hierarchy.
10512 *
10513 * @coverage dart.engine.resolver
10514 */
10515 class TypeResolverVisitor extends ScopedVisitor {
10516
10517 /**
10518 * @return `true` if the name of the given [TypeName] is an built-in identifie r.
10519 */
10520 static bool isBuiltInIdentifier(TypeName node) {
10521 sc.Token token = node.name.beginToken;
10522 return identical(token.type, sc.TokenType.KEYWORD);
10523 }
10524
10525 /**
10526 * @return `true` if given [TypeName] is used as a type annotation.
10527 */
10528 static bool isTypeAnnotation(TypeName node) {
10529 ASTNode parent = node.parent;
10530 if (parent is VariableDeclarationList) {
10531 return identical(((parent as VariableDeclarationList)).type, node);
10532 }
10533 if (parent is FieldFormalParameter) {
10534 return identical(((parent as FieldFormalParameter)).type, node);
10535 }
10536 if (parent is SimpleFormalParameter) {
10537 return identical(((parent as SimpleFormalParameter)).type, node);
10538 }
10539 return false;
10540 }
10541
10542 /**
10543 * The type representing the type 'dynamic'.
10544 */
10545 Type2 _dynamicType;
10546
10547 /**
10548 * The flag specifying if currently visited class references 'super' expressio n.
10549 */
10550 bool _hasReferenceToSuper = false;
10551
10552 /**
10553 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
10554 *
10555 * @param library the library containing the compilation unit being resolved
10556 * @param source the source representing the compilation unit being visited
10557 * @param typeProvider the object used to access the types from the core libra ry
10558 */
10559 TypeResolverVisitor.con1(Library library, Source source, TypeProvider typeProv ider) : super.con1(library, source, typeProvider) {
10560 _dynamicType = typeProvider.dynamicType;
10561 }
10562
10563 /**
10564 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
10565 *
10566 * @param definingLibrary the element for the library containing the compilati on unit being
10567 * visited
10568 * @param source the source representing the compilation unit being visited
10569 * @param typeProvider the object used to access the types from the core libra ry
10570 * @param errorListener the error listener that will be informed of any errors that are found
10571 * during resolution
10572 */
10573 TypeResolverVisitor.con2(LibraryElement definingLibrary, Source source, TypePr ovider typeProvider, AnalysisErrorListener errorListener) : super.con2(definingL ibrary, source, typeProvider, errorListener) {
10574 _dynamicType = typeProvider.dynamicType;
10575 }
10576 Object visitCatchClause(CatchClause node) {
10577 super.visitCatchClause(node);
10578 SimpleIdentifier exception = node.exceptionParameter;
10579 if (exception != null) {
10580 TypeName exceptionTypeName = node.exceptionType;
10581 Type2 exceptionType;
10582 if (exceptionTypeName == null) {
10583 exceptionType = typeProvider.dynamicType;
10584 } else {
10585 exceptionType = getType3(exceptionTypeName);
10586 }
10587 recordType(exception, exceptionType);
10588 Element element = exception.staticElement;
10589 if (element is VariableElementImpl) {
10590 ((element as VariableElementImpl)).type = exceptionType;
10591 } else {
10592 }
10593 }
10594 SimpleIdentifier stackTrace = node.stackTraceParameter;
10595 if (stackTrace != null) {
10596 recordType(stackTrace, typeProvider.stackTraceType);
10597 }
10598 return null;
10599 }
10600 Object visitClassDeclaration(ClassDeclaration node) {
10601 _hasReferenceToSuper = false;
10602 super.visitClassDeclaration(node);
10603 ClassElementImpl classElement = getClassElement(node.name);
10604 InterfaceType superclassType = null;
10605 ExtendsClause extendsClause = node.extendsClause;
10606 if (extendsClause != null) {
10607 ErrorCode errorCode = (node.withClause == null ? CompileTimeErrorCode.EXTE NDS_NON_CLASS : CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS) as ErrorCo de;
10608 superclassType = resolveType(extendsClause.superclass, errorCode, errorCod e);
10609 if (superclassType != typeProvider.objectType) {
10610 classElement.validMixin = false;
10611 }
10612 }
10613 if (classElement != null) {
10614 if (superclassType == null) {
10615 InterfaceType objectType = typeProvider.objectType;
10616 if (classElement.type != objectType) {
10617 superclassType = objectType;
10618 }
10619 }
10620 classElement.supertype = superclassType;
10621 classElement.hasReferenceToSuper2 = _hasReferenceToSuper;
10622 }
10623 resolve(classElement, node.withClause, node.implementsClause);
10624 return null;
10625 }
10626 Object visitClassTypeAlias(ClassTypeAlias node) {
10627 super.visitClassTypeAlias(node);
10628 ClassElementImpl classElement = getClassElement(node.name);
10629 ErrorCode errorCode = CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS;
10630 InterfaceType superclassType = resolveType(node.superclass, errorCode, error Code);
10631 if (superclassType == null) {
10632 superclassType = typeProvider.objectType;
10633 }
10634 if (classElement != null && superclassType != null) {
10635 classElement.supertype = superclassType;
10636 }
10637 resolve(classElement, node.withClause, node.implementsClause);
10638 return null;
10639 }
10640 Object visitConstructorDeclaration(ConstructorDeclaration node) {
10641 super.visitConstructorDeclaration(node);
10642 ExecutableElementImpl element = node.element as ExecutableElementImpl;
10643 ClassElement definingClass = element.enclosingElement as ClassElement;
10644 element.returnType = definingClass.type;
10645 FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
10646 type.typeArguments = definingClass.type.typeArguments;
10647 element.type = type;
10648 return null;
10649 }
10650 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
10651 super.visitDeclaredIdentifier(node);
10652 Type2 declaredType;
10653 TypeName typeName = node.type;
10654 if (typeName == null) {
10655 declaredType = _dynamicType;
10656 } else {
10657 declaredType = getType3(typeName);
10658 }
10659 LocalVariableElementImpl element = node.element as LocalVariableElementImpl;
10660 element.type = declaredType;
10661 return null;
10662 }
10663 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
10664 super.visitDefaultFormalParameter(node);
10665 return null;
10666 }
10667 Object visitFieldFormalParameter(FieldFormalParameter node) {
10668 super.visitFieldFormalParameter(node);
10669 Element element = node.identifier.staticElement;
10670 if (element is ParameterElementImpl) {
10671 ParameterElementImpl parameter = element as ParameterElementImpl;
10672 FormalParameterList parameterList = node.parameters;
10673 if (parameterList == null) {
10674 Type2 type;
10675 TypeName typeName = node.type;
10676 if (typeName == null) {
10677 type = _dynamicType;
10678 } else {
10679 type = getType3(typeName);
10680 }
10681 parameter.type = type;
10682 } else {
10683 setFunctionTypedParameterType(parameter, node.type, node.parameters);
10684 }
10685 } else {
10686 }
10687 return null;
10688 }
10689 Object visitFunctionDeclaration(FunctionDeclaration node) {
10690 super.visitFunctionDeclaration(node);
10691 ExecutableElementImpl element = node.element as ExecutableElementImpl;
10692 element.returnType = computeReturnType(node.returnType);
10693 FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
10694 ClassElement definingClass = element.getAncestor(ClassElement);
10695 if (definingClass != null) {
10696 type.typeArguments = definingClass.type.typeArguments;
10697 }
10698 element.type = type;
10699 return null;
10700 }
10701 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
10702 super.visitFunctionTypeAlias(node);
10703 FunctionTypeAliasElementImpl element = node.element as FunctionTypeAliasElem entImpl;
10704 element.returnType = computeReturnType(node.returnType);
10705 return null;
10706 }
10707 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
10708 super.visitFunctionTypedFormalParameter(node);
10709 Element element = node.identifier.staticElement;
10710 if (element is ParameterElementImpl) {
10711 setFunctionTypedParameterType(element as ParameterElementImpl, node.return Type, node.parameters);
10712 } else {
10713 }
10714 return null;
10715 }
10716 Object visitMethodDeclaration(MethodDeclaration node) {
10717 super.visitMethodDeclaration(node);
10718 ExecutableElementImpl element = node.element as ExecutableElementImpl;
10719 element.returnType = computeReturnType(node.returnType);
10720 FunctionTypeImpl type = new FunctionTypeImpl.con1(element);
10721 ClassElement definingClass = element.getAncestor(ClassElement);
10722 if (definingClass != null) {
10723 type.typeArguments = definingClass.type.typeArguments;
10724 }
10725 element.type = type;
10726 if (element is PropertyAccessorElement) {
10727 PropertyAccessorElement accessor = element as PropertyAccessorElement;
10728 PropertyInducingElementImpl variable = accessor.variable as PropertyInduci ngElementImpl;
10729 if (accessor.isGetter) {
10730 variable.type = type.returnType;
10731 } else if (variable.type == null) {
10732 List<Type2> parameterTypes = type.normalParameterTypes;
10733 if (parameterTypes != null && parameterTypes.length > 0) {
10734 variable.type = parameterTypes[0];
10735 }
10736 }
10737 }
10738 return null;
10739 }
10740 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
10741 super.visitSimpleFormalParameter(node);
10742 Type2 declaredType;
10743 TypeName typeName = node.type;
10744 if (typeName == null) {
10745 declaredType = _dynamicType;
10746 } else {
10747 declaredType = getType3(typeName);
10748 }
10749 Element element = node.identifier.staticElement;
10750 if (element is ParameterElement) {
10751 ((element as ParameterElementImpl)).type = declaredType;
10752 } else {
10753 }
10754 return null;
10755 }
10756 Object visitSuperExpression(SuperExpression node) {
10757 _hasReferenceToSuper = true;
10758 return super.visitSuperExpression(node);
10759 }
10760 Object visitTypeName(TypeName node) {
10761 super.visitTypeName(node);
10762 Identifier typeName = node.name;
10763 TypeArgumentList argumentList = node.typeArguments;
10764 Element element = nameScope.lookup(typeName, definingLibrary);
10765 if (element == null) {
10766 if (typeName.name == this._dynamicType.name) {
10767 setElement(typeName, this._dynamicType.element);
10768 if (argumentList != null) {
10769 }
10770 typeName.staticType = this._dynamicType;
10771 node.type = this._dynamicType;
10772 return null;
10773 }
10774 VoidTypeImpl voidType = VoidTypeImpl.instance;
10775 if (typeName.name == voidType.name) {
10776 if (argumentList != null) {
10777 }
10778 typeName.staticType = voidType;
10779 node.type = voidType;
10780 return null;
10781 }
10782 ASTNode parent = node.parent;
10783 if (typeName is PrefixedIdentifier && parent is ConstructorName && argumen tList == null) {
10784 ConstructorName name = parent as ConstructorName;
10785 if (name.name == null) {
10786 PrefixedIdentifier prefixedIdentifier = typeName as PrefixedIdentifier ;
10787 SimpleIdentifier prefix = prefixedIdentifier.prefix;
10788 element = nameScope.lookup(prefix, definingLibrary);
10789 if (element is PrefixElement) {
10790 if (parent.parent is InstanceCreationExpression && ((parent.parent a s InstanceCreationExpression)).isConst) {
10791 reportError5(CompileTimeErrorCode.CONST_WITH_NON_TYPE, prefixedIde ntifier.identifier, [prefixedIdentifier.identifier.name]);
10792 } else {
10793 reportError5(StaticWarningCode.NEW_WITH_NON_TYPE, prefixedIdentifi er.identifier, [prefixedIdentifier.identifier.name]);
10794 }
10795 setElement(prefix, element);
10796 return null;
10797 } else if (element != null) {
10798 name.name = prefixedIdentifier.identifier;
10799 name.period = prefixedIdentifier.period;
10800 node.name = prefix;
10801 typeName = prefix;
10802 }
10803 }
10804 }
10805 }
10806 bool elementValid = element is! MultiplyDefinedElement;
10807 if (elementValid && element is! ClassElement && isTypeNameInInstanceCreation Expression(node)) {
10808 SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName);
10809 InstanceCreationExpression creation = node.parent.parent as InstanceCreati onExpression;
10810 if (creation.isConst) {
10811 if (element == null) {
10812 reportError5(CompileTimeErrorCode.UNDEFINED_CLASS, typeNameSimple, [ty peName]);
10813 } else {
10814 reportError5(CompileTimeErrorCode.CONST_WITH_NON_TYPE, typeNameSimple, [typeName]);
10815 }
10816 elementValid = false;
10817 } else {
10818 if (element != null) {
10819 reportError5(StaticWarningCode.NEW_WITH_NON_TYPE, typeNameSimple, [typ eName]);
10820 elementValid = false;
10821 }
10822 }
10823 }
10824 if (elementValid && element == null) {
10825 SimpleIdentifier typeNameSimple = getTypeSimpleIdentifier(typeName);
10826 if (isBuiltInIdentifier(node) && isTypeAnnotation(node)) {
10827 reportError5(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE, typeName, [typeName.name]);
10828 } else if (typeNameSimple.name == "boolean") {
10829 reportError5(StaticWarningCode.UNDEFINED_CLASS_BOOLEAN, typeNameSimple, []);
10830 } else if (isTypeNameInCatchClause(node)) {
10831 reportError5(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName, [type Name.name]);
10832 } else if (isTypeNameInAsExpression(node)) {
10833 reportError5(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.nam e]);
10834 } else if (isTypeNameInIsExpression(node)) {
10835 reportError5(StaticWarningCode.TYPE_TEST_NON_TYPE, typeName, [typeName.n ame]);
10836 } else if (isTypeNameTargetInRedirectedConstructor(node)) {
10837 reportError5(StaticWarningCode.REDIRECT_TO_NON_CLASS, typeName, [typeNam e.name]);
10838 } else if (isTypeNameInTypeArgumentList(node)) {
10839 reportError5(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, typeName, [typeName.name]);
10840 } else {
10841 reportError5(StaticWarningCode.UNDEFINED_CLASS, typeName, [typeName.name ]);
10842 }
10843 elementValid = false;
10844 }
10845 if (!elementValid) {
10846 if (element is MultiplyDefinedElement) {
10847 setElement(typeName, element);
10848 } else {
10849 setElement(typeName, this._dynamicType.element);
10850 }
10851 typeName.staticType = this._dynamicType;
10852 node.type = this._dynamicType;
10853 return null;
10854 }
10855 Type2 type = null;
10856 if (element is ClassElement) {
10857 setElement(typeName, element);
10858 type = ((element as ClassElement)).type;
10859 } else if (element is FunctionTypeAliasElement) {
10860 setElement(typeName, element);
10861 type = ((element as FunctionTypeAliasElement)).type;
10862 } else if (element is TypeParameterElement) {
10863 setElement(typeName, element);
10864 type = ((element as TypeParameterElement)).type;
10865 if (argumentList != null) {
10866 }
10867 } else if (element is MultiplyDefinedElement) {
10868 List<Element> elements = ((element as MultiplyDefinedElement)).conflicting Elements;
10869 type = getType(elements);
10870 if (type != null) {
10871 node.type = type;
10872 }
10873 } else {
10874 if (isTypeNameInCatchClause(node)) {
10875 reportError5(StaticWarningCode.NON_TYPE_IN_CATCH_CLAUSE, typeName, [type Name.name]);
10876 } else if (isTypeNameInAsExpression(node)) {
10877 reportError5(StaticWarningCode.CAST_TO_NON_TYPE, typeName, [typeName.nam e]);
10878 } else if (isTypeNameInIsExpression(node)) {
10879 reportError5(StaticWarningCode.TYPE_TEST_NON_TYPE, typeName, [typeName.n ame]);
10880 } else if (isTypeNameTargetInRedirectedConstructor(node)) {
10881 reportError5(StaticWarningCode.REDIRECT_TO_NON_CLASS, typeName, [typeNam e.name]);
10882 } else if (isTypeNameInTypeArgumentList(node)) {
10883 reportError5(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, typeName, [typeName.name]);
10884 } else {
10885 ASTNode parent = typeName.parent;
10886 while (parent is TypeName) {
10887 parent = parent.parent;
10888 }
10889 if (parent is ExtendsClause || parent is ImplementsClause || parent is W ithClause || parent is ClassTypeAlias) {
10890 } else {
10891 reportError5(StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]);
10892 }
10893 }
10894 setElement(typeName, this._dynamicType.element);
10895 typeName.staticType = this._dynamicType;
10896 node.type = this._dynamicType;
10897 return null;
10898 }
10899 if (argumentList != null) {
10900 NodeList<TypeName> arguments = argumentList.arguments;
10901 int argumentCount = arguments.length;
10902 List<Type2> parameters = getTypeArguments(type);
10903 int parameterCount = parameters.length;
10904 int count = Math.min(argumentCount, parameterCount);
10905 List<Type2> typeArguments = new List<Type2>();
10906 for (int i = 0; i < count; i++) {
10907 Type2 argumentType = getType3(arguments[i]);
10908 if (argumentType != null) {
10909 typeArguments.add(argumentType);
10910 }
10911 }
10912 if (argumentCount != parameterCount) {
10913 reportError5(getInvalidTypeParametersErrorCode(node), node, [typeName.na me, parameterCount, argumentCount]);
10914 }
10915 argumentCount = typeArguments.length;
10916 if (argumentCount < parameterCount) {
10917 for (int i = argumentCount; i < parameterCount; i++) {
10918 typeArguments.add(this._dynamicType);
10919 }
10920 }
10921 if (type is InterfaceTypeImpl) {
10922 InterfaceTypeImpl interfaceType = type as InterfaceTypeImpl;
10923 type = interfaceType.substitute4(new List.from(typeArguments));
10924 } else if (type is FunctionTypeImpl) {
10925 FunctionTypeImpl functionType = type as FunctionTypeImpl;
10926 type = functionType.substitute3(new List.from(typeArguments));
10927 } else {
10928 }
10929 } else {
10930 List<Type2> parameters = getTypeArguments(type);
10931 int parameterCount = parameters.length;
10932 if (parameterCount > 0) {
10933 DynamicTypeImpl dynamicType = DynamicTypeImpl.instance;
10934 List<Type2> arguments = new List<Type2>(parameterCount);
10935 for (int i = 0; i < parameterCount; i++) {
10936 arguments[i] = dynamicType;
10937 }
10938 type = type.substitute2(arguments, parameters);
10939 }
10940 }
10941 typeName.staticType = type;
10942 node.type = type;
10943 return null;
10944 }
10945 Object visitVariableDeclaration(VariableDeclaration node) {
10946 super.visitVariableDeclaration(node);
10947 Type2 declaredType;
10948 TypeName typeName = ((node.parent as VariableDeclarationList)).type;
10949 if (typeName == null) {
10950 declaredType = _dynamicType;
10951 } else {
10952 declaredType = getType3(typeName);
10953 }
10954 Element element = node.name.staticElement;
10955 if (element is VariableElement) {
10956 ((element as VariableElementImpl)).type = declaredType;
10957 if (element is PropertyInducingElement) {
10958 PropertyInducingElement variableElement = element as PropertyInducingEle ment;
10959 PropertyAccessorElementImpl getter = variableElement.getter as PropertyA ccessorElementImpl;
10960 getter.returnType = declaredType;
10961 FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter);
10962 ClassElement definingClass = element.getAncestor(ClassElement);
10963 if (definingClass != null) {
10964 getterType.typeArguments = definingClass.type.typeArguments;
10965 }
10966 getter.type = getterType;
10967 PropertyAccessorElementImpl setter = variableElement.setter as PropertyA ccessorElementImpl;
10968 if (setter != null) {
10969 List<ParameterElement> parameters = setter.parameters;
10970 if (parameters.length > 0) {
10971 ((parameters[0] as ParameterElementImpl)).type = declaredType;
10972 }
10973 setter.returnType = VoidTypeImpl.instance;
10974 FunctionTypeImpl setterType = new FunctionTypeImpl.con1(setter);
10975 if (definingClass != null) {
10976 setterType.typeArguments = definingClass.type.typeArguments;
10977 }
10978 setter.type = setterType;
10979 }
10980 }
10981 } else {
10982 }
10983 return null;
10984 }
10985
10986 /**
10987 * Given a type name representing the return type of a function, compute the r eturn type of the
10988 * function.
10989 *
10990 * @param returnType the type name representing the return type of the functio n
10991 * @return the return type that was computed
10992 */
10993 Type2 computeReturnType(TypeName returnType) {
10994 if (returnType == null) {
10995 return _dynamicType;
10996 } else {
10997 return returnType.type;
10998 }
10999 }
11000
11001 /**
11002 * Return the class element that represents the class whose name was provided.
11003 *
11004 * @param identifier the name from the declaration of a class
11005 * @return the class element that represents the class
11006 */
11007 ClassElementImpl getClassElement(SimpleIdentifier identifier) {
11008 if (identifier == null) {
11009 return null;
11010 }
11011 Element element = identifier.staticElement;
11012 if (element is! ClassElementImpl) {
11013 return null;
11014 }
11015 return element as ClassElementImpl;
11016 }
11017
11018 /**
11019 * Return an array containing all of the elements associated with the paramete rs in the given
11020 * list.
11021 *
11022 * @param parameterList the list of parameters whose elements are to be return ed
11023 * @return the elements associated with the parameters
11024 */
11025 List<ParameterElement> getElements(FormalParameterList parameterList) {
11026 List<ParameterElement> elements = new List<ParameterElement>();
11027 for (FormalParameter parameter in parameterList.parameters) {
11028 ParameterElement element = parameter.identifier.staticElement as Parameter Element;
11029 if (element != null) {
11030 elements.add(element);
11031 }
11032 }
11033 return new List.from(elements);
11034 }
11035
11036 /**
11037 * The number of type arguments in the given type name does not match the numb er of parameters in
11038 * the corresponding class element. Return the error code that should be used to report this
11039 * error.
11040 *
11041 * @param node the type name with the wrong number of type arguments
11042 * @return the error code that should be used to report that the wrong number of type arguments
11043 * were provided
11044 */
11045 ErrorCode getInvalidTypeParametersErrorCode(TypeName node) {
11046 ASTNode parent = node.parent;
11047 if (parent is ConstructorName) {
11048 parent = parent.parent;
11049 if (parent is InstanceCreationExpression) {
11050 if (((parent as InstanceCreationExpression)).isConst) {
11051 return CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS;
11052 } else {
11053 return StaticWarningCode.NEW_WITH_INVALID_TYPE_PARAMETERS;
11054 }
11055 }
11056 }
11057 return StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS;
11058 }
11059
11060 /**
11061 * Given the multiple elements to which a single name could potentially be res olved, return the
11062 * single interface type that should be used, or `null` if there is no clear c hoice.
11063 *
11064 * @param elements the elements to which a single name could potentially be re solved
11065 * @return the single interface type that should be used for the type name
11066 */
11067 InterfaceType getType(List<Element> elements) {
11068 InterfaceType type = null;
11069 for (Element element in elements) {
11070 if (element is ClassElement) {
11071 if (type != null) {
11072 return null;
11073 }
11074 type = ((element as ClassElement)).type;
11075 }
11076 }
11077 return type;
11078 }
11079
11080 /**
11081 * Return the type represented by the given type name.
11082 *
11083 * @param typeName the type name representing the type to be returned
11084 * @return the type represented by the type name
11085 */
11086 Type2 getType3(TypeName typeName) {
11087 Type2 type = typeName.type;
11088 if (type == null) {
11089 return _dynamicType;
11090 }
11091 return type;
11092 }
11093
11094 /**
11095 * Return the type arguments associated with the given type.
11096 *
11097 * @param type the type whole type arguments are to be returned
11098 * @return the type arguments associated with the given type
11099 */
11100 List<Type2> getTypeArguments(Type2 type) {
11101 if (type is InterfaceType) {
11102 return ((type as InterfaceType)).typeArguments;
11103 } else if (type is FunctionType) {
11104 return ((type as FunctionType)).typeArguments;
11105 }
11106 return TypeImpl.EMPTY_ARRAY;
11107 }
11108
11109 /**
11110 * Returns the simple identifier of the given (may be qualified) type name.
11111 *
11112 * @param typeName the (may be qualified) qualified type name
11113 * @return the simple identifier of the given (may be qualified) type name.
11114 */
11115 SimpleIdentifier getTypeSimpleIdentifier(Identifier typeName) {
11116 if (typeName is SimpleIdentifier) {
11117 return typeName as SimpleIdentifier;
11118 } else {
11119 return ((typeName as PrefixedIdentifier)).identifier;
11120 }
11121 }
11122
11123 /**
11124 * Checks if the given type name is used as the type in an as expression.
11125 *
11126 * @param typeName the type name to analyzer
11127 * @return `true` if the given type name is used as the type in an as expressi on
11128 */
11129 bool isTypeNameInAsExpression(TypeName typeName) {
11130 ASTNode parent = typeName.parent;
11131 if (parent is AsExpression) {
11132 AsExpression asExpression = parent as AsExpression;
11133 return identical(asExpression.type, typeName);
11134 }
11135 return false;
11136 }
11137
11138 /**
11139 * Checks if the given type name is used as the exception type in a catch clau se.
11140 *
11141 * @param typeName the type name to analyzer
11142 * @return `true` if the given type name is used as the exception type in a ca tch clause
11143 */
11144 bool isTypeNameInCatchClause(TypeName typeName) {
11145 ASTNode parent = typeName.parent;
11146 if (parent is CatchClause) {
11147 CatchClause catchClause = parent as CatchClause;
11148 return identical(catchClause.exceptionType, typeName);
11149 }
11150 return false;
11151 }
11152
11153 /**
11154 * Checks if the given type name is used as the type in an instance creation e xpression.
11155 *
11156 * @param typeName the type name to analyzer
11157 * @return `true` if the given type name is used as the type in an instance cr eation
11158 * expression
11159 */
11160 bool isTypeNameInInstanceCreationExpression(TypeName typeName) {
11161 ASTNode parent = typeName.parent;
11162 if (parent is ConstructorName && parent.parent is InstanceCreationExpression ) {
11163 ConstructorName constructorName = parent as ConstructorName;
11164 return constructorName != null && identical(constructorName.type, typeName );
11165 }
11166 return false;
11167 }
11168
11169 /**
11170 * Checks if the given type name is used as the type in an is expression.
11171 *
11172 * @param typeName the type name to analyzer
11173 * @return `true` if the given type name is used as the type in an is expressi on
11174 */
11175 bool isTypeNameInIsExpression(TypeName typeName) {
11176 ASTNode parent = typeName.parent;
11177 if (parent is IsExpression) {
11178 IsExpression isExpression = parent as IsExpression;
11179 return identical(isExpression.type, typeName);
11180 }
11181 return false;
11182 }
11183
11184 /**
11185 * Checks if the given type name used in a type argument list.
11186 *
11187 * @param typeName the type name to analyzer
11188 * @return `true` if the given type name is in a type argument list
11189 */
11190 bool isTypeNameInTypeArgumentList(TypeName typeName) => typeName.parent is Typ eArgumentList;
11191
11192 /**
11193 * Checks if the given type name is the target in a redirected constructor.
11194 *
11195 * @param typeName the type name to analyzer
11196 * @return `true` if the given type name is used as the type in a redirected c onstructor
11197 */
11198 bool isTypeNameTargetInRedirectedConstructor(TypeName typeName) {
11199 ASTNode parent = typeName.parent;
11200 if (parent is ConstructorName) {
11201 ConstructorName constructorName = parent as ConstructorName;
11202 parent = constructorName.parent;
11203 if (parent is ConstructorDeclaration) {
11204 ConstructorDeclaration constructorDeclaration = parent as ConstructorDec laration;
11205 return constructorName == constructorDeclaration.redirectedConstructor;
11206 }
11207 }
11208 return false;
11209 }
11210
11211 /**
11212 * Record that the static type of the given node is the given type.
11213 *
11214 * @param expression the node whose type is to be recorded
11215 * @param type the static type of the node
11216 */
11217 Object recordType(Expression expression, Type2 type) {
11218 if (type == null) {
11219 expression.staticType = _dynamicType;
11220 } else {
11221 expression.staticType = type;
11222 }
11223 return null;
11224 }
11225
11226 /**
11227 * Resolve the types in the given with and implements clauses and associate th ose types with the
11228 * given class element.
11229 *
11230 * @param classElement the class element with which the mixin and interface ty pes are to be
11231 * associated
11232 * @param withClause the with clause to be resolved
11233 * @param implementsClause the implements clause to be resolved
11234 */
11235 void resolve(ClassElementImpl classElement, WithClause withClause, ImplementsC lause implementsClause) {
11236 if (withClause != null) {
11237 List<InterfaceType> mixinTypes = resolveTypes(withClause.mixinTypes, Compi leTimeErrorCode.MIXIN_OF_NON_CLASS, CompileTimeErrorCode.MIXIN_OF_NON_CLASS);
11238 if (classElement != null) {
11239 classElement.mixins = mixinTypes;
11240 }
11241 }
11242 if (implementsClause != null) {
11243 NodeList<TypeName> interfaces = implementsClause.interfaces;
11244 List<InterfaceType> interfaceTypes = resolveTypes(interfaces, CompileTimeE rrorCode.IMPLEMENTS_NON_CLASS, CompileTimeErrorCode.IMPLEMENTS_DYNAMIC);
11245 if (classElement != null) {
11246 classElement.interfaces = interfaceTypes;
11247 }
11248 List<TypeName> typeNames = new List.from(interfaces);
11249 List<bool> detectedRepeatOnIndex = new List<bool>.filled(typeNames.length, false);
11250 for (int i = 0; i < detectedRepeatOnIndex.length; i++) {
11251 detectedRepeatOnIndex[i] = false;
11252 }
11253 for (int i = 0; i < typeNames.length; i++) {
11254 TypeName typeName = typeNames[i];
11255 if (!detectedRepeatOnIndex[i]) {
11256 Element element = typeName.name.staticElement;
11257 for (int j = i + 1; j < typeNames.length; j++) {
11258 TypeName typeName2 = typeNames[j];
11259 Identifier identifier2 = typeName2.name;
11260 String name2 = identifier2.name;
11261 Element element2 = identifier2.staticElement;
11262 if (element != null && element == element2) {
11263 detectedRepeatOnIndex[j] = true;
11264 reportError5(CompileTimeErrorCode.IMPLEMENTS_REPEATED, typeName2, [name2]);
11265 }
11266 }
11267 }
11268 }
11269 }
11270 }
11271
11272 /**
11273 * Return the type specified by the given name.
11274 *
11275 * @param typeName the type name specifying the type to be returned
11276 * @param nonTypeError the error to produce if the type name is defined to be something other than
11277 * a type
11278 * @param dynamicTypeError the error to produce if the type name is "dynamic"
11279 * @return the type specified by the type name
11280 */
11281 InterfaceType resolveType(TypeName typeName, ErrorCode nonTypeError, ErrorCode dynamicTypeError) {
11282 Type2 type = typeName.type;
11283 if (type is InterfaceType) {
11284 return type as InterfaceType;
11285 }
11286 Identifier name = typeName.name;
11287 if (name.name == sc.Keyword.DYNAMIC.syntax) {
11288 reportError5(dynamicTypeError, name, [name.name]);
11289 } else {
11290 reportError5(nonTypeError, name, [name.name]);
11291 }
11292 return null;
11293 }
11294
11295 /**
11296 * Resolve the types in the given list of type names.
11297 *
11298 * @param typeNames the type names to be resolved
11299 * @param nonTypeError the error to produce if the type name is defined to be something other than
11300 * a type
11301 * @param dynamicTypeError the error to produce if the type name is "dynamic"
11302 * @return an array containing all of the types that were resolved.
11303 */
11304 List<InterfaceType> resolveTypes(NodeList<TypeName> typeNames, ErrorCode nonTy peError, ErrorCode dynamicTypeError) {
11305 List<InterfaceType> types = new List<InterfaceType>();
11306 for (TypeName typeName in typeNames) {
11307 InterfaceType type = resolveType(typeName, nonTypeError, dynamicTypeError) ;
11308 if (type != null) {
11309 types.add(type);
11310 }
11311 }
11312 return new List.from(types);
11313 }
11314 void setElement(Identifier typeName, Element element) {
11315 if (element != null) {
11316 if (typeName is SimpleIdentifier) {
11317 ((typeName as SimpleIdentifier)).staticElement = element;
11318 } else if (typeName is PrefixedIdentifier) {
11319 PrefixedIdentifier identifier = typeName as PrefixedIdentifier;
11320 identifier.identifier.staticElement = element;
11321 SimpleIdentifier prefix = identifier.prefix;
11322 Element prefixElement = nameScope.lookup(prefix, definingLibrary);
11323 if (prefixElement != null) {
11324 prefix.staticElement = prefixElement;
11325 }
11326 }
11327 }
11328 }
11329
11330 /**
11331 * Given a parameter element, create a function type based on the given return type and parameter
11332 * list and associate the created type with the element.
11333 *
11334 * @param element the parameter element whose type is to be set
11335 * @param returnType the (possibly `null`) return type of the function
11336 * @param parameterList the list of parameters to the function
11337 */
11338 void setFunctionTypedParameterType(ParameterElementImpl element, TypeName retu rnType, FormalParameterList parameterList) {
11339 List<ParameterElement> parameters = getElements(parameterList);
11340 FunctionTypeAliasElementImpl aliasElement = new FunctionTypeAliasElementImpl (null);
11341 aliasElement.synthetic = true;
11342 aliasElement.shareParameters(parameters);
11343 aliasElement.returnType = computeReturnType(returnType);
11344 FunctionTypeImpl type = new FunctionTypeImpl.con2(aliasElement);
11345 ClassElement definingClass = element.getAncestor(ClassElement);
11346 if (definingClass != null) {
11347 aliasElement.shareTypeParameters(definingClass.typeParameters);
11348 type.typeArguments = definingClass.type.typeArguments;
11349 } else {
11350 FunctionTypeAliasElement alias = element.getAncestor(FunctionTypeAliasElem ent);
11351 while (alias != null && alias.isSynthetic) {
11352 alias = alias.getAncestor(FunctionTypeAliasElement);
11353 }
11354 if (alias != null) {
11355 aliasElement.typeParameters = alias.typeParameters;
11356 type.typeArguments = alias.type.typeArguments;
11357 } else {
11358 type.typeArguments = TypeImpl.EMPTY_ARRAY;
11359 }
11360 }
11361 element.type = type;
11362 }
11363 }
11364 /**
11365 * Instances of the class `VariableResolverVisitor` are used to resolve
11366 * [SimpleIdentifier]s to local variables and formal parameters.
11367 *
11368 * @coverage dart.engine.resolver
11369 */
11370 class VariableResolverVisitor extends ScopedVisitor {
11371
11372 /**
11373 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
11374 *
11375 * @param library the library containing the compilation unit being resolved
11376 * @param source the source representing the compilation unit being visited
11377 * @param typeProvider the object used to access the types from the core libra ry
11378 */
11379 VariableResolverVisitor(Library library, Source source, TypeProvider typeProvi der) : super.con1(library, source, typeProvider);
11380 Object visitSimpleIdentifier(SimpleIdentifier node) {
11381 if (node.staticElement != null) {
11382 return null;
11383 }
11384 ASTNode parent = node.parent;
11385 if (parent is PrefixedIdentifier && identical(((parent as PrefixedIdentifier )).identifier, node)) {
11386 return null;
11387 }
11388 if (parent is PropertyAccess && identical(((parent as PropertyAccess)).prope rtyName, node)) {
11389 return null;
11390 }
11391 if (parent is MethodInvocation && identical(((parent as MethodInvocation)).m ethodName, node)) {
11392 return null;
11393 }
11394 if (parent is ConstructorName) {
11395 return null;
11396 }
11397 if (parent is Label) {
11398 return null;
11399 }
11400 Element element = nameScope.lookup(node, definingLibrary);
11401 if (element is! VariableElement) {
11402 return null;
11403 }
11404 ElementKind kind = element.kind;
11405 if (identical(kind, ElementKind.LOCAL_VARIABLE)) {
11406 node.staticElement = element;
11407 if (node.inSetterContext()) {
11408 ((element as LocalVariableElementImpl)).markPotentiallyMutated();
11409 }
11410 } else if (identical(kind, ElementKind.PARAMETER)) {
11411 node.staticElement = element;
11412 if (node.inSetterContext()) {
11413 ((element as ParameterElementImpl)).markPotentiallyMutated();
11414 }
11415 }
11416 return null;
11417 }
11418 }
11419 /**
11420 * Instances of the class `ClassScope` implement the scope defined by a class.
11421 *
11422 * @coverage dart.engine.resolver
11423 */
11424 class ClassScope extends EnclosedScope {
11425
11426 /**
11427 * Initialize a newly created scope enclosed within another scope.
11428 *
11429 * @param enclosingScope the scope in which this scope is lexically enclosed
11430 * @param typeElement the element representing the type represented by this sc ope
11431 */
11432 ClassScope(Scope enclosingScope, ClassElement typeElement) : super(new Enclose dScope(enclosingScope)) {
11433 defineTypeParameters(typeElement);
11434 defineMembers(typeElement);
11435 }
11436 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
11437 if (existing is PropertyAccessorElement && duplicate is MethodElement) {
11438 if (existing.nameOffset < duplicate.nameOffset) {
11439 return new AnalysisError.con2(duplicate.source, duplicate.nameOffset, du plicate.displayName.length, CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAM E, [existing.displayName]);
11440 } else {
11441 return new AnalysisError.con2(existing.source, existing.nameOffset, exis ting.displayName.length, CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME, [existing.displayName]);
11442 }
11443 }
11444 return super.getErrorForDuplicate(existing, duplicate);
11445 }
11446
11447 /**
11448 * Define the instance members defined by the class.
11449 *
11450 * @param typeElement the element representing the type represented by this sc ope
11451 */
11452 void defineMembers(ClassElement typeElement) {
11453 for (PropertyAccessorElement accessor in typeElement.accessors) {
11454 define(accessor);
11455 }
11456 for (MethodElement method in typeElement.methods) {
11457 define(method);
11458 }
11459 }
11460
11461 /**
11462 * Define the type parameters for the class.
11463 *
11464 * @param typeElement the element representing the type represented by this sc ope
11465 */
11466 void defineTypeParameters(ClassElement typeElement) {
11467 Scope parameterScope = enclosingScope;
11468 for (TypeParameterElement typeParameter in typeElement.typeParameters) {
11469 parameterScope.define(typeParameter);
11470 }
11471 }
11472 }
11473 /**
11474 * Instances of the class `EnclosedScope` implement a scope that is lexically en closed in
11475 * another scope.
11476 *
11477 * @coverage dart.engine.resolver
11478 */
11479 class EnclosedScope extends Scope {
11480
11481 /**
11482 * The scope in which this scope is lexically enclosed.
11483 */
11484 Scope enclosingScope;
11485
11486 /**
11487 * A set of names that will be defined in this scope, but right now are not de fined. However
11488 * according to the scoping rules these names are hidden, even if they were de fined in an outer
11489 * scope.
11490 */
11491 Set<String> _hiddenNames = new Set<String>();
11492
11493 /**
11494 * Initialize a newly created scope enclosed within another scope.
11495 *
11496 * @param enclosingScope the scope in which this scope is lexically enclosed
11497 */
11498 EnclosedScope(Scope enclosingScope) {
11499 this.enclosingScope = enclosingScope;
11500 }
11501 LibraryElement get definingLibrary => enclosingScope.definingLibrary;
11502 AnalysisErrorListener get errorListener => enclosingScope.errorListener;
11503
11504 /**
11505 * Hides the name of the given element in this scope. If there is already an e lement with the
11506 * given name defined in an outer scope, then it will become unavailable.
11507 *
11508 * @param element the element to be hidden in this scope
11509 */
11510 void hide(Element element) {
11511 if (element != null) {
11512 String name = element.name;
11513 if (name != null && !name.isEmpty) {
11514 javaSetAdd(_hiddenNames, name);
11515 }
11516 }
11517 }
11518 Element lookup3(Identifier identifier, String name, LibraryElement referencing Library) {
11519 Element element = localLookup(name, referencingLibrary);
11520 if (element != null) {
11521 return element;
11522 }
11523 if (_hiddenNames.contains(name)) {
11524 errorListener.onError(new AnalysisError.con2(source, identifier.offset, id entifier.length, CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, []));
11525 }
11526 return enclosingScope.lookup3(identifier, name, referencingLibrary);
11527 }
11528 }
11529 /**
11530 * Instances of the class `FunctionScope` implement the scope defined by a funct ion.
11531 *
11532 * @coverage dart.engine.resolver
11533 */
11534 class FunctionScope extends EnclosedScope {
11535 ExecutableElement _functionElement;
11536 bool _parametersDefined = false;
11537
11538 /**
11539 * Initialize a newly created scope enclosed within another scope.
11540 *
11541 * @param enclosingScope the scope in which this scope is lexically enclosed
11542 * @param functionElement the element representing the type represented by thi s scope
11543 */
11544 FunctionScope(Scope enclosingScope, ExecutableElement functionElement) : super (new EnclosedScope(enclosingScope)) {
11545 this._functionElement = functionElement;
11546 }
11547
11548 /**
11549 * Define the parameters for the given function in the scope that encloses thi s function.
11550 */
11551 void defineParameters() {
11552 if (_parametersDefined) {
11553 return;
11554 }
11555 _parametersDefined = true;
11556 Scope parameterScope = enclosingScope;
11557 if (_functionElement.enclosingElement is ExecutableElement) {
11558 String name = _functionElement.name;
11559 if (name != null && !name.isEmpty) {
11560 parameterScope.define(_functionElement);
11561 }
11562 }
11563 for (ParameterElement parameter in _functionElement.parameters) {
11564 if (!parameter.isInitializingFormal) {
11565 parameterScope.define(parameter);
11566 }
11567 }
11568 }
11569 }
11570 /**
11571 * Instances of the class `FunctionTypeScope` implement the scope defined by a f unction type
11572 * alias.
11573 *
11574 * @coverage dart.engine.resolver
11575 */
11576 class FunctionTypeScope extends EnclosedScope {
11577 FunctionTypeAliasElement _typeElement;
11578 bool _parametersDefined = false;
11579
11580 /**
11581 * Initialize a newly created scope enclosed within another scope.
11582 *
11583 * @param enclosingScope the scope in which this scope is lexically enclosed
11584 * @param typeElement the element representing the type alias represented by t his scope
11585 */
11586 FunctionTypeScope(Scope enclosingScope, FunctionTypeAliasElement typeElement) : super(new EnclosedScope(enclosingScope)) {
11587 this._typeElement = typeElement;
11588 defineTypeParameters();
11589 }
11590
11591 /**
11592 * Define the parameters for the function type alias.
11593 *
11594 * @param typeElement the element representing the type represented by this sc ope
11595 */
11596 void defineParameters() {
11597 if (_parametersDefined) {
11598 return;
11599 }
11600 _parametersDefined = true;
11601 for (ParameterElement parameter in _typeElement.parameters) {
11602 define(parameter);
11603 }
11604 }
11605
11606 /**
11607 * Define the type parameters for the function type alias.
11608 *
11609 * @param typeElement the element representing the type represented by this sc ope
11610 */
11611 void defineTypeParameters() {
11612 Scope typeParameterScope = enclosingScope;
11613 for (TypeParameterElement typeParameter in _typeElement.typeParameters) {
11614 typeParameterScope.define(typeParameter);
11615 }
11616 }
11617 }
11618 /**
11619 * Instances of the class `LabelScope` represent a scope in which a single label is defined.
11620 *
11621 * @coverage dart.engine.resolver
11622 */
11623 class LabelScope {
11624
11625 /**
11626 * The label scope enclosing this label scope.
11627 */
11628 LabelScope _outerScope;
11629
11630 /**
11631 * The label defined in this scope.
11632 */
11633 String _label;
11634
11635 /**
11636 * The element to which the label resolves.
11637 */
11638 LabelElement _element;
11639
11640 /**
11641 * The marker used to look up a label element for an unlabeled `break` or `con tinue`.
11642 */
11643 static String EMPTY_LABEL = "";
11644
11645 /**
11646 * The label element returned for scopes that can be the target of an unlabele d `break` or
11647 * `continue`.
11648 */
11649 static SimpleIdentifier _EMPTY_LABEL_IDENTIFIER = new SimpleIdentifier.full(ne w sc.StringToken(sc.TokenType.IDENTIFIER, "", 0));
11650
11651 /**
11652 * Initialize a newly created scope to represent the potential target of an un labeled
11653 * `break` or `continue`.
11654 *
11655 * @param outerScope the label scope enclosing the new label scope
11656 * @param onSwitchStatement `true` if this label is associated with a `switch`
11657 * statement
11658 * @param onSwitchMember `true` if this label is associated with a `switch` me mber
11659 */
11660 LabelScope.con1(LabelScope outerScope, bool onSwitchStatement, bool onSwitchMe mber) : this.con2(outerScope, EMPTY_LABEL, new LabelElementImpl(_EMPTY_LABEL_IDE NTIFIER, onSwitchStatement, onSwitchMember));
11661
11662 /**
11663 * Initialize a newly created scope to represent the given label.
11664 *
11665 * @param outerScope the label scope enclosing the new label scope
11666 * @param label the label defined in this scope
11667 * @param element the element to which the label resolves
11668 */
11669 LabelScope.con2(LabelScope outerScope, String label, LabelElement element) {
11670 this._outerScope = outerScope;
11671 this._label = label;
11672 this._element = element;
11673 }
11674
11675 /**
11676 * Return the label element corresponding to the given label, or `null` if the given label
11677 * is not defined in this scope.
11678 *
11679 * @param targetLabel the label being looked up
11680 * @return the label element corresponding to the given label
11681 */
11682 LabelElement lookup(SimpleIdentifier targetLabel) => lookup2(targetLabel.name) ;
11683
11684 /**
11685 * Return the label element corresponding to the given label, or `null` if the given label
11686 * is not defined in this scope.
11687 *
11688 * @param targetLabel the label being looked up
11689 * @return the label element corresponding to the given label
11690 */
11691 LabelElement lookup2(String targetLabel) {
11692 if (_label == targetLabel) {
11693 return _element;
11694 } else if (_outerScope != null) {
11695 return _outerScope.lookup2(targetLabel);
11696 } else {
11697 return null;
11698 }
11699 }
11700 }
11701 /**
11702 * Instances of the class `LibraryImportScope` represent the scope containing al l of the names
11703 * available from imported libraries.
11704 *
11705 * @coverage dart.engine.resolver
11706 */
11707 class LibraryImportScope extends Scope {
11708
11709 /**
11710 * The element representing the library in which this scope is enclosed.
11711 */
11712 LibraryElement _definingLibrary;
11713
11714 /**
11715 * The listener that is to be informed when an error is encountered.
11716 */
11717 AnalysisErrorListener _errorListener;
11718
11719 /**
11720 * A list of the namespaces representing the names that are available in this scope from imported
11721 * libraries.
11722 */
11723 List<Namespace> _importedNamespaces = new List<Namespace>();
11724
11725 /**
11726 * Initialize a newly created scope representing the names imported into the g iven library.
11727 *
11728 * @param definingLibrary the element representing the library that imports th e names defined in
11729 * this scope
11730 * @param errorListener the listener that is to be informed when an error is e ncountered
11731 */
11732 LibraryImportScope(LibraryElement definingLibrary, AnalysisErrorListener error Listener) {
11733 this._definingLibrary = definingLibrary;
11734 this._errorListener = errorListener;
11735 createImportedNamespaces(definingLibrary);
11736 }
11737 void define(Element element) {
11738 if (!Scope.isPrivateName(element.displayName)) {
11739 super.define(element);
11740 }
11741 }
11742 LibraryElement get definingLibrary => _definingLibrary;
11743 AnalysisErrorListener get errorListener => _errorListener;
11744 Element lookup3(Identifier identifier, String name, LibraryElement referencing Library) {
11745 Element foundElement = localLookup(name, referencingLibrary);
11746 if (foundElement != null) {
11747 return foundElement;
11748 }
11749 for (Namespace nameSpace in _importedNamespaces) {
11750 Element element = nameSpace.get(name);
11751 if (element != null) {
11752 if (foundElement == null) {
11753 foundElement = element;
11754 } else if (foundElement != element) {
11755 foundElement = MultiplyDefinedElementImpl.fromElements(_definingLibrar y.context, foundElement, element);
11756 }
11757 }
11758 }
11759 if (foundElement is MultiplyDefinedElementImpl) {
11760 foundElement = removeSdkElements(identifier, name, foundElement as Multipl yDefinedElementImpl);
11761 }
11762 if (foundElement is MultiplyDefinedElementImpl) {
11763 String foundEltName = foundElement.displayName;
11764 List<Element> conflictingMembers = ((foundElement as MultiplyDefinedElemen tImpl)).conflictingElements;
11765 String libName1 = getLibraryName(conflictingMembers[0], "");
11766 String libName2 = getLibraryName(conflictingMembers[1], "");
11767 _errorListener.onError(new AnalysisError.con2(getSource2(identifier), iden tifier.offset, identifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltN ame, libName1, libName2]));
11768 return foundElement;
11769 }
11770 if (foundElement != null) {
11771 defineWithoutChecking2(name, foundElement);
11772 }
11773 return foundElement;
11774 }
11775
11776 /**
11777 * Create all of the namespaces associated with the libraries imported into th is library. The
11778 * names are not added to this scope, but are stored for later reference.
11779 *
11780 * @param definingLibrary the element representing the library that imports th e libraries for
11781 * which namespaces will be created
11782 */
11783 void createImportedNamespaces(LibraryElement definingLibrary) {
11784 NamespaceBuilder builder = new NamespaceBuilder();
11785 for (ImportElement element in definingLibrary.imports) {
11786 _importedNamespaces.add(builder.createImportNamespace(element));
11787 }
11788 }
11789
11790 /**
11791 * Returns the name of the library that defines given element.
11792 *
11793 * @param element the element to get library name
11794 * @param def the default name to use
11795 * @return the name of the library that defines given element
11796 */
11797 String getLibraryName(Element element, String def) {
11798 if (element == null) {
11799 return def;
11800 }
11801 LibraryElement library = element.library;
11802 if (library == null) {
11803 return def;
11804 }
11805 return library.definingCompilationUnit.displayName;
11806 }
11807
11808 /**
11809 * Return the source that contains the given identifier, or the source associa ted with this scope
11810 * if the source containing the identifier could not be determined.
11811 *
11812 * @param identifier the identifier whose source is to be returned
11813 * @return the source that contains the given identifier
11814 */
11815 Source getSource2(Identifier identifier) {
11816 CompilationUnit unit = identifier.getAncestor(CompilationUnit);
11817 if (unit != null) {
11818 CompilationUnitElement element = unit.element;
11819 if (element != null) {
11820 Source source = element.source;
11821 if (source != null) {
11822 return source;
11823 }
11824 }
11825 }
11826 return this.source;
11827 }
11828
11829 /**
11830 * Given a collection of elements that a single name could all be mapped to, r emove from the list
11831 * all of the names defined in the SDK. Return the element(s) that remain.
11832 *
11833 * @param identifier the identifier node to lookup element for, used to report correct kind of a
11834 * problem and associate problem with
11835 * @param name the name associated with the element
11836 * @param foundElement the element encapsulating the collection of elements
11837 * @return all of the elements that are not defined in the SDK
11838 */
11839 Element removeSdkElements(Identifier identifier, String name, MultiplyDefinedE lementImpl foundElement) {
11840 List<Element> conflictingMembers = foundElement.conflictingElements;
11841 int length = conflictingMembers.length;
11842 int to = 0;
11843 Element sdkElement = null;
11844 for (Element member in conflictingMembers) {
11845 if (member.library.isInSdk) {
11846 sdkElement = member;
11847 } else {
11848 conflictingMembers[to++] = member;
11849 }
11850 }
11851 if (sdkElement != null && to > 0) {
11852 String sdkLibName = getLibraryName(sdkElement, "");
11853 String otherLibName = getLibraryName(conflictingMembers[0], "");
11854 _errorListener.onError(new AnalysisError.con2(getSource2(identifier), iden tifier.offset, identifier.length, StaticWarningCode.CONFLICTING_DART_IMPORT, [na me, sdkLibName, otherLibName]));
11855 }
11856 if (to == length) {
11857 return foundElement;
11858 } else if (to == 1) {
11859 return conflictingMembers[0];
11860 } else if (to == 0) {
11861 AnalysisEngine.instance.logger.logInformation("Multiply defined SDK elemen t: ${foundElement}");
11862 return foundElement;
11863 }
11864 List<Element> remaining = new List<Element>(to);
11865 JavaSystem.arraycopy(conflictingMembers, 0, remaining, 0, to);
11866 return new MultiplyDefinedElementImpl(_definingLibrary.context, remaining);
11867 }
11868 }
11869 /**
11870 * Instances of the class `LibraryScope` implement a scope containing all of the names defined
11871 * in a given library.
11872 *
11873 * @coverage dart.engine.resolver
11874 */
11875 class LibraryScope extends EnclosedScope {
11876
11877 /**
11878 * Initialize a newly created scope representing the names defined in the give n library.
11879 *
11880 * @param definingLibrary the element representing the library represented by this scope
11881 * @param errorListener the listener that is to be informed when an error is e ncountered
11882 */
11883 LibraryScope(LibraryElement definingLibrary, AnalysisErrorListener errorListen er) : super(new LibraryImportScope(definingLibrary, errorListener)) {
11884 defineTopLevelNames(definingLibrary);
11885 }
11886 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
11887 if (existing is PrefixElement) {
11888 int offset = duplicate.nameOffset;
11889 if (duplicate is PropertyAccessorElement) {
11890 PropertyAccessorElement accessor = duplicate as PropertyAccessorElement;
11891 if (accessor.isSynthetic) {
11892 offset = accessor.variable.nameOffset;
11893 }
11894 }
11895 return new AnalysisError.con2(source, offset, duplicate.displayName.length , CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, [existing.displayN ame]);
11896 }
11897 return super.getErrorForDuplicate(existing, duplicate);
11898 }
11899
11900 /**
11901 * Add to this scope all of the public top-level names that are defined in the given compilation
11902 * unit.
11903 *
11904 * @param compilationUnit the compilation unit defining the top-level names to be added to this
11905 * scope
11906 */
11907 void defineLocalNames(CompilationUnitElement compilationUnit) {
11908 for (PropertyAccessorElement element in compilationUnit.accessors) {
11909 define(element);
11910 }
11911 for (FunctionElement element in compilationUnit.functions) {
11912 define(element);
11913 }
11914 for (FunctionTypeAliasElement element in compilationUnit.functionTypeAliases ) {
11915 define(element);
11916 }
11917 for (ClassElement element in compilationUnit.types) {
11918 define(element);
11919 }
11920 }
11921
11922 /**
11923 * Add to this scope all of the names that are explicitly defined in the given library.
11924 *
11925 * @param definingLibrary the element representing the library that defines th e names in this
11926 * scope
11927 */
11928 void defineTopLevelNames(LibraryElement definingLibrary) {
11929 for (PrefixElement prefix in definingLibrary.prefixes) {
11930 define(prefix);
11931 }
11932 defineLocalNames(definingLibrary.definingCompilationUnit);
11933 for (CompilationUnitElement compilationUnit in definingLibrary.parts) {
11934 defineLocalNames(compilationUnit);
11935 }
11936 }
11937 }
11938 /**
11939 * Instances of the class `Namespace` implement a mapping of identifiers to the elements
11940 * represented by those identifiers. Namespaces are the building blocks for scop es.
11941 *
11942 * @coverage dart.engine.resolver
11943 */
11944 class Namespace {
11945
11946 /**
11947 * A table mapping names that are defined in this namespace to the element rep resenting the thing
11948 * declared with that name.
11949 */
11950 Map<String, Element> _definedNames;
11951
11952 /**
11953 * An empty namespace.
11954 */
11955 static Namespace EMPTY = new Namespace(new Map<String, Element>());
11956
11957 /**
11958 * Initialize a newly created namespace to have the given defined names.
11959 *
11960 * @param definedNames the mapping from names that are defined in this namespa ce to the
11961 * corresponding elements
11962 */
11963 Namespace(Map<String, Element> definedNames) {
11964 this._definedNames = definedNames;
11965 }
11966
11967 /**
11968 * Return the element in this namespace that is available to the containing sc ope using the given
11969 * name.
11970 *
11971 * @param name the name used to reference the
11972 * @return the element represented by the given identifier
11973 */
11974 Element get(String name) => _definedNames[name];
11975
11976 /**
11977 * Return a table containing the same mappings as those defined by this namesp ace.
11978 *
11979 * @return a table containing the same mappings as those defined by this names pace
11980 */
11981 Map<String, Element> get definedNames => new Map<String, Element>.from(_define dNames);
11982 }
11983 /**
11984 * Instances of the class `NamespaceBuilder` are used to build a `Namespace`. Na mespace
11985 * builders are thread-safe and re-usable.
11986 *
11987 * @coverage dart.engine.resolver
11988 */
11989 class NamespaceBuilder {
11990
11991 /**
11992 * Create a namespace representing the export namespace of the given [ExportEl ement].
11993 *
11994 * @param element the export element whose export namespace is to be created
11995 * @return the export namespace that was created
11996 */
11997 Namespace createExportNamespace(ExportElement element) {
11998 LibraryElement exportedLibrary = element.exportedLibrary;
11999 if (exportedLibrary == null) {
12000 return Namespace.EMPTY;
12001 }
12002 Map<String, Element> definedNames = createExportMapping(exportedLibrary, new Set<LibraryElement>());
12003 definedNames = apply(definedNames, element.combinators);
12004 return new Namespace(definedNames);
12005 }
12006
12007 /**
12008 * Create a namespace representing the export namespace of the given library.
12009 *
12010 * @param library the library whose export namespace is to be created
12011 * @return the export namespace that was created
12012 */
12013 Namespace createExportNamespace2(LibraryElement library) => new Namespace(crea teExportMapping(library, new Set<LibraryElement>()));
12014
12015 /**
12016 * Create a namespace representing the import namespace of the given library.
12017 *
12018 * @param library the library whose import namespace is to be created
12019 * @return the import namespace that was created
12020 */
12021 Namespace createImportNamespace(ImportElement element) {
12022 LibraryElement importedLibrary = element.importedLibrary;
12023 if (importedLibrary == null) {
12024 return Namespace.EMPTY;
12025 }
12026 Map<String, Element> definedNames = createExportMapping(importedLibrary, new Set<LibraryElement>());
12027 definedNames = apply(definedNames, element.combinators);
12028 definedNames = apply2(definedNames, element.prefix);
12029 return new Namespace(definedNames);
12030 }
12031
12032 /**
12033 * Create a namespace representing the public namespace of the given library.
12034 *
12035 * @param library the library whose public namespace is to be created
12036 * @return the public namespace that was created
12037 */
12038 Namespace createPublicNamespace(LibraryElement library) {
12039 Map<String, Element> definedNames = new Map<String, Element>();
12040 addPublicNames(definedNames, library.definingCompilationUnit);
12041 for (CompilationUnitElement compilationUnit in library.parts) {
12042 addPublicNames(definedNames, compilationUnit);
12043 }
12044 return new Namespace(definedNames);
12045 }
12046
12047 /**
12048 * Add all of the names in the given namespace to the given mapping table.
12049 *
12050 * @param definedNames the mapping table to which the names in the given names pace are to be added
12051 * @param namespace the namespace containing the names to be added to this nam espace
12052 */
12053 void addAll(Map<String, Element> definedNames, Map<String, Element> newNames) {
12054 for (MapEntry<String, Element> entry in getMapEntrySet(newNames)) {
12055 definedNames[entry.getKey()] = entry.getValue();
12056 }
12057 }
12058
12059 /**
12060 * Add all of the names in the given namespace to the given mapping table.
12061 *
12062 * @param definedNames the mapping table to which the names in the given names pace are to be added
12063 * @param namespace the namespace containing the names to be added to this nam espace
12064 */
12065 void addAll2(Map<String, Element> definedNames, Namespace namespace) {
12066 if (namespace != null) {
12067 addAll(definedNames, namespace.definedNames);
12068 }
12069 }
12070
12071 /**
12072 * Add the given element to the given mapping table if it has a publicly visib le name.
12073 *
12074 * @param definedNames the mapping table to which the public name is to be add ed
12075 * @param element the element to be added
12076 */
12077 void addIfPublic(Map<String, Element> definedNames, Element element) {
12078 String name = element.name;
12079 if (name != null && !Scope.isPrivateName(name)) {
12080 definedNames[name] = element;
12081 }
12082 }
12083
12084 /**
12085 * Add to the given mapping table all of the public top-level names that are d efined in the given
12086 * compilation unit.
12087 *
12088 * @param definedNames the mapping table to which the public names are to be a dded
12089 * @param compilationUnit the compilation unit defining the top-level names to be added to this
12090 * namespace
12091 */
12092 void addPublicNames(Map<String, Element> definedNames, CompilationUnitElement compilationUnit) {
12093 for (PropertyAccessorElement element in compilationUnit.accessors) {
12094 addIfPublic(definedNames, element);
12095 }
12096 for (FunctionElement element in compilationUnit.functions) {
12097 addIfPublic(definedNames, element);
12098 }
12099 for (FunctionTypeAliasElement element in compilationUnit.functionTypeAliases ) {
12100 addIfPublic(definedNames, element);
12101 }
12102 for (ClassElement element in compilationUnit.types) {
12103 addIfPublic(definedNames, element);
12104 }
12105 }
12106
12107 /**
12108 * Apply the given combinators to all of the names in the given mapping table.
12109 *
12110 * @param definedNames the mapping table to which the namespace operations are to be applied
12111 * @param combinators the combinators to be applied
12112 */
12113 Map<String, Element> apply(Map<String, Element> definedNames, List<NamespaceCo mbinator> combinators) {
12114 for (NamespaceCombinator combinator in combinators) {
12115 if (combinator is HideElementCombinator) {
12116 hide(definedNames, ((combinator as HideElementCombinator)).hiddenNames);
12117 } else if (combinator is ShowElementCombinator) {
12118 definedNames = show(definedNames, ((combinator as ShowElementCombinator) ).shownNames);
12119 } else {
12120 AnalysisEngine.instance.logger.logError("Unknown type of combinator: ${c ombinator.runtimeType.toString()}");
12121 }
12122 }
12123 return definedNames;
12124 }
12125
12126 /**
12127 * Apply the given prefix to all of the names in the table of defined names.
12128 *
12129 * @param definedNames the names that were defined before this operation
12130 * @param prefixElement the element defining the prefix to be added to the nam es
12131 */
12132 Map<String, Element> apply2(Map<String, Element> definedNames, PrefixElement p refixElement) {
12133 if (prefixElement != null) {
12134 String prefix = prefixElement.name;
12135 Map<String, Element> newNames = new Map<String, Element>();
12136 for (MapEntry<String, Element> entry in getMapEntrySet(definedNames)) {
12137 newNames["${prefix}.${entry.getKey()}"] = entry.getValue();
12138 }
12139 return newNames;
12140 } else {
12141 return definedNames;
12142 }
12143 }
12144
12145 /**
12146 * Create a mapping table representing the export namespace of the given libra ry.
12147 *
12148 * @param library the library whose public namespace is to be created
12149 * @param visitedElements a set of libraries that do not need to be visited wh en processing the
12150 * export directives of the given library because all of the names de fined by them will
12151 * be added by another library
12152 * @return the mapping table that was created
12153 */
12154 Map<String, Element> createExportMapping(LibraryElement library, Set<LibraryEl ement> visitedElements) {
12155 javaSetAdd(visitedElements, library);
12156 try {
12157 Map<String, Element> definedNames = new Map<String, Element>();
12158 for (ExportElement element in library.exports) {
12159 LibraryElement exportedLibrary = element.exportedLibrary;
12160 if (exportedLibrary != null && !visitedElements.contains(exportedLibrary )) {
12161 Map<String, Element> exportedNames = createExportMapping(exportedLibra ry, visitedElements);
12162 exportedNames = apply(exportedNames, element.combinators);
12163 addAll(definedNames, exportedNames);
12164 }
12165 }
12166 addAll2(definedNames, ((library.context as InternalAnalysisContext)).getPu blicNamespace(library));
12167 return definedNames;
12168 } finally {
12169 visitedElements.remove(library);
12170 }
12171 }
12172
12173 /**
12174 * Hide all of the given names by removing them from the given collection of d efined names.
12175 *
12176 * @param definedNames the names that were defined before this operation
12177 * @param hiddenNames the names to be hidden
12178 */
12179 void hide(Map<String, Element> definedNames, List<String> hiddenNames) {
12180 for (String name in hiddenNames) {
12181 definedNames.remove(name);
12182 definedNames.remove("${name}=");
12183 }
12184 }
12185
12186 /**
12187 * Show only the given names by removing all other names from the given collec tion of defined
12188 * names.
12189 *
12190 * @param definedNames the names that were defined before this operation
12191 * @param shownNames the names to be shown
12192 */
12193 Map<String, Element> show(Map<String, Element> definedNames, List<String> show nNames) {
12194 Map<String, Element> newNames = new Map<String, Element>();
12195 for (String name in shownNames) {
12196 Element element = definedNames[name];
12197 if (element != null) {
12198 newNames[name] = element;
12199 }
12200 String setterName = "${name}=";
12201 element = definedNames[setterName];
12202 if (element != null) {
12203 newNames[setterName] = element;
12204 }
12205 }
12206 return newNames;
12207 }
12208 }
12209 /**
12210 * The abstract class `Scope` defines the behavior common to name scopes used by the resolver
12211 * to determine which names are visible at any given point in the code.
12212 *
12213 * @coverage dart.engine.resolver
12214 */
12215 abstract class Scope {
12216
12217 /**
12218 * The prefix used to mark an identifier as being private to its library.
12219 */
12220 static String PRIVATE_NAME_PREFIX = "_";
12221
12222 /**
12223 * The suffix added to the declared name of a setter when looking up the sette r. Used to
12224 * disambiguate between a getter and a setter that have the same name.
12225 */
12226 static String SETTER_SUFFIX = "=";
12227
12228 /**
12229 * The name used to look up the method used to implement the unary minus opera tor. Used to
12230 * disambiguate between the unary and binary operators.
12231 */
12232 static String UNARY_MINUS = "unary-";
12233
12234 /**
12235 * Return `true` if the given name is a library-private name.
12236 *
12237 * @param name the name being tested
12238 * @return `true` if the given name is a library-private name
12239 */
12240 static bool isPrivateName(String name) => name != null && name.startsWith(PRIV ATE_NAME_PREFIX);
12241
12242 /**
12243 * A table mapping names that are defined in this scope to the element represe nting the thing
12244 * declared with that name.
12245 */
12246 Map<String, Element> _definedNames = new Map<String, Element>();
12247
12248 /**
12249 * Add the given element to this scope. If there is already an element with th e given name defined
12250 * in this scope, then an error will be generated and the original element wil l continue to be
12251 * mapped to the name. If there is an element with the given name in an enclos ing scope, then a
12252 * warning will be generated but the given element will hide the inherited ele ment.
12253 *
12254 * @param element the element to be added to this scope
12255 */
12256 void define(Element element) {
12257 String name = getName(element);
12258 if (name != null && !name.isEmpty) {
12259 if (_definedNames.containsKey(name)) {
12260 errorListener.onError(getErrorForDuplicate(_definedNames[name], element) );
12261 } else {
12262 _definedNames[name] = element;
12263 }
12264 }
12265 }
12266
12267 /**
12268 * Return the element with which the given identifier is associated, or `null` if the name
12269 * is not defined within this scope.
12270 *
12271 * @param identifier the identifier associated with the element to be returned
12272 * @param referencingLibrary the library that contains the reference to the na me, used to
12273 * implement library-level privacy
12274 * @return the element with which the given identifier is associated
12275 */
12276 Element lookup(Identifier identifier, LibraryElement referencingLibrary) => lo okup3(identifier, identifier.name, referencingLibrary);
12277
12278 /**
12279 * Add the given element to this scope without checking for duplication or hid ing.
12280 *
12281 * @param element the element to be added to this scope
12282 */
12283 void defineWithoutChecking(Element element) {
12284 _definedNames[getName(element)] = element;
12285 }
12286
12287 /**
12288 * Add the given element to this scope without checking for duplication or hid ing.
12289 *
12290 * @param name the name of the element to be added
12291 * @param element the element to be added to this scope
12292 */
12293 void defineWithoutChecking2(String name, Element element) {
12294 _definedNames[name] = element;
12295 }
12296
12297 /**
12298 * Return the element representing the library in which this scope is enclosed .
12299 *
12300 * @return the element representing the library in which this scope is enclose d
12301 */
12302 LibraryElement get definingLibrary;
12303
12304 /**
12305 * Return the error code to be used when reporting that a name being defined l ocally conflicts
12306 * with another element of the same name in the local scope.
12307 *
12308 * @param existing the first element to be declared with the conflicting name
12309 * @param duplicate another element declared with the conflicting name
12310 * @return the error code used to report duplicate names within a scope
12311 */
12312 AnalysisError getErrorForDuplicate(Element existing, Element duplicate) {
12313 Source source = duplicate.source;
12314 if (source == null) {
12315 source = this.source;
12316 }
12317 return new AnalysisError.con2(source, duplicate.nameOffset, duplicate.displa yName.length, CompileTimeErrorCode.DUPLICATE_DEFINITION, [existing.displayName]) ;
12318 }
12319
12320 /**
12321 * Return the listener that is to be informed when an error is encountered.
12322 *
12323 * @return the listener that is to be informed when an error is encountered
12324 */
12325 AnalysisErrorListener get errorListener;
12326
12327 /**
12328 * Return the source object representing the compilation unit with which error s related to this
12329 * scope should be associated.
12330 *
12331 * @return the source object with which errors should be associated
12332 */
12333 Source get source => definingLibrary.definingCompilationUnit.source;
12334
12335 /**
12336 * Return the element with which the given name is associated, or `null` if th e name is not
12337 * defined within this scope. This method only returns elements that are direc tly defined within
12338 * this scope, not elements that are defined in an enclosing scope.
12339 *
12340 * @param name the name associated with the element to be returned
12341 * @param referencingLibrary the library that contains the reference to the na me, used to
12342 * implement library-level privacy
12343 * @return the element with which the given name is associated
12344 */
12345 Element localLookup(String name, LibraryElement referencingLibrary) => _define dNames[name];
12346
12347 /**
12348 * Return the element with which the given name is associated, or `null` if th e name is not
12349 * defined within this scope.
12350 *
12351 * @param identifier the identifier node to lookup element for, used to report correct kind of a
12352 * problem and associate problem with
12353 * @param name the name associated with the element to be returned
12354 * @param referencingLibrary the library that contains the reference to the na me, used to
12355 * implement library-level privacy
12356 * @return the element with which the given name is associated
12357 */
12358 Element lookup3(Identifier identifier, String name, LibraryElement referencing Library);
12359
12360 /**
12361 * Return the name that will be used to look up the given element.
12362 *
12363 * @param element the element whose look-up name is to be returned
12364 * @return the name that will be used to look up the given element
12365 */
12366 String getName(Element element) {
12367 if (element is MethodElement) {
12368 MethodElement method = element as MethodElement;
12369 if (method.name == "-" && method.parameters.length == 0) {
12370 return UNARY_MINUS;
12371 }
12372 }
12373 return element.name;
12374 }
12375 }
12376 /**
12377 * Instances of the class `ConstantVerifier` traverse an AST structure looking f or additional
12378 * errors and warnings not covered by the parser and resolver. In particular, it looks for errors
12379 * and warnings related to constant expressions.
12380 *
12381 * @coverage dart.engine.resolver
12382 */
12383 class ConstantVerifier extends RecursiveASTVisitor<Object> {
12384
12385 /**
12386 * The error reporter by which errors will be reported.
12387 */
12388 ErrorReporter _errorReporter;
12389
12390 /**
12391 * The type representing the type 'bool'.
12392 */
12393 InterfaceType _boolType;
12394
12395 /**
12396 * The type representing the type 'int'.
12397 */
12398 InterfaceType _intType;
12399
12400 /**
12401 * The type representing the type 'num'.
12402 */
12403 InterfaceType _numType;
12404
12405 /**
12406 * The type representing the type 'string'.
12407 */
12408 InterfaceType _stringType;
12409
12410 /**
12411 * Initialize a newly created constant verifier.
12412 *
12413 * @param errorReporter the error reporter by which errors will be reported
12414 */
12415 ConstantVerifier(ErrorReporter errorReporter, TypeProvider typeProvider) {
12416 this._errorReporter = errorReporter;
12417 this._boolType = typeProvider.boolType;
12418 this._intType = typeProvider.intType;
12419 this._numType = typeProvider.numType;
12420 this._stringType = typeProvider.stringType;
12421 }
12422 Object visitAnnotation(Annotation node) {
12423 super.visitAnnotation(node);
12424 Element element = node.element;
12425 if (element is ConstructorElement) {
12426 ConstructorElement constructorElement = element as ConstructorElement;
12427 if (!constructorElement.isConst) {
12428 _errorReporter.reportError2(CompileTimeErrorCode.NON_CONSTANT_ANNOTATION _CONSTRUCTOR, node, []);
12429 return null;
12430 }
12431 ArgumentList argumentList = node.arguments;
12432 if (argumentList == null) {
12433 _errorReporter.reportError2(CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCT OR_ARGUMENTS, node, []);
12434 return null;
12435 }
12436 validateConstantArguments(argumentList);
12437 }
12438 return null;
12439 }
12440 Object visitConstructorDeclaration(ConstructorDeclaration node) {
12441 if (node.constKeyword != null) {
12442 validateInitializers(node);
12443 }
12444 validateDefaultValues(node.parameters);
12445 return super.visitConstructorDeclaration(node);
12446 }
12447 Object visitFunctionExpression(FunctionExpression node) {
12448 super.visitFunctionExpression(node);
12449 validateDefaultValues(node.parameters);
12450 return null;
12451 }
12452 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
12453 validateConstantArguments2(node);
12454 return super.visitInstanceCreationExpression(node);
12455 }
12456 Object visitListLiteral(ListLiteral node) {
12457 super.visitListLiteral(node);
12458 if (node.constKeyword != null) {
12459 for (Expression element in node.elements) {
12460 validate(element, CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT);
12461 }
12462 }
12463 return null;
12464 }
12465 Object visitMapLiteral(MapLiteral node) {
12466 super.visitMapLiteral(node);
12467 bool isConst = node.constKeyword != null;
12468 bool reportEqualKeys = true;
12469 Set<Object> keys = new Set<Object>();
12470 List<Expression> invalidKeys = new List<Expression>();
12471 for (MapLiteralEntry entry in node.entries) {
12472 Expression key = entry.key;
12473 if (isConst) {
12474 EvaluationResultImpl result = validate(key, CompileTimeErrorCode.NON_CON STANT_MAP_KEY);
12475 validate(entry.value, CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE);
12476 if (result is ValidResult) {
12477 Object value = ((result as ValidResult)).value;
12478 if (keys.contains(value)) {
12479 invalidKeys.add(key);
12480 } else {
12481 javaSetAdd(keys, value);
12482 }
12483 }
12484 } else {
12485 EvaluationResultImpl result = key.accept(new ConstantVisitor());
12486 if (result is ValidResult) {
12487 Object value = ((result as ValidResult)).value;
12488 if (keys.contains(value)) {
12489 invalidKeys.add(key);
12490 } else {
12491 javaSetAdd(keys, value);
12492 }
12493 } else {
12494 reportEqualKeys = false;
12495 }
12496 }
12497 }
12498 if (reportEqualKeys) {
12499 for (Expression key in invalidKeys) {
12500 _errorReporter.reportError2(StaticWarningCode.EQUAL_KEYS_IN_MAP, key, [] );
12501 }
12502 }
12503 return null;
12504 }
12505 Object visitMethodDeclaration(MethodDeclaration node) {
12506 super.visitMethodDeclaration(node);
12507 validateDefaultValues(node.parameters);
12508 return null;
12509 }
12510 Object visitSwitchCase(SwitchCase node) {
12511 super.visitSwitchCase(node);
12512 validate(node.expression, CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION) ;
12513 return null;
12514 }
12515 Object visitVariableDeclaration(VariableDeclaration node) {
12516 super.visitVariableDeclaration(node);
12517 Expression initializer = node.initializer;
12518 if (initializer != null && node.isConst) {
12519 VariableElementImpl element = node.element as VariableElementImpl;
12520 EvaluationResultImpl result = element.evaluationResult;
12521 if (result == null) {
12522 result = validate(initializer, CompileTimeErrorCode.CONST_INITIALIZED_WI TH_NON_CONSTANT_VALUE);
12523 element.evaluationResult = result;
12524 } else if (result is ErrorResult) {
12525 reportErrors(result, CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CON STANT_VALUE);
12526 }
12527 }
12528 return null;
12529 }
12530
12531 /**
12532 * If the given result represents one or more errors, report those errors. Exc ept for special
12533 * cases, use the given error code rather than the one reported in the error.
12534 *
12535 * @param result the result containing any errors that need to be reported
12536 * @param errorCode the error code to be used if the result represents an erro r
12537 */
12538 void reportErrors(EvaluationResultImpl result, ErrorCode errorCode) {
12539 if (result is ErrorResult) {
12540 for (ErrorResult_ErrorData data in ((result as ErrorResult)).errorData) {
12541 ErrorCode dataErrorCode = data.errorCode;
12542 if (identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCE PTION) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRIN G) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL) || ide ntical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_INT) || identical(dat aErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM)) {
12543 _errorReporter.reportError2(dataErrorCode, data.node, []);
12544 } else {
12545 _errorReporter.reportError2(errorCode, data.node, []);
12546 }
12547 }
12548 }
12549 }
12550
12551 /**
12552 * Validate that the given expression is a compile time constant. Return the v alue of the compile
12553 * time constant, or `null` if the expression is not a compile time constant.
12554 *
12555 * @param expression the expression to be validated
12556 * @param errorCode the error code to be used if the expression is not a compi le time constant
12557 * @return the value of the compile time constant
12558 */
12559 EvaluationResultImpl validate(Expression expression, ErrorCode errorCode) {
12560 EvaluationResultImpl result = expression.accept(new ConstantVisitor());
12561 reportErrors(result, errorCode);
12562 return result;
12563 }
12564
12565 /**
12566 * Validate that if the passed arguments are constant expressions.
12567 *
12568 * @param argumentList the argument list to evaluate
12569 */
12570 void validateConstantArguments(ArgumentList argumentList) {
12571 for (Expression argument in argumentList.arguments) {
12572 if (argument is NamedExpression) {
12573 argument = ((argument as NamedExpression)).expression;
12574 }
12575 validate(argument, CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT);
12576 }
12577 }
12578
12579 /**
12580 * Validate that if the passed instance creation is 'const' then all its argum ents are constant
12581 * expressions.
12582 *
12583 * @param node the instance creation evaluate
12584 */
12585 void validateConstantArguments2(InstanceCreationExpression node) {
12586 if (!node.isConst) {
12587 return;
12588 }
12589 ArgumentList argumentList = node.argumentList;
12590 if (argumentList == null) {
12591 return;
12592 }
12593 validateConstantArguments(argumentList);
12594 }
12595
12596 /**
12597 * Validate that the default value associated with each of the parameters in t he given list is a
12598 * compile time constant.
12599 *
12600 * @param parameters the list of parameters to be validated
12601 */
12602 void validateDefaultValues(FormalParameterList parameters) {
12603 if (parameters == null) {
12604 return;
12605 }
12606 for (FormalParameter parameter in parameters.parameters) {
12607 if (parameter is DefaultFormalParameter) {
12608 DefaultFormalParameter defaultParameter = parameter as DefaultFormalPara meter;
12609 Expression defaultValue = defaultParameter.defaultValue;
12610 if (defaultValue != null) {
12611 EvaluationResultImpl result = validate(defaultValue, CompileTimeErrorC ode.NON_CONSTANT_DEFAULT_VALUE);
12612 VariableElementImpl element = parameter.element as VariableElementImpl ;
12613 element.evaluationResult = result;
12614 }
12615 }
12616 }
12617 }
12618
12619 /**
12620 * Validates that the given expression is a compile time constant.
12621 *
12622 * @param parameterElements the elements of parameters of constant constructor , they are
12623 * considered as a valid potentially constant expressions
12624 * @param expression the expression to validate
12625 */
12626 void validateInitializerExpression(List<ParameterElement> parameterElements, E xpression expression) {
12627 EvaluationResultImpl result = expression.accept(new ConstantVisitor_13(this, parameterElements));
12628 reportErrors(result, CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER) ;
12629 }
12630
12631 /**
12632 * Validates that all of the arguments of a constructor initializer are compil e time constants.
12633 *
12634 * @param parameterElements the elements of parameters of constant constructor , they are
12635 * considered as a valid potentially constant expressions
12636 * @param argumentList the argument list to validate
12637 */
12638 void validateInitializerInvocationArguments(List<ParameterElement> parameterEl ements, ArgumentList argumentList) {
12639 if (argumentList == null) {
12640 return;
12641 }
12642 for (Expression argument in argumentList.arguments) {
12643 validateInitializerExpression(parameterElements, argument);
12644 }
12645 }
12646
12647 /**
12648 * Validates that the expressions of the given initializers (of a constant con structor) are all
12649 * compile time constants.
12650 *
12651 * @param constructor the constant constructor declaration to validate
12652 */
12653 void validateInitializers(ConstructorDeclaration constructor) {
12654 List<ParameterElement> parameterElements = constructor.parameters.parameterE lements;
12655 NodeList<ConstructorInitializer> initializers = constructor.initializers;
12656 for (ConstructorInitializer initializer in initializers) {
12657 if (initializer is ConstructorFieldInitializer) {
12658 ConstructorFieldInitializer fieldInitializer = initializer as Constructo rFieldInitializer;
12659 validateInitializerExpression(parameterElements, fieldInitializer.expres sion);
12660 }
12661 if (initializer is RedirectingConstructorInvocation) {
12662 RedirectingConstructorInvocation invocation = initializer as Redirecting ConstructorInvocation;
12663 validateInitializerInvocationArguments(parameterElements, invocation.arg umentList);
12664 }
12665 if (initializer is SuperConstructorInvocation) {
12666 SuperConstructorInvocation invocation = initializer as SuperConstructorI nvocation;
12667 validateInitializerInvocationArguments(parameterElements, invocation.arg umentList);
12668 }
12669 }
12670 }
12671 }
12672 class ConstantVisitor_13 extends ConstantVisitor {
12673 final ConstantVerifier ConstantVerifier_this;
12674 List<ParameterElement> parameterElements;
12675 ConstantVisitor_13(this.ConstantVerifier_this, this.parameterElements) : super ();
12676 EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) {
12677 Element element = node.staticElement;
12678 for (ParameterElement parameterElement in parameterElements) {
12679 if (identical(parameterElement, element) && parameterElement != null) {
12680 Type2 type = parameterElement.type;
12681 if (type != null) {
12682 if (type.isDynamic) {
12683 return ValidResult.RESULT_DYNAMIC;
12684 }
12685 if (type.isSubtypeOf(ConstantVerifier_this._boolType)) {
12686 return ValidResult.RESULT_BOOL;
12687 }
12688 if (type.isSubtypeOf(ConstantVerifier_this._intType)) {
12689 return ValidResult.RESULT_INT;
12690 }
12691 if (type.isSubtypeOf(ConstantVerifier_this._numType)) {
12692 return ValidResult.RESULT_NUM;
12693 }
12694 if (type.isSubtypeOf(ConstantVerifier_this._stringType)) {
12695 return ValidResult.RESULT_STRING;
12696 }
12697 }
12698 return ValidResult.RESULT_OBJECT;
12699 }
12700 }
12701 return super.visitSimpleIdentifier(node);
12702 }
12703 }
12704 /**
12705 * Instances of the class `ErrorVerifier` traverse an AST structure looking for additional
12706 * errors and warnings not covered by the parser and resolver.
12707 *
12708 * @coverage dart.engine.resolver
12709 */
12710 class ErrorVerifier extends RecursiveASTVisitor<Object> {
12711
12712 /**
12713 * Checks if the given expression is the reference to the type.
12714 *
12715 * @param expr the expression to evaluate
12716 * @return `true` if the given expression is the reference to the type
12717 */
12718 static bool isTypeReference(Expression expr) {
12719 if (expr is Identifier) {
12720 Identifier identifier = expr as Identifier;
12721 return identifier.staticElement is ClassElement;
12722 }
12723 return false;
12724 }
12725
12726 /**
12727 * The error reporter by which errors will be reported.
12728 */
12729 ErrorReporter _errorReporter;
12730
12731 /**
12732 * The current library that is being analyzed.
12733 */
12734 LibraryElement _currentLibrary;
12735
12736 /**
12737 * The type representing the type 'dynamic'.
12738 */
12739 Type2 _dynamicType;
12740
12741 /**
12742 * The object providing access to the types defined by the language.
12743 */
12744 TypeProvider _typeProvider;
12745
12746 /**
12747 * The manager for the inheritance mappings.
12748 */
12749 InheritanceManager _inheritanceManager;
12750
12751 /**
12752 * A flag indicating whether we are running in strict mode. In strict mode, er ror reporting is
12753 * based exclusively on the static type information.
12754 */
12755 bool _strictMode = false;
12756
12757 /**
12758 * This is set to `true` iff the visitor is currently visiting children nodes of a
12759 * [ConstructorDeclaration] and the constructor is 'const'.
12760 *
12761 * @see #visitConstructorDeclaration(ConstructorDeclaration)
12762 */
12763 bool _isEnclosingConstructorConst = false;
12764
12765 /**
12766 * This is set to `true` iff the visitor is currently visiting children nodes of a
12767 * [CatchClause].
12768 *
12769 * @see #visitCatchClause(CatchClause)
12770 */
12771 bool _isInCatchClause = false;
12772
12773 /**
12774 * This is set to `true` iff the visitor is currently visiting children nodes of an
12775 * [Comment].
12776 */
12777 bool _isInComment = false;
12778
12779 /**
12780 * This is set to `true` iff the visitor is currently visiting children nodes of an
12781 * [InstanceCreationExpression].
12782 */
12783 bool _isInConstInstanceCreation = false;
12784
12785 /**
12786 * This is set to `true` iff the visitor is currently visiting children nodes of a native
12787 * [ClassDeclaration].
12788 */
12789 bool _isInNativeClass = false;
12790
12791 /**
12792 * This is set to `true` iff the visitor is currently visiting a static variab le
12793 * declaration.
12794 */
12795 bool _isInStaticVariableDeclaration = false;
12796
12797 /**
12798 * This is set to `true` iff the visitor is currently visiting an instance var iable
12799 * declaration.
12800 */
12801 bool _isInInstanceVariableDeclaration = false;
12802
12803 /**
12804 * This is set to `true` iff the visitor is currently visiting an instance var iable
12805 * initializer.
12806 */
12807 bool _isInInstanceVariableInitializer = false;
12808
12809 /**
12810 * This is set to `true` iff the visitor is currently visiting a
12811 * [ConstructorInitializer].
12812 */
12813 bool _isInConstructorInitializer = false;
12814
12815 /**
12816 * This is set to `true` iff the visitor is currently visiting a
12817 * [FunctionTypedFormalParameter].
12818 */
12819 bool _isInFunctionTypedFormalParameter = false;
12820
12821 /**
12822 * This is set to `true` iff the visitor is currently visiting a static method . By "method"
12823 * here getter, setter and operator declarations are also implied since they a re all represented
12824 * with a [MethodDeclaration] in the AST structure.
12825 */
12826 bool _isInStaticMethod = false;
12827
12828 /**
12829 * This is set to `true` iff the visitor is currently visiting code in the SDK .
12830 */
12831 bool _isInSystemLibrary = false;
12832
12833 /**
12834 * The class containing the AST nodes being visited, or `null` if we are not i n the scope of
12835 * a class.
12836 */
12837 ClassElement _enclosingClass;
12838
12839 /**
12840 * The method or function that we are currently visiting, or `null` if we are not inside a
12841 * method or function.
12842 */
12843 ExecutableElement _enclosingFunction;
12844
12845 /**
12846 * The number of return statements found in the method or function that we are currently visiting
12847 * that have a return value.
12848 */
12849 int _returnWithCount = 0;
12850
12851 /**
12852 * The number of return statements found in the method or function that we are currently visiting
12853 * that do not have a return value.
12854 */
12855 int _returnWithoutCount = 0;
12856
12857 /**
12858 * This map is initialized when visiting the contents of a class declaration. If the visitor is
12859 * not in an enclosing class declaration, then the map is set to `null`.
12860 *
12861 * When set the map maps the set of [FieldElement]s in the class to an
12862 * [INIT_STATE#NOT_INIT] or [INIT_STATE#INIT_IN_DECLARATION]. <code>checkFor*< /code>
12863 * methods, specifically [checkForAllFinalInitializedErrorCodes],
12864 * can make a copy of the map to compute error code states. <code>checkFor*</c ode> methods should
12865 * only ever make a copy, or read from this map after it has been set in
12866 * [visitClassDeclaration].
12867 *
12868 * @see #visitClassDeclaration(ClassDeclaration)
12869 * @see #checkForAllFinalInitializedErrorCodes(ConstructorDeclaration)
12870 */
12871 Map<FieldElement, INIT_STATE> _initialFieldElementsMap;
12872
12873 /**
12874 * A table mapping name of the library to the export directive which export th is library.
12875 */
12876 Map<String, LibraryElement> _nameToExportElement = new Map<String, LibraryElem ent>();
12877
12878 /**
12879 * A table mapping name of the library to the import directive which import th is library.
12880 */
12881 Map<String, LibraryElement> _nameToImportElement = new Map<String, LibraryElem ent>();
12882
12883 /**
12884 * A table mapping names to the export elements exported them.
12885 */
12886 Map<String, ExportElement> _exportedNames = new Map<String, ExportElement>();
12887
12888 /**
12889 * A set of the names of the variable initializers we are visiting now.
12890 */
12891 Set<String> _namesForReferenceToDeclaredVariableInInitializer = new Set<String >();
12892
12893 /**
12894 * A list of types used by the [CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS] and
12895 * [CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS] error codes.
12896 */
12897 List<InterfaceType> _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT;
12898 ErrorVerifier(ErrorReporter errorReporter, LibraryElement currentLibrary, Type Provider typeProvider, InheritanceManager inheritanceManager) {
12899 this._errorReporter = errorReporter;
12900 this._currentLibrary = currentLibrary;
12901 this._isInSystemLibrary = currentLibrary.source.isInSystemLibrary;
12902 this._typeProvider = typeProvider;
12903 this._inheritanceManager = inheritanceManager;
12904 _strictMode = currentLibrary.context.analysisOptions.strictMode;
12905 _isEnclosingConstructorConst = false;
12906 _isInCatchClause = false;
12907 _isInStaticVariableDeclaration = false;
12908 _isInInstanceVariableDeclaration = false;
12909 _isInInstanceVariableInitializer = false;
12910 _isInConstructorInitializer = false;
12911 _isInStaticMethod = false;
12912 _dynamicType = typeProvider.dynamicType;
12913 _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMENT = <InterfaceType> [
12914 typeProvider.nullType,
12915 typeProvider.numType,
12916 typeProvider.intType,
12917 typeProvider.doubleType,
12918 typeProvider.boolType,
12919 typeProvider.stringType];
12920 }
12921 Object visitArgumentDefinitionTest(ArgumentDefinitionTest node) {
12922 checkForArgumentDefinitionTestNonParameter(node);
12923 return super.visitArgumentDefinitionTest(node);
12924 }
12925 Object visitArgumentList(ArgumentList node) {
12926 checkForArgumentTypeNotAssignable(node);
12927 return super.visitArgumentList(node);
12928 }
12929 Object visitAssertStatement(AssertStatement node) {
12930 checkForNonBoolExpression(node);
12931 return super.visitAssertStatement(node);
12932 }
12933 Object visitAssignmentExpression(AssignmentExpression node) {
12934 sc.Token operator = node.operator;
12935 sc.TokenType operatorType = operator.type;
12936 if (identical(operatorType, sc.TokenType.EQ)) {
12937 checkForInvalidAssignment2(node.leftHandSide, node.rightHandSide);
12938 } else {
12939 checkForInvalidAssignment(node);
12940 }
12941 checkForAssignmentToFinal(node);
12942 checkForArgumentTypeNotAssignable2(node.rightHandSide);
12943 return super.visitAssignmentExpression(node);
12944 }
12945 Object visitBinaryExpression(BinaryExpression node) {
12946 checkForArgumentTypeNotAssignable2(node.rightOperand);
12947 return super.visitBinaryExpression(node);
12948 }
12949 Object visitBlockFunctionBody(BlockFunctionBody node) {
12950 int previousReturnWithCount = _returnWithCount;
12951 int previousReturnWithoutCount = _returnWithoutCount;
12952 try {
12953 _returnWithCount = 0;
12954 _returnWithoutCount = 0;
12955 super.visitBlockFunctionBody(node);
12956 checkForMixedReturns(node);
12957 } finally {
12958 _returnWithCount = previousReturnWithCount;
12959 _returnWithoutCount = previousReturnWithoutCount;
12960 }
12961 return null;
12962 }
12963 Object visitCatchClause(CatchClause node) {
12964 bool previousIsInCatchClause = _isInCatchClause;
12965 try {
12966 _isInCatchClause = true;
12967 return super.visitCatchClause(node);
12968 } finally {
12969 _isInCatchClause = previousIsInCatchClause;
12970 }
12971 }
12972 Object visitClassDeclaration(ClassDeclaration node) {
12973 ClassElement outerClass = _enclosingClass;
12974 try {
12975 _isInNativeClass = node.nativeClause != null;
12976 _enclosingClass = node.element;
12977 WithClause withClause = node.withClause;
12978 ImplementsClause implementsClause = node.implementsClause;
12979 ExtendsClause extendsClause = node.extendsClause;
12980 checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_I DENTIFIER_AS_TYPE_NAME);
12981 checkForMemberWithClassName();
12982 checkForNoDefaultSuperConstructorImplicit(node);
12983 checkForAllMixinErrorCodes(withClause);
12984 checkForConflictingTypeVariableErrorCodes(node);
12985 if (implementsClause != null || extendsClause != null) {
12986 if (!checkForImplementsDisallowedClass(implementsClause) && !checkForExt endsDisallowedClass(extendsClause)) {
12987 checkForNonAbstractClassInheritsAbstractMember(node);
12988 checkForInconsistentMethodInheritance();
12989 checkForRecursiveInterfaceInheritance(_enclosingClass);
12990 }
12991 }
12992 ClassElement classElement = node.element;
12993 if (classElement != null) {
12994 List<FieldElement> fieldElements = classElement.fields;
12995 _initialFieldElementsMap = new Map<FieldElement, INIT_STATE>();
12996 for (FieldElement fieldElement in fieldElements) {
12997 if (!fieldElement.isSynthetic) {
12998 _initialFieldElementsMap[fieldElement] = fieldElement.initializer == null ? INIT_STATE.NOT_INIT : INIT_STATE.INIT_IN_DECLARATION;
12999 }
13000 }
13001 }
13002 checkForFinalNotInitialized(node);
13003 checkForDuplicateDefinitionInheritance();
13004 checkForConflictingGetterAndMethod();
13005 checkImplementsSuperClass(node);
13006 checkImplementsFunctionWithoutCall(node);
13007 return super.visitClassDeclaration(node);
13008 } finally {
13009 _isInNativeClass = false;
13010 _initialFieldElementsMap = null;
13011 _enclosingClass = outerClass;
13012 }
13013 }
13014 Object visitClassTypeAlias(ClassTypeAlias node) {
13015 checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDE NTIFIER_AS_TYPEDEF_NAME);
13016 checkForAllMixinErrorCodes(node.withClause);
13017 ClassElement outerClassElement = _enclosingClass;
13018 try {
13019 _enclosingClass = node.element;
13020 checkForRecursiveInterfaceInheritance(node.element);
13021 checkForTypeAliasCannotReferenceItself_mixin(node);
13022 } finally {
13023 _enclosingClass = outerClassElement;
13024 }
13025 return super.visitClassTypeAlias(node);
13026 }
13027 Object visitComment(Comment node) {
13028 _isInComment = true;
13029 try {
13030 return super.visitComment(node);
13031 } finally {
13032 _isInComment = false;
13033 }
13034 }
13035 Object visitConditionalExpression(ConditionalExpression node) {
13036 checkForNonBoolCondition(node.condition);
13037 return super.visitConditionalExpression(node);
13038 }
13039 Object visitConstructorDeclaration(ConstructorDeclaration node) {
13040 ExecutableElement outerFunction = _enclosingFunction;
13041 try {
13042 _enclosingFunction = node.element;
13043 _isEnclosingConstructorConst = node.constKeyword != null;
13044 checkForConstConstructorWithNonFinalField(node);
13045 checkForConstConstructorWithNonConstSuper(node);
13046 checkForConflictingConstructorNameAndMember(node);
13047 checkForAllFinalInitializedErrorCodes(node);
13048 checkForRedirectingConstructorErrorCodes(node);
13049 checkForMultipleSuperInitializers(node);
13050 checkForRecursiveConstructorRedirect(node);
13051 if (!checkForRecursiveFactoryRedirect(node)) {
13052 checkForAllRedirectConstructorErrorCodes(node);
13053 }
13054 checkForUndefinedConstructorInInitializerImplicit(node);
13055 checkForRedirectToNonConstConstructor(node);
13056 checkForReturnInGenerativeConstructor(node);
13057 return super.visitConstructorDeclaration(node);
13058 } finally {
13059 _isEnclosingConstructorConst = false;
13060 _enclosingFunction = outerFunction;
13061 }
13062 }
13063 Object visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
13064 _isInConstructorInitializer = true;
13065 try {
13066 checkForFieldInitializerNotAssignable(node);
13067 return super.visitConstructorFieldInitializer(node);
13068 } finally {
13069 _isInConstructorInitializer = false;
13070 }
13071 }
13072 Object visitDefaultFormalParameter(DefaultFormalParameter node) {
13073 checkForInvalidAssignment2(node.identifier, node.defaultValue);
13074 checkForDefaultValueInFunctionTypedParameter(node);
13075 return super.visitDefaultFormalParameter(node);
13076 }
13077 Object visitDoStatement(DoStatement node) {
13078 checkForNonBoolCondition(node.condition);
13079 return super.visitDoStatement(node);
13080 }
13081 Object visitExportDirective(ExportDirective node) {
13082 checkForAmbiguousExport(node);
13083 checkForExportDuplicateLibraryName(node);
13084 checkForExportInternalLibrary(node);
13085 return super.visitExportDirective(node);
13086 }
13087 Object visitExpressionFunctionBody(ExpressionFunctionBody node) {
13088 FunctionType functionType = _enclosingFunction == null ? null : _enclosingFu nction.type;
13089 Type2 expectedReturnType = functionType == null ? DynamicTypeImpl.instance : functionType.returnType;
13090 checkForReturnOfInvalidType(node.expression, expectedReturnType);
13091 return super.visitExpressionFunctionBody(node);
13092 }
13093 Object visitFieldDeclaration(FieldDeclaration node) {
13094 if (!node.isStatic) {
13095 VariableDeclarationList variables = node.fields;
13096 if (variables.isConst) {
13097 _errorReporter.reportError4(CompileTimeErrorCode.CONST_INSTANCE_FIELD, v ariables.keyword, []);
13098 }
13099 }
13100 _isInStaticVariableDeclaration = node.isStatic;
13101 _isInInstanceVariableDeclaration = !_isInStaticVariableDeclaration;
13102 try {
13103 checkForAllInvalidOverrideErrorCodes2(node);
13104 return super.visitFieldDeclaration(node);
13105 } finally {
13106 _isInStaticVariableDeclaration = false;
13107 _isInInstanceVariableDeclaration = false;
13108 }
13109 }
13110 Object visitFieldFormalParameter(FieldFormalParameter node) {
13111 checkForConstFormalParameter(node);
13112 checkForPrivateOptionalParameter(node);
13113 checkForFieldInitializingFormalRedirectingConstructor(node);
13114 return super.visitFieldFormalParameter(node);
13115 }
13116 Object visitFunctionDeclaration(FunctionDeclaration node) {
13117 ExecutableElement outerFunction = _enclosingFunction;
13118 try {
13119 SimpleIdentifier identifier = node.name;
13120 String methodName = "";
13121 if (identifier != null) {
13122 methodName = identifier.name;
13123 }
13124 _enclosingFunction = node.element;
13125 if (node.isSetter || node.isGetter) {
13126 checkForMismatchedAccessorTypes(node, methodName);
13127 if (node.isSetter) {
13128 FunctionExpression functionExpression = node.functionExpression;
13129 if (functionExpression != null) {
13130 checkForWrongNumberOfParametersForSetter(node.name, functionExpressi on.parameters);
13131 }
13132 TypeName returnType = node.returnType;
13133 checkForNonVoidReturnTypeForSetter(returnType);
13134 }
13135 }
13136 return super.visitFunctionDeclaration(node);
13137 } finally {
13138 _enclosingFunction = outerFunction;
13139 }
13140 }
13141 Object visitFunctionExpression(FunctionExpression node) {
13142 if (node.parent is! FunctionDeclaration) {
13143 ExecutableElement outerFunction = _enclosingFunction;
13144 try {
13145 _enclosingFunction = node.element;
13146 return super.visitFunctionExpression(node);
13147 } finally {
13148 _enclosingFunction = outerFunction;
13149 }
13150 } else {
13151 return super.visitFunctionExpression(node);
13152 }
13153 }
13154 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
13155 Expression functionExpression = node.function;
13156 Type2 expressionType = functionExpression.staticType;
13157 if (!isFunctionType(expressionType)) {
13158 _errorReporter.reportError2(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTI ON_EXPRESSION, functionExpression, []);
13159 }
13160 return super.visitFunctionExpressionInvocation(node);
13161 }
13162 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
13163 checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDE NTIFIER_AS_TYPEDEF_NAME);
13164 checkForDefaultValueInFunctionTypeAlias(node);
13165 checkForTypeAliasCannotReferenceItself_function(node);
13166 return super.visitFunctionTypeAlias(node);
13167 }
13168 Object visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
13169 bool old = _isInFunctionTypedFormalParameter;
13170 _isInFunctionTypedFormalParameter = true;
13171 try {
13172 return super.visitFunctionTypedFormalParameter(node);
13173 } finally {
13174 _isInFunctionTypedFormalParameter = old;
13175 }
13176 }
13177 Object visitIfStatement(IfStatement node) {
13178 checkForNonBoolCondition(node.condition);
13179 return super.visitIfStatement(node);
13180 }
13181 Object visitImportDirective(ImportDirective node) {
13182 checkForImportDuplicateLibraryName(node);
13183 checkForImportInternalLibrary(node);
13184 return super.visitImportDirective(node);
13185 }
13186 Object visitIndexExpression(IndexExpression node) {
13187 checkForArgumentTypeNotAssignable2(node.index);
13188 return super.visitIndexExpression(node);
13189 }
13190 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
13191 _isInConstInstanceCreation = node.isConst;
13192 try {
13193 ConstructorName constructorName = node.constructorName;
13194 TypeName typeName = constructorName.type;
13195 Type2 type = typeName.type;
13196 if (type is InterfaceType) {
13197 InterfaceType interfaceType = type as InterfaceType;
13198 checkForConstOrNewWithAbstractClass(node, typeName, interfaceType);
13199 if (_isInConstInstanceCreation) {
13200 checkForConstWithNonConst(node);
13201 checkForConstWithUndefinedConstructor(node);
13202 checkForConstWithTypeParameters(node);
13203 } else {
13204 checkForNewWithUndefinedConstructor(node);
13205 }
13206 }
13207 return super.visitInstanceCreationExpression(node);
13208 } finally {
13209 _isInConstInstanceCreation = false;
13210 }
13211 }
13212 Object visitListLiteral(ListLiteral node) {
13213 if (node.constKeyword != null) {
13214 TypeArgumentList typeArguments = node.typeArguments;
13215 if (typeArguments != null) {
13216 NodeList<TypeName> arguments = typeArguments.arguments;
13217 if (arguments.length != 0) {
13218 checkForInvalidTypeArgumentInConstTypedLiteral(arguments, CompileTimeE rrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST);
13219 }
13220 }
13221 }
13222 checkForExpectedOneListTypeArgument(node);
13223 checkForListElementTypeNotAssignable(node);
13224 return super.visitListLiteral(node);
13225 }
13226 Object visitMapLiteral(MapLiteral node) {
13227 TypeArgumentList typeArguments = node.typeArguments;
13228 if (typeArguments != null) {
13229 NodeList<TypeName> arguments = typeArguments.arguments;
13230 if (arguments.length != 0) {
13231 if (node.constKeyword != null) {
13232 checkForInvalidTypeArgumentInConstTypedLiteral(arguments, CompileTimeE rrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP);
13233 }
13234 }
13235 }
13236 checkExpectedTwoMapTypeArguments(typeArguments);
13237 checkForNonConstMapAsExpressionStatement(node);
13238 checkForMapTypeNotAssignable(node);
13239 checkForConstMapKeyExpressionTypeImplementsEquals2(node);
13240 return super.visitMapLiteral(node);
13241 }
13242 Object visitMethodDeclaration(MethodDeclaration node) {
13243 ExecutableElement previousFunction = _enclosingFunction;
13244 try {
13245 _isInStaticMethod = node.isStatic;
13246 _enclosingFunction = node.element;
13247 SimpleIdentifier identifier = node.name;
13248 String methodName = "";
13249 if (identifier != null) {
13250 methodName = identifier.name;
13251 }
13252 if (node.isSetter || node.isGetter) {
13253 checkForMismatchedAccessorTypes(node, methodName);
13254 checkForConflictingInstanceGetterAndSuperclassMember(node);
13255 }
13256 if (node.isGetter) {
13257 checkForConflictingStaticGetterAndInstanceSetter(node);
13258 } else if (node.isSetter) {
13259 checkForWrongNumberOfParametersForSetter(node.name, node.parameters);
13260 checkForNonVoidReturnTypeForSetter(node.returnType);
13261 checkForConflictingStaticSetterAndInstanceMember(node);
13262 } else if (node.isOperator) {
13263 checkForOptionalParameterInOperator(node);
13264 checkForWrongNumberOfParametersForOperator(node);
13265 checkForNonVoidReturnTypeForOperator(node);
13266 }
13267 checkForConcreteClassWithAbstractMember(node);
13268 checkForAllInvalidOverrideErrorCodes3(node);
13269 return super.visitMethodDeclaration(node);
13270 } finally {
13271 _enclosingFunction = previousFunction;
13272 _isInStaticMethod = false;
13273 }
13274 }
13275 Object visitMethodInvocation(MethodInvocation node) {
13276 Expression target = node.realTarget;
13277 SimpleIdentifier methodName = node.methodName;
13278 checkForStaticAccessToInstanceMember(target, methodName);
13279 checkForInstanceAccessToStaticMember(target, methodName);
13280 if (target == null) {
13281 checkForUnqualifiedReferenceToNonLocalStaticMember(methodName);
13282 }
13283 return super.visitMethodInvocation(node);
13284 }
13285 Object visitNativeClause(NativeClause node) {
13286 if (!_isInSystemLibrary) {
13287 _errorReporter.reportError2(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node, []);
13288 }
13289 return super.visitNativeClause(node);
13290 }
13291 Object visitNativeFunctionBody(NativeFunctionBody node) {
13292 checkForNativeFunctionBodyInNonSDKCode(node);
13293 return super.visitNativeFunctionBody(node);
13294 }
13295 Object visitPostfixExpression(PostfixExpression node) {
13296 checkForAssignmentToFinal2(node.operand);
13297 checkForIntNotAssignable(node.operand);
13298 return super.visitPostfixExpression(node);
13299 }
13300 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
13301 if (node.parent is! Annotation) {
13302 checkForStaticAccessToInstanceMember(node.prefix, node.identifier);
13303 checkForInstanceAccessToStaticMember(node.prefix, node.identifier);
13304 }
13305 return super.visitPrefixedIdentifier(node);
13306 }
13307 Object visitPrefixExpression(PrefixExpression node) {
13308 if (node.operator.type.isIncrementOperator) {
13309 checkForAssignmentToFinal2(node.operand);
13310 }
13311 checkForIntNotAssignable(node.operand);
13312 return super.visitPrefixExpression(node);
13313 }
13314 Object visitPropertyAccess(PropertyAccess node) {
13315 Expression target = node.realTarget;
13316 SimpleIdentifier propertyName = node.propertyName;
13317 checkForStaticAccessToInstanceMember(target, propertyName);
13318 checkForInstanceAccessToStaticMember(target, propertyName);
13319 return super.visitPropertyAccess(node);
13320 }
13321 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
13322 _isInConstructorInitializer = true;
13323 try {
13324 return super.visitRedirectingConstructorInvocation(node);
13325 } finally {
13326 _isInConstructorInitializer = false;
13327 }
13328 }
13329 Object visitRethrowExpression(RethrowExpression node) {
13330 checkForRethrowOutsideCatch(node);
13331 return super.visitRethrowExpression(node);
13332 }
13333 Object visitReturnStatement(ReturnStatement node) {
13334 if (node.expression == null) {
13335 _returnWithoutCount++;
13336 } else {
13337 _returnWithCount++;
13338 }
13339 checkForAllReturnStatementErrorCodes(node);
13340 return super.visitReturnStatement(node);
13341 }
13342 Object visitSimpleFormalParameter(SimpleFormalParameter node) {
13343 checkForConstFormalParameter(node);
13344 checkForPrivateOptionalParameter(node);
13345 return super.visitSimpleFormalParameter(node);
13346 }
13347 Object visitSimpleIdentifier(SimpleIdentifier node) {
13348 checkForReferenceToDeclaredVariableInInitializer(node);
13349 checkForImplicitThisReferenceInInitializer(node);
13350 if (!isUnqualifiedReferenceToNonLocalStaticMemberAllowed(node)) {
13351 checkForUnqualifiedReferenceToNonLocalStaticMember(node);
13352 }
13353 return super.visitSimpleIdentifier(node);
13354 }
13355 Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
13356 _isInConstructorInitializer = true;
13357 try {
13358 return super.visitSuperConstructorInvocation(node);
13359 } finally {
13360 _isInConstructorInitializer = false;
13361 }
13362 }
13363 Object visitSwitchStatement(SwitchStatement node) {
13364 checkForInconsistentCaseExpressionTypes(node);
13365 checkForSwitchExpressionNotAssignable(node);
13366 checkForCaseBlocksNotTerminated(node);
13367 return super.visitSwitchStatement(node);
13368 }
13369 Object visitThisExpression(ThisExpression node) {
13370 checkForInvalidReferenceToThis(node);
13371 return super.visitThisExpression(node);
13372 }
13373 Object visitThrowExpression(ThrowExpression node) {
13374 checkForConstEvalThrowsException(node);
13375 return super.visitThrowExpression(node);
13376 }
13377 Object visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
13378 checkForFinalNotInitialized2(node.variables);
13379 return super.visitTopLevelVariableDeclaration(node);
13380 }
13381 Object visitTypeName(TypeName node) {
13382 checkForTypeArgumentNotMatchingBounds(node);
13383 checkForTypeParameterReferencedByStatic(node);
13384 return super.visitTypeName(node);
13385 }
13386 Object visitTypeParameter(TypeParameter node) {
13387 checkForBuiltInIdentifierAsName(node.name, CompileTimeErrorCode.BUILT_IN_IDE NTIFIER_AS_TYPE_PARAMETER_NAME);
13388 checkForTypeParameterSupertypeOfItsBound(node);
13389 return super.visitTypeParameter(node);
13390 }
13391 Object visitVariableDeclaration(VariableDeclaration node) {
13392 SimpleIdentifier nameNode = node.name;
13393 Expression initializerNode = node.initializer;
13394 checkForInvalidAssignment2(nameNode, initializerNode);
13395 nameNode.accept(this);
13396 String name = nameNode.name;
13397 javaSetAdd(_namesForReferenceToDeclaredVariableInInitializer, name);
13398 _isInInstanceVariableInitializer = _isInInstanceVariableDeclaration;
13399 try {
13400 if (initializerNode != null) {
13401 initializerNode.accept(this);
13402 }
13403 } finally {
13404 _isInInstanceVariableInitializer = false;
13405 _namesForReferenceToDeclaredVariableInInitializer.remove(name);
13406 }
13407 return null;
13408 }
13409 Object visitVariableDeclarationList(VariableDeclarationList node) => super.vis itVariableDeclarationList(node);
13410 Object visitVariableDeclarationStatement(VariableDeclarationStatement node) {
13411 checkForFinalNotInitialized2(node.variables);
13412 return super.visitVariableDeclarationStatement(node);
13413 }
13414 Object visitWhileStatement(WhileStatement node) {
13415 checkForNonBoolCondition(node.condition);
13416 return super.visitWhileStatement(node);
13417 }
13418
13419 /**
13420 * This verifies if the passed map literal has type arguments then there is ex actly two.
13421 *
13422 * @param node the map literal to evaluate
13423 * @return `true` if and only if an error code is generated on the passed node
13424 * @see StaticTypeWarningCode#EXPECTED_TWO_MAP_TYPE_ARGUMENTS
13425 */
13426 bool checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) {
13427 if (typeArguments == null) {
13428 return false;
13429 }
13430 int num = typeArguments.arguments.length;
13431 if (num == 2) {
13432 return false;
13433 }
13434 _errorReporter.reportError2(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGU MENTS, typeArguments, [num]);
13435 return true;
13436 }
13437
13438 /**
13439 * This verifies that the passed constructor declaration does not violate any of the error codes
13440 * relating to the initialization of fields in the enclosing class.
13441 *
13442 * @param node the [ConstructorDeclaration] to evaluate
13443 * @return `true` if and only if an error code is generated on the passed node
13444 * @see #initialFieldElementsMap
13445 * @see CompileTimeErrorCode#FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR
13446 * @see CompileTimeErrorCode#FINAL_INITIALIZED_MULTIPLE_TIMES
13447 */
13448 bool checkForAllFinalInitializedErrorCodes(ConstructorDeclaration node) {
13449 if (node.factoryKeyword != null || node.redirectedConstructor != null || nod e.externalKeyword != null) {
13450 return false;
13451 }
13452 if (_isInNativeClass) {
13453 return false;
13454 }
13455 bool foundError = false;
13456 Map<FieldElement, INIT_STATE> fieldElementsMap = new Map<FieldElement, INIT_ STATE>.from(_initialFieldElementsMap);
13457 NodeList<FormalParameter> formalParameters = node.parameters.parameters;
13458 for (FormalParameter formalParameter in formalParameters) {
13459 FormalParameter parameter = formalParameter;
13460 if (parameter is DefaultFormalParameter) {
13461 parameter = ((parameter as DefaultFormalParameter)).parameter;
13462 }
13463 if (parameter is FieldFormalParameter) {
13464 FieldElement fieldElement = ((parameter.element as FieldFormalParameterE lementImpl)).field;
13465 INIT_STATE state = fieldElementsMap[fieldElement];
13466 if (identical(state, INIT_STATE.NOT_INIT)) {
13467 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_FIELD_FORMAL;
13468 } else if (identical(state, INIT_STATE.INIT_IN_DECLARATION)) {
13469 if (fieldElement.isFinal || fieldElement.isConst) {
13470 _errorReporter.reportError2(StaticWarningCode.FINAL_INITIALIZED_IN_D ECLARATION_AND_CONSTRUCTOR, formalParameter.identifier, [fieldElement.displayNam e]);
13471 foundError = true;
13472 }
13473 } else if (identical(state, INIT_STATE.INIT_IN_FIELD_FORMAL)) {
13474 if (fieldElement.isFinal || fieldElement.isConst) {
13475 _errorReporter.reportError2(CompileTimeErrorCode.FINAL_INITIALIZED_M ULTIPLE_TIMES, formalParameter.identifier, [fieldElement.displayName]);
13476 foundError = true;
13477 }
13478 }
13479 }
13480 }
13481 NodeList<ConstructorInitializer> initializers = node.initializers;
13482 for (ConstructorInitializer constructorInitializer in initializers) {
13483 if (constructorInitializer is RedirectingConstructorInvocation) {
13484 return false;
13485 }
13486 if (constructorInitializer is ConstructorFieldInitializer) {
13487 ConstructorFieldInitializer constructorFieldInitializer = constructorIni tializer as ConstructorFieldInitializer;
13488 SimpleIdentifier fieldName = constructorFieldInitializer.fieldName;
13489 Element element = fieldName.staticElement;
13490 if (element is FieldElement) {
13491 FieldElement fieldElement = element as FieldElement;
13492 INIT_STATE state = fieldElementsMap[fieldElement];
13493 if (identical(state, INIT_STATE.NOT_INIT)) {
13494 fieldElementsMap[fieldElement] = INIT_STATE.INIT_IN_INITIALIZERS;
13495 } else if (identical(state, INIT_STATE.INIT_IN_DECLARATION)) {
13496 if (fieldElement.isFinal || fieldElement.isConst) {
13497 _errorReporter.reportError2(StaticWarningCode.FIELD_INITIALIZED_IN _INITIALIZER_AND_DECLARATION, fieldName, []);
13498 foundError = true;
13499 }
13500 } else if (identical(state, INIT_STATE.INIT_IN_FIELD_FORMAL)) {
13501 _errorReporter.reportError2(CompileTimeErrorCode.FIELD_INITIALIZED_I N_PARAMETER_AND_INITIALIZER, fieldName, []);
13502 foundError = true;
13503 } else if (identical(state, INIT_STATE.INIT_IN_INITIALIZERS)) {
13504 _errorReporter.reportError2(CompileTimeErrorCode.FIELD_INITIALIZED_B Y_MULTIPLE_INITIALIZERS, fieldName, [fieldElement.displayName]);
13505 foundError = true;
13506 }
13507 }
13508 }
13509 }
13510 for (MapEntry<FieldElement, INIT_STATE> entry in getMapEntrySet(fieldElement sMap)) {
13511 if (identical(entry.getValue(), INIT_STATE.NOT_INIT)) {
13512 FieldElement fieldElement = entry.getKey();
13513 if (fieldElement.isConst) {
13514 _errorReporter.reportError2(CompileTimeErrorCode.CONST_NOT_INITIALIZED , node.returnType, [fieldElement.name]);
13515 foundError = true;
13516 } else if (fieldElement.isFinal) {
13517 _errorReporter.reportError2(StaticWarningCode.FINAL_NOT_INITIALIZED, n ode.returnType, [fieldElement.name]);
13518 foundError = true;
13519 }
13520 }
13521 }
13522 return foundError;
13523 }
13524
13525 /**
13526 * This checks the passed executable element against override-error codes.
13527 *
13528 * @param executableElement a non-null [ExecutableElement] to evaluate
13529 * @param parameters the parameters of the executable element
13530 * @param errorNameTarget the node to report problems on
13531 * @return `true` if and only if an error code is generated on the passed node
13532 * @see StaticWarningCode#INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC
13533 * @see CompileTimeErrorCode#INVALID_OVERRIDE_REQUIRED
13534 * @see CompileTimeErrorCode#INVALID_OVERRIDE_POSITIONAL
13535 * @see CompileTimeErrorCode#INVALID_OVERRIDE_NAMED
13536 * @see StaticWarningCode#INVALID_GETTER_OVERRIDE_RETURN_TYPE
13537 * @see StaticWarningCode#INVALID_METHOD_OVERRIDE_RETURN_TYPE
13538 * @see StaticWarningCode#INVALID_METHOD_OVERRIDE_NORMAL_PARAM_TYPE
13539 * @see StaticWarningCode#INVALID_SETTER_OVERRIDE_NORMAL_PARAM_TYPE
13540 * @see StaticWarningCode#INVALID_METHOD_OVERRIDE_OPTIONAL_PARAM_TYPE
13541 * @see StaticWarningCode#INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE
13542 * @see StaticWarningCode#INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES
13543 */
13544 bool checkForAllInvalidOverrideErrorCodes(ExecutableElement executableElement, List<ParameterElement> parameters, List<ASTNode> parameterLocations, SimpleIden tifier errorNameTarget) {
13545 String executableElementName = executableElement.name;
13546 bool executableElementPrivate = Identifier.isPrivateName(executableElementNa me);
13547 ExecutableElement overriddenExecutable = _inheritanceManager.lookupInheritan ce(_enclosingClass, executableElementName);
13548 bool isGetter = false;
13549 bool isSetter = false;
13550 if (executableElement is PropertyAccessorElement) {
13551 PropertyAccessorElement accessorElement = executableElement as PropertyAcc essorElement;
13552 isGetter = accessorElement.isGetter;
13553 isSetter = accessorElement.isSetter;
13554 }
13555 if (overriddenExecutable == null) {
13556 if (!isGetter && !isSetter && !executableElement.isOperator) {
13557 Set<ClassElement> visitedClasses = new Set<ClassElement>();
13558 InterfaceType superclassType = _enclosingClass.supertype;
13559 ClassElement superclassElement = superclassType == null ? null : supercl assType.element;
13560 while (superclassElement != null && !visitedClasses.contains(superclassE lement)) {
13561 javaSetAdd(visitedClasses, superclassElement);
13562 LibraryElement superclassLibrary = superclassElement.library;
13563 List<FieldElement> fieldElts = superclassElement.fields;
13564 for (FieldElement fieldElt in fieldElts) {
13565 if (fieldElt.name != executableElementName) {
13566 continue;
13567 }
13568 if (executableElementPrivate && _currentLibrary != superclassLibrary ) {
13569 continue;
13570 }
13571 if (fieldElt.isStatic) {
13572 _errorReporter.reportError2(StaticWarningCode.INSTANCE_METHOD_NAME _COLLIDES_WITH_SUPERCLASS_STATIC, errorNameTarget, [
13573 executableElementName,
13574 fieldElt.enclosingElement.displayName]);
13575 return true;
13576 }
13577 }
13578 List<MethodElement> methodElements = superclassElement.methods;
13579 for (MethodElement methodElement in methodElements) {
13580 if (methodElement.name != executableElementName) {
13581 continue;
13582 }
13583 if (executableElementPrivate && _currentLibrary != superclassLibrary ) {
13584 continue;
13585 }
13586 if (methodElement.isStatic) {
13587 _errorReporter.reportError2(StaticWarningCode.INSTANCE_METHOD_NAME _COLLIDES_WITH_SUPERCLASS_STATIC, errorNameTarget, [
13588 executableElementName,
13589 methodElement.enclosingElement.displayName]);
13590 return true;
13591 }
13592 }
13593 superclassType = superclassElement.supertype;
13594 superclassElement = superclassType == null ? null : superclassType.ele ment;
13595 }
13596 }
13597 return false;
13598 }
13599 FunctionType overridingFT = executableElement.type;
13600 FunctionType overriddenFT = overriddenExecutable.type;
13601 InterfaceType enclosingType = _enclosingClass.type;
13602 overriddenFT = _inheritanceManager.substituteTypeArgumentsInMemberFromInheri tance(overriddenFT, executableElementName, enclosingType);
13603 if (overridingFT == null || overriddenFT == null) {
13604 return false;
13605 }
13606 Type2 overridingFTReturnType = overridingFT.returnType;
13607 Type2 overriddenFTReturnType = overriddenFT.returnType;
13608 List<Type2> overridingNormalPT = overridingFT.normalParameterTypes;
13609 List<Type2> overriddenNormalPT = overriddenFT.normalParameterTypes;
13610 List<Type2> overridingPositionalPT = overridingFT.optionalParameterTypes;
13611 List<Type2> overriddenPositionalPT = overriddenFT.optionalParameterTypes;
13612 Map<String, Type2> overridingNamedPT = overridingFT.namedParameterTypes;
13613 Map<String, Type2> overriddenNamedPT = overriddenFT.namedParameterTypes;
13614 if (overridingNormalPT.length > overriddenNormalPT.length) {
13615 _errorReporter.reportError2(StaticWarningCode.INVALID_OVERRIDE_REQUIRED, e rrorNameTarget, [
13616 overriddenNormalPT.length,
13617 overriddenExecutable.enclosingElement.displayName]);
13618 return true;
13619 }
13620 if (overridingNormalPT.length + overridingPositionalPT.length < overriddenPo sitionalPT.length + overriddenNormalPT.length) {
13621 _errorReporter.reportError2(StaticWarningCode.INVALID_OVERRIDE_POSITIONAL, errorNameTarget, [
13622 overriddenPositionalPT.length + overriddenNormalPT.length,
13623 overriddenExecutable.enclosingElement.displayName]);
13624 return true;
13625 }
13626 Set<String> overridingParameterNameSet = overridingNamedPT.keys.toSet();
13627 JavaIterator<String> overriddenParameterNameIterator = new JavaIterator(over riddenNamedPT.keys.toSet());
13628 while (overriddenParameterNameIterator.hasNext) {
13629 String overriddenParamName = overriddenParameterNameIterator.next();
13630 if (!overridingParameterNameSet.contains(overriddenParamName)) {
13631 _errorReporter.reportError2(StaticWarningCode.INVALID_OVERRIDE_NAMED, er rorNameTarget, [
13632 overriddenParamName,
13633 overriddenExecutable.enclosingElement.displayName]);
13634 return true;
13635 }
13636 }
13637 if (overriddenFTReturnType != VoidTypeImpl.instance && !overridingFTReturnTy pe.isAssignableTo(overriddenFTReturnType)) {
13638 _errorReporter.reportError2(!isGetter ? StaticWarningCode.INVALID_METHOD_O VERRIDE_RETURN_TYPE : StaticWarningCode.INVALID_GETTER_OVERRIDE_RETURN_TYPE, err orNameTarget, [
13639 overridingFTReturnType.displayName,
13640 overriddenFTReturnType.displayName,
13641 overriddenExecutable.enclosingElement.displayName]);
13642 return true;
13643 }
13644 if (parameterLocations == null) {
13645 return false;
13646 }
13647 int parameterIndex = 0;
13648 for (int i = 0; i < overridingNormalPT.length; i++) {
13649 if (!overridingNormalPT[i].isAssignableTo(overriddenNormalPT[i])) {
13650 _errorReporter.reportError2(!isSetter ? StaticWarningCode.INVALID_METHOD _OVERRIDE_NORMAL_PARAM_TYPE : StaticWarningCode.INVALID_SETTER_OVERRIDE_NORMAL_P ARAM_TYPE, parameterLocations[parameterIndex], [
13651 overridingNormalPT[i].displayName,
13652 overriddenNormalPT[i].displayName,
13653 overriddenExecutable.enclosingElement.displayName]);
13654 return true;
13655 }
13656 parameterIndex++;
13657 }
13658 for (int i = 0; i < overriddenPositionalPT.length; i++) {
13659 if (!overridingPositionalPT[i].isAssignableTo(overriddenPositionalPT[i])) {
13660 _errorReporter.reportError2(StaticWarningCode.INVALID_METHOD_OVERRIDE_OP TIONAL_PARAM_TYPE, parameterLocations[parameterIndex], [
13661 overridingPositionalPT[i].displayName,
13662 overriddenPositionalPT[i].displayName,
13663 overriddenExecutable.enclosingElement.displayName]);
13664 return true;
13665 }
13666 parameterIndex++;
13667 }
13668 JavaIterator<MapEntry<String, Type2>> overriddenNamedPTIterator = new JavaIt erator(getMapEntrySet(overriddenNamedPT));
13669 while (overriddenNamedPTIterator.hasNext) {
13670 MapEntry<String, Type2> overriddenNamedPTEntry = overriddenNamedPTIterator .next();
13671 Type2 overridingType = overridingNamedPT[overriddenNamedPTEntry.getKey()];
13672 if (overridingType == null) {
13673 continue;
13674 }
13675 if (!overriddenNamedPTEntry.getValue().isAssignableTo(overridingType)) {
13676 ParameterElement parameterToSelect = null;
13677 ASTNode parameterLocationToSelect = null;
13678 for (int i = 0; i < parameters.length; i++) {
13679 ParameterElement parameter = parameters[i];
13680 if (identical(parameter.parameterKind, ParameterKind.NAMED) && overrid denNamedPTEntry.getKey() == parameter.name) {
13681 parameterToSelect = parameter;
13682 parameterLocationToSelect = parameterLocations[i];
13683 break;
13684 }
13685 }
13686 if (parameterToSelect != null) {
13687 _errorReporter.reportError2(StaticWarningCode.INVALID_METHOD_OVERRIDE_ NAMED_PARAM_TYPE, parameterLocationToSelect, [
13688 overridingType.displayName,
13689 overriddenNamedPTEntry.getValue().displayName,
13690 overriddenExecutable.enclosingElement.displayName]);
13691 return true;
13692 }
13693 }
13694 }
13695 bool foundError = false;
13696 List<ASTNode> formalParameters = new List<ASTNode>();
13697 List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>();
13698 List<ParameterElementImpl> overriddenParameterElts = new List<ParameterEleme ntImpl>();
13699 List<ParameterElement> overriddenPEs = overriddenExecutable.parameters;
13700 for (int i = 0; i < parameters.length; i++) {
13701 ParameterElement parameter = parameters[i];
13702 if (parameter.parameterKind.isOptional) {
13703 formalParameters.add(parameterLocations[i]);
13704 parameterElts.add(parameter as ParameterElementImpl);
13705 }
13706 }
13707 for (ParameterElement parameterElt in overriddenPEs) {
13708 if (parameterElt.parameterKind.isOptional) {
13709 if (parameterElt is ParameterElementImpl) {
13710 overriddenParameterElts.add(parameterElt as ParameterElementImpl);
13711 }
13712 }
13713 }
13714 if (parameterElts.length > 0) {
13715 if (identical(parameterElts[0].parameterKind, ParameterKind.NAMED)) {
13716 for (int i = 0; i < parameterElts.length; i++) {
13717 ParameterElementImpl parameterElt = parameterElts[i];
13718 EvaluationResultImpl result = parameterElt.evaluationResult;
13719 if (result == null || identical(result, ValidResult.RESULT_OBJECT)) {
13720 continue;
13721 }
13722 String parameterName = parameterElt.name;
13723 for (int j = 0; j < overriddenParameterElts.length; j++) {
13724 ParameterElementImpl overriddenParameterElt = overriddenParameterElt s[j];
13725 String overriddenParameterName = overriddenParameterElt.name;
13726 if (parameterName != null && parameterName == overriddenParameterNam e) {
13727 EvaluationResultImpl overriddenResult = overriddenParameterElt.eva luationResult;
13728 if (overriddenResult == null || identical(result, ValidResult.RESU LT_OBJECT)) {
13729 break;
13730 }
13731 if (!result.equalValues(overriddenResult)) {
13732 _errorReporter.reportError2(StaticWarningCode.INVALID_OVERRIDE_D IFFERENT_DEFAULT_VALUES_NAMED, formalParameters[i], [
13733 overriddenExecutable.enclosingElement.displayName,
13734 overriddenExecutable.displayName,
13735 parameterName]);
13736 foundError = true;
13737 }
13738 }
13739 }
13740 }
13741 } else {
13742 for (int i = 0; i < parameterElts.length && i < overriddenParameterElts. length; i++) {
13743 ParameterElementImpl parameterElt = parameterElts[i];
13744 EvaluationResultImpl result = parameterElt.evaluationResult;
13745 if (result == null || identical(result, ValidResult.RESULT_OBJECT)) {
13746 continue;
13747 }
13748 ParameterElementImpl overriddenParameterElt = overriddenParameterElts[ i];
13749 EvaluationResultImpl overriddenResult = overriddenParameterElt.evaluat ionResult;
13750 if (overriddenResult == null || identical(result, ValidResult.RESULT_O BJECT)) {
13751 continue;
13752 }
13753 if (!result.equalValues(overriddenResult)) {
13754 _errorReporter.reportError2(StaticWarningCode.INVALID_OVERRIDE_DIFFE RENT_DEFAULT_VALUES_POSITIONAL, formalParameters[i], [
13755 overriddenExecutable.enclosingElement.displayName,
13756 overriddenExecutable.displayName]);
13757 foundError = true;
13758 }
13759 }
13760 }
13761 }
13762 return foundError;
13763 }
13764
13765 /**
13766 * This checks the passed field declaration against override-error codes.
13767 *
13768 * @param node the [MethodDeclaration] to evaluate
13769 * @return `true` if and only if an error code is generated on the passed node
13770 * @see #checkForAllInvalidOverrideErrorCodes(ExecutableElement)
13771 */
13772 bool checkForAllInvalidOverrideErrorCodes2(FieldDeclaration node) {
13773 if (_enclosingClass == null || node.isStatic) {
13774 return false;
13775 }
13776 bool hasProblems = false;
13777 VariableDeclarationList fields = node.fields;
13778 for (VariableDeclaration field in fields.variables) {
13779 FieldElement element = field.element as FieldElement;
13780 if (element == null) {
13781 continue;
13782 }
13783 PropertyAccessorElement getter = element.getter;
13784 PropertyAccessorElement setter = element.setter;
13785 SimpleIdentifier fieldName = field.name;
13786 if (getter != null) {
13787 hasProblems = javaBooleanOr(hasProblems, checkForAllInvalidOverrideError Codes(getter, ParameterElementImpl.EMPTY_ARRAY, ASTNode.EMPTY_ARRAY, fieldName)) ;
13788 }
13789 if (setter != null) {
13790 hasProblems = javaBooleanOr(hasProblems, checkForAllInvalidOverrideError Codes(setter, setter.parameters, <ASTNode> [fieldName], fieldName));
13791 }
13792 }
13793 return hasProblems;
13794 }
13795
13796 /**
13797 * This checks the passed method declaration against override-error codes.
13798 *
13799 * @param node the [MethodDeclaration] to evaluate
13800 * @return `true` if and only if an error code is generated on the passed node
13801 * @see #checkForAllInvalidOverrideErrorCodes(ExecutableElement)
13802 */
13803 bool checkForAllInvalidOverrideErrorCodes3(MethodDeclaration node) {
13804 if (_enclosingClass == null || node.isStatic || node.body is NativeFunctionB ody) {
13805 return false;
13806 }
13807 ExecutableElement executableElement = node.element;
13808 if (executableElement == null) {
13809 return false;
13810 }
13811 SimpleIdentifier methodName = node.name;
13812 if (methodName.isSynthetic) {
13813 return false;
13814 }
13815 FormalParameterList formalParameterList = node.parameters;
13816 NodeList<FormalParameter> parameterList = formalParameterList != null ? form alParameterList.parameters : null;
13817 List<ASTNode> parameters = parameterList != null ? new List.from(parameterLi st) : null;
13818 return checkForAllInvalidOverrideErrorCodes(executableElement, executableEle ment.parameters, parameters, methodName);
13819 }
13820
13821 /**
13822 * This verifies that all classes of the passed 'with' clause are valid.
13823 *
13824 * @param node the 'with' clause to evaluate
13825 * @return `true` if and only if an error code is generated on the passed node
13826 * @see CompileTimeErrorCode#MIXIN_DECLARES_CONSTRUCTOR
13827 * @see CompileTimeErrorCode#MIXIN_INHERITS_FROM_NOT_OBJECT
13828 * @see CompileTimeErrorCode#MIXIN_REFERENCES_SUPER
13829 */
13830 bool checkForAllMixinErrorCodes(WithClause withClause) {
13831 if (withClause == null) {
13832 return false;
13833 }
13834 bool problemReported = false;
13835 for (TypeName mixinName in withClause.mixinTypes) {
13836 Type2 mixinType = mixinName.type;
13837 if (mixinType is! InterfaceType) {
13838 continue;
13839 }
13840 if (checkForExtendsOrImplementsDisallowedClass(mixinName, CompileTimeError Code.MIXIN_OF_DISALLOWED_CLASS)) {
13841 problemReported = true;
13842 } else {
13843 ClassElement mixinElement = ((mixinType as InterfaceType)).element;
13844 problemReported = javaBooleanOr(problemReported, checkForMixinDeclaresCo nstructor(mixinName, mixinElement));
13845 problemReported = javaBooleanOr(problemReported, checkForMixinInheritsNo tFromObject(mixinName, mixinElement));
13846 problemReported = javaBooleanOr(problemReported, checkForMixinReferences Super(mixinName, mixinElement));
13847 }
13848 }
13849 return problemReported;
13850 }
13851
13852 /**
13853 * This checks error related to the redirected constructors.
13854 *
13855 * @param node the constructor declaration to evaluate
13856 * @return `true` if and only if an error code is generated on the passed node
13857 * @see StaticWarningCode#REDIRECT_TO_INVALID_RETURN_TYPE
13858 * @see StaticWarningCode#REDIRECT_TO_INVALID_FUNCTION_TYPE
13859 * @see StaticWarningCode#REDIRECT_TO_MISSING_CONSTRUCTOR
13860 */
13861 bool checkForAllRedirectConstructorErrorCodes(ConstructorDeclaration node) {
13862 ConstructorName redirectedConstructor = node.redirectedConstructor;
13863 if (redirectedConstructor == null) {
13864 return false;
13865 }
13866 ConstructorElement redirectedElement = redirectedConstructor.staticElement;
13867 if (redirectedElement == null) {
13868 TypeName constructorTypeName = redirectedConstructor.type;
13869 Type2 redirectedType = constructorTypeName.type;
13870 if (redirectedType != null && redirectedType.element != null && !redirecte dType.isDynamic) {
13871 String constructorStrName = constructorTypeName.name.name;
13872 if (redirectedConstructor.name != null) {
13873 constructorStrName += ".${redirectedConstructor.name.name}";
13874 }
13875 _errorReporter.reportError2(StaticWarningCode.REDIRECT_TO_MISSING_CONSTR UCTOR, redirectedConstructor, [constructorStrName, redirectedType.displayName]);
13876 return true;
13877 }
13878 return false;
13879 }
13880 FunctionType redirectedType = redirectedElement.type;
13881 Type2 redirectedReturnType = redirectedType.returnType;
13882 FunctionType constructorType = node.element.type;
13883 Type2 constructorReturnType = constructorType.returnType;
13884 if (!redirectedReturnType.isAssignableTo(constructorReturnType)) {
13885 _errorReporter.reportError2(StaticWarningCode.REDIRECT_TO_INVALID_RETURN_T YPE, redirectedConstructor, [redirectedReturnType, constructorReturnType]);
13886 return true;
13887 }
13888 if (!redirectedType.isSubtypeOf(constructorType)) {
13889 _errorReporter.reportError2(StaticWarningCode.REDIRECT_TO_INVALID_FUNCTION _TYPE, redirectedConstructor, [redirectedType, constructorType]);
13890 return true;
13891 }
13892 return false;
13893 }
13894
13895 /**
13896 * This checks that the return statement of the form <i>return e;</i> is not i n a generative
13897 * constructor.
13898 *
13899 * This checks that return statements without expressions are not in a generat ive constructor and
13900 * the return type is not assignable to `null`; that is, we don't have `return ;` if
13901 * the enclosing method has a return type.
13902 *
13903 * This checks that the return type matches the type of the declared return ty pe in the enclosing
13904 * method or function.
13905 *
13906 * @param node the return statement to evaluate
13907 * @return `true` if and only if an error code is generated on the passed node
13908 * @see CompileTimeErrorCode#RETURN_IN_GENERATIVE_CONSTRUCTOR
13909 * @see StaticWarningCode#RETURN_WITHOUT_VALUE
13910 * @see StaticTypeWarningCode#RETURN_OF_INVALID_TYPE
13911 */
13912 bool checkForAllReturnStatementErrorCodes(ReturnStatement node) {
13913 FunctionType functionType = _enclosingFunction == null ? null : _enclosingFu nction.type;
13914 Type2 expectedReturnType = functionType == null ? DynamicTypeImpl.instance : functionType.returnType;
13915 Expression returnExpression = node.expression;
13916 bool isGenerativeConstructor = _enclosingFunction is ConstructorElement && ! ((_enclosingFunction as ConstructorElement)).isFactory;
13917 if (isGenerativeConstructor) {
13918 if (returnExpression == null) {
13919 return false;
13920 }
13921 _errorReporter.reportError2(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONS TRUCTOR, returnExpression, []);
13922 return true;
13923 }
13924 if (returnExpression == null) {
13925 if (VoidTypeImpl.instance.isAssignableTo(expectedReturnType)) {
13926 return false;
13927 }
13928 _errorReporter.reportError2(StaticWarningCode.RETURN_WITHOUT_VALUE, node, []);
13929 return true;
13930 }
13931 return checkForReturnOfInvalidType(returnExpression, expectedReturnType);
13932 }
13933
13934 /**
13935 * This verifies that the export namespace of the passed export directive does not export any name
13936 * already exported by other export directive.
13937 *
13938 * @param node the export directive node to report problem on
13939 * @return `true` if and only if an error code is generated on the passed node
13940 * @see CompileTimeErrorCode#AMBIGUOUS_EXPORT
13941 */
13942 bool checkForAmbiguousExport(ExportDirective node) {
13943 if (node.element is! ExportElement) {
13944 return false;
13945 }
13946 ExportElement exportElement = node.element as ExportElement;
13947 LibraryElement exportedLibrary = exportElement.exportedLibrary;
13948 if (exportedLibrary == null) {
13949 return false;
13950 }
13951 Namespace namespace = new NamespaceBuilder().createExportNamespace(exportEle ment);
13952 Set<String> newNames = namespace.definedNames.keys.toSet();
13953 for (String name in newNames) {
13954 ExportElement prevElement = _exportedNames[name];
13955 if (prevElement != null && prevElement != exportElement) {
13956 _errorReporter.reportError2(CompileTimeErrorCode.AMBIGUOUS_EXPORT, node, [
13957 name,
13958 prevElement.exportedLibrary.definingCompilationUnit.displayName,
13959 exportedLibrary.definingCompilationUnit.displayName]);
13960 return true;
13961 } else {
13962 _exportedNames[name] = exportElement;
13963 }
13964 }
13965 return false;
13966 }
13967
13968 /**
13969 * This verifies that the passed argument definition test identifier is a para meter.
13970 *
13971 * @param node the [ArgumentDefinitionTest] to evaluate
13972 * @return `true` if and only if an error code is generated on the passed node
13973 * @see CompileTimeErrorCode#ARGUMENT_DEFINITION_TEST_NON_PARAMETER
13974 */
13975 bool checkForArgumentDefinitionTestNonParameter(ArgumentDefinitionTest node) {
13976 SimpleIdentifier identifier = node.identifier;
13977 Element element = identifier.staticElement;
13978 if (element != null && element is! ParameterElement) {
13979 _errorReporter.reportError2(CompileTimeErrorCode.ARGUMENT_DEFINITION_TEST_ NON_PARAMETER, identifier, [identifier.name]);
13980 return true;
13981 }
13982 return false;
13983 }
13984
13985 /**
13986 * This verifies that the passed arguments can be assigned to their correspond ing parameters.
13987 *
13988 * @param node the arguments to evaluate
13989 * @return `true` if and only if an error code is generated on the passed node
13990 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
13991 */
13992 bool checkForArgumentTypeNotAssignable(ArgumentList argumentList) {
13993 if (argumentList == null) {
13994 return false;
13995 }
13996 bool problemReported = false;
13997 for (Expression argument in argumentList.arguments) {
13998 problemReported = javaBooleanOr(problemReported, checkForArgumentTypeNotAs signable2(argument));
13999 }
14000 return problemReported;
14001 }
14002
14003 /**
14004 * This verifies that the passed argument can be assigned to its corresponding parameter.
14005 *
14006 * @param argument the argument to evaluate
14007 * @return `true` if and only if an error code is generated on the passed node
14008 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
14009 */
14010 bool checkForArgumentTypeNotAssignable2(Expression argument) {
14011 if (argument == null) {
14012 return false;
14013 }
14014 ParameterElement staticParameterElement = argument.staticParameterElement;
14015 Type2 staticParameterType = staticParameterElement == null ? null : staticPa rameterElement.type;
14016 ParameterElement propagatedParameterElement = argument.propagatedParameterEl ement;
14017 Type2 propagatedParameterType = propagatedParameterElement == null ? null : propagatedParameterElement.type;
14018 return checkForArgumentTypeNotAssignable3(argument, staticParameterType, pro pagatedParameterType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
14019 }
14020
14021 /**
14022 * This verifies that the passed expression can be assigned to its correspondi ng parameters.
14023 *
14024 * @param expression the expression to evaluate
14025 * @param expectedStaticType the expected static type
14026 * @param expectedPropagatedType the expected propagated type, may be `null`
14027 * @return `true` if and only if an error code is generated on the passed node
14028 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
14029 */
14030 bool checkForArgumentTypeNotAssignable3(Expression expression, Type2 expectedS taticType, Type2 expectedPropagatedType, ErrorCode errorCode) => checkForArgumen tTypeNotAssignable4(expression, expectedStaticType, getStaticType(expression), e xpectedPropagatedType, expression.propagatedType, errorCode);
14031
14032 /**
14033 * This verifies that the passed expression can be assigned to its correspondi ng parameters.
14034 *
14035 * @param expression the expression to evaluate
14036 * @param expectedStaticType the expected static type of the parameter
14037 * @param actualStaticType the actual static type of the argument
14038 * @param expectedPropagatedType the expected propagated type of the parameter , may be
14039 * `null`
14040 * @param actualPropagatedType the expected propagated type of the parameter, may be `null`
14041 * @return `true` if and only if an error code is generated on the passed node
14042 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
14043 */
14044 bool checkForArgumentTypeNotAssignable4(Expression expression, Type2 expectedS taticType, Type2 actualStaticType, Type2 expectedPropagatedType, Type2 actualPro pagatedType, ErrorCode errorCode) {
14045 if (actualStaticType == null || expectedStaticType == null) {
14046 return false;
14047 }
14048 if (_strictMode) {
14049 if (actualStaticType.isAssignableTo(expectedStaticType)) {
14050 return false;
14051 }
14052 _errorReporter.reportError2(errorCode, expression, [
14053 actualStaticType.displayName,
14054 expectedStaticType.displayName]);
14055 return true;
14056 }
14057 if (actualPropagatedType == null || expectedPropagatedType == null) {
14058 if (actualStaticType.isAssignableTo(expectedStaticType)) {
14059 return false;
14060 }
14061 _errorReporter.reportError2(errorCode, expression, [
14062 actualStaticType.displayName,
14063 expectedStaticType.displayName]);
14064 return true;
14065 }
14066 if (actualStaticType.isAssignableTo(expectedStaticType) || actualStaticType. isAssignableTo(expectedPropagatedType) || actualPropagatedType.isAssignableTo(ex pectedStaticType) || actualPropagatedType.isAssignableTo(expectedPropagatedType) ) {
14067 return false;
14068 }
14069 _errorReporter.reportError2(errorCode, expression, [
14070 (actualPropagatedType == null ? actualStaticType : actualPropagatedType) .displayName,
14071 (expectedPropagatedType == null ? expectedStaticType : expectedPropagate dType).displayName]);
14072 return true;
14073 }
14074
14075 /**
14076 * This verifies that left hand side of the passed assignment expression is no t final.
14077 *
14078 * @param node the assignment expression to evaluate
14079 * @return `true` if and only if an error code is generated on the passed node
14080 * @see StaticWarningCode#ASSIGNMENT_TO_FINAL
14081 */
14082 bool checkForAssignmentToFinal(AssignmentExpression node) {
14083 Expression leftExpression = node.leftHandSide;
14084 return checkForAssignmentToFinal2(leftExpression);
14085 }
14086
14087 /**
14088 * This verifies that the passed expression is not final.
14089 *
14090 * @param node the expression to evaluate
14091 * @return `true` if and only if an error code is generated on the passed node
14092 * @see StaticWarningCode#ASSIGNMENT_TO_CONST
14093 * @see StaticWarningCode#ASSIGNMENT_TO_FINAL
14094 * @see StaticWarningCode#ASSIGNMENT_TO_METHOD
14095 */
14096 bool checkForAssignmentToFinal2(Expression expression) {
14097 Element element = null;
14098 if (expression is Identifier) {
14099 element = ((expression as Identifier)).staticElement;
14100 }
14101 if (expression is PropertyAccess) {
14102 element = ((expression as PropertyAccess)).propertyName.staticElement;
14103 }
14104 if (element is PropertyAccessorElement) {
14105 PropertyAccessorElement accessor = element as PropertyAccessorElement;
14106 element = accessor.variable;
14107 }
14108 if (element is VariableElement) {
14109 VariableElement variable = element as VariableElement;
14110 if (variable.isConst) {
14111 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_CONST, expre ssion, []);
14112 return true;
14113 }
14114 if (variable.isFinal) {
14115 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_FINAL, expre ssion, []);
14116 return true;
14117 }
14118 return false;
14119 }
14120 if (element is MethodElement) {
14121 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_METHOD, expres sion, []);
14122 return true;
14123 }
14124 return false;
14125 }
14126
14127 /**
14128 * This verifies that the passed identifier is not a keyword, and generates th e passed error code
14129 * on the identifier if it is a keyword.
14130 *
14131 * @param identifier the identifier to check to ensure that it is not a keywor d
14132 * @param errorCode if the passed identifier is a keyword then this error code is created on the
14133 * identifier, the error code will be one of
14134 * [CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_NAME],
14135 * [CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME] or
14136 * [CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME]
14137 * @return `true` if and only if an error code is generated on the passed node
14138 * @see CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_NAME
14139 * @see CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME
14140 * @see CompileTimeErrorCode#BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME
14141 */
14142 bool checkForBuiltInIdentifierAsName(SimpleIdentifier identifier, ErrorCode er rorCode) {
14143 sc.Token token = identifier.token;
14144 if (identical(token.type, sc.TokenType.KEYWORD)) {
14145 _errorReporter.reportError2(errorCode, identifier, [identifier.name]);
14146 return true;
14147 }
14148 return false;
14149 }
14150
14151 /**
14152 * This verifies that the given switch case is terminated with 'break', 'conti nue', 'return' or
14153 * 'throw'.
14154 *
14155 * @param node the switch case to evaluate
14156 * @return `true` if and only if an error code is generated on the passed node
14157 * @see StaticWarningCode#CASE_BLOCK_NOT_TERMINATED
14158 */
14159 bool checkForCaseBlockNotTerminated(SwitchCase node) {
14160 NodeList<Statement> statements = node.statements;
14161 if (statements.isEmpty) {
14162 ASTNode parent = node.parent;
14163 if (parent is SwitchStatement) {
14164 SwitchStatement switchStatement = parent as SwitchStatement;
14165 NodeList<SwitchMember> members = switchStatement.members;
14166 int index = members.indexOf(node);
14167 if (index != -1 && index < members.length - 1) {
14168 return false;
14169 }
14170 }
14171 } else {
14172 Statement statement = statements[statements.length - 1];
14173 if (statement is BreakStatement || statement is ContinueStatement || state ment is ReturnStatement) {
14174 return false;
14175 }
14176 if (statement is ExpressionStatement) {
14177 Expression expression = ((statement as ExpressionStatement)).expression;
14178 if (expression is ThrowExpression) {
14179 return false;
14180 }
14181 }
14182 }
14183 _errorReporter.reportError4(StaticWarningCode.CASE_BLOCK_NOT_TERMINATED, nod e.keyword, []);
14184 return true;
14185 }
14186
14187 /**
14188 * This verifies that the switch cases in the given switch statement is termin ated with 'break',
14189 * 'continue', 'return' or 'throw'.
14190 *
14191 * @param node the switch statement containing the cases to be checked
14192 * @return `true` if and only if an error code is generated on the passed node
14193 * @see StaticWarningCode#CASE_BLOCK_NOT_TERMINATED
14194 */
14195 bool checkForCaseBlocksNotTerminated(SwitchStatement node) {
14196 bool foundError = false;
14197 NodeList<SwitchMember> members = node.members;
14198 int lastMember = members.length - 1;
14199 for (int i = 0; i < lastMember; i++) {
14200 SwitchMember member = members[i];
14201 if (member is SwitchCase) {
14202 foundError = javaBooleanOr(foundError, checkForCaseBlockNotTerminated(me mber as SwitchCase));
14203 }
14204 }
14205 return foundError;
14206 }
14207
14208 /**
14209 * This verifies that the passed switch statement does not have a case express ion with the
14210 * operator '==' overridden.
14211 *
14212 * @param node the switch statement to evaluate
14213 * @param type the common type of all 'case' expressions
14214 * @return `true` if and only if an error code is generated on the passed node
14215 * @see CompileTimeErrorCode#CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
14216 */
14217 bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, Type2 ty pe) {
14218 if (!implementsEqualsWhenNotAllowed(type)) {
14219 return false;
14220 }
14221 _errorReporter.reportError4(CompileTimeErrorCode.CASE_EXPRESSION_TYPE_IMPLEM ENTS_EQUALS, node.keyword, [type.displayName]);
14222 return true;
14223 }
14224
14225 /**
14226 * This verifies that the passed method declaration is abstract only if the en closing class is
14227 * also abstract.
14228 *
14229 * @param node the method declaration to evaluate
14230 * @return `true` if and only if an error code is generated on the passed node
14231 * @see StaticWarningCode#CONCRETE_CLASS_WITH_ABSTRACT_MEMBER
14232 */
14233 bool checkForConcreteClassWithAbstractMember(MethodDeclaration node) {
14234 if (node.isAbstract && _enclosingClass != null && !_enclosingClass.isAbstrac t) {
14235 SimpleIdentifier methodName = node.name;
14236 _errorReporter.reportError2(StaticWarningCode.CONCRETE_CLASS_WITH_ABSTRACT _MEMBER, methodName, [methodName.name, _enclosingClass.displayName]);
14237 return true;
14238 }
14239 return false;
14240 }
14241
14242 /**
14243 * This verifies all possible conflicts of the constructor name with other con structors and
14244 * members of the same class.
14245 *
14246 * @param node the constructor declaration to evaluate
14247 * @return `true` if and only if an error code is generated on the passed node
14248 * @see CompileTimeErrorCode#DUPLICATE_CONSTRUCTOR_DEFAULT
14249 * @see CompileTimeErrorCode#DUPLICATE_CONSTRUCTOR_NAME
14250 * @see CompileTimeErrorCode#CONFLICTING_CONSTRUCTOR_NAME_AND_FIELD
14251 * @see CompileTimeErrorCode#CONFLICTING_CONSTRUCTOR_NAME_AND_METHOD
14252 */
14253 bool checkForConflictingConstructorNameAndMember(ConstructorDeclaration node) {
14254 ConstructorElement constructorElement = node.element;
14255 SimpleIdentifier constructorName = node.name;
14256 String name = constructorElement.name;
14257 ClassElement classElement = constructorElement.enclosingElement;
14258 List<ConstructorElement> constructors = classElement.constructors;
14259 for (ConstructorElement otherConstructor in constructors) {
14260 if (identical(otherConstructor, constructorElement)) {
14261 continue;
14262 }
14263 if (name == otherConstructor.name) {
14264 if (name == null || name.length == 0) {
14265 _errorReporter.reportError2(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR _DEFAULT, node, []);
14266 } else {
14267 _errorReporter.reportError2(CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR _NAME, node, [name]);
14268 }
14269 return true;
14270 }
14271 }
14272 if (constructorName != null && constructorElement != null && !constructorNam e.isSynthetic) {
14273 List<FieldElement> fields = classElement.fields;
14274 for (FieldElement field in fields) {
14275 if (field.name == name) {
14276 _errorReporter.reportError2(CompileTimeErrorCode.CONFLICTING_CONSTRUCT OR_NAME_AND_FIELD, node, [name]);
14277 return true;
14278 }
14279 }
14280 List<MethodElement> methods = classElement.methods;
14281 for (MethodElement method in methods) {
14282 if (method.name == name) {
14283 _errorReporter.reportError2(CompileTimeErrorCode.CONFLICTING_CONSTRUCT OR_NAME_AND_METHOD, node, [name]);
14284 return true;
14285 }
14286 }
14287 }
14288 return false;
14289 }
14290
14291 /**
14292 * This verifies that the [enclosingClass] does not have method and getter wit h the same
14293 * names.
14294 *
14295 * @return `true` if and only if an error code is generated on the passed node
14296 * @see CompileTimeErrorCode#CONFLICTING_GETTER_AND_METHOD
14297 * @see CompileTimeErrorCode#CONFLICTING_METHOD_AND_GETTER
14298 */
14299 bool checkForConflictingGetterAndMethod() {
14300 if (_enclosingClass == null) {
14301 return false;
14302 }
14303 bool hasProblem = false;
14304 for (MethodElement method in _enclosingClass.methods) {
14305 String name = method.name;
14306 ExecutableElement inherited = _inheritanceManager.lookupInheritance(_enclo singClass, name);
14307 if (inherited is! PropertyAccessorElement) {
14308 continue;
14309 }
14310 hasProblem = true;
14311 _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_GETTER_AND_ME THOD, method.nameOffset, name.length, [
14312 _enclosingClass.displayName,
14313 inherited.enclosingElement.displayName,
14314 name]);
14315 }
14316 for (PropertyAccessorElement accessor in _enclosingClass.accessors) {
14317 if (!accessor.isGetter) {
14318 continue;
14319 }
14320 String name = accessor.name;
14321 ExecutableElement inherited = _inheritanceManager.lookupInheritance(_enclo singClass, name);
14322 if (inherited is! MethodElement) {
14323 continue;
14324 }
14325 hasProblem = true;
14326 _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_METHOD_AND_GE TTER, accessor.nameOffset, name.length, [
14327 _enclosingClass.displayName,
14328 inherited.enclosingElement.displayName,
14329 name]);
14330 }
14331 return hasProblem;
14332 }
14333
14334 /**
14335 * This verifies that the superclass of the enclosing class does not declare a ccessible static
14336 * member with the same name as the passed instance getter/setter method decla ration.
14337 *
14338 * @param node the method declaration to evaluate
14339 * @return `true` if and only if an error code is generated on the passed node
14340 * @see StaticWarningCode#CONFLICTING_INSTANCE_GETTER_AND_SUPERCLASS_MEMBER
14341 * @see StaticWarningCode#CONFLICTING_INSTANCE_SETTER_AND_SUPERCLASS_MEMBER
14342 */
14343 bool checkForConflictingInstanceGetterAndSuperclassMember(MethodDeclaration no de) {
14344 if (node.isStatic) {
14345 return false;
14346 }
14347 SimpleIdentifier nameNode = node.name;
14348 if (nameNode == null) {
14349 return false;
14350 }
14351 String name = nameNode.name;
14352 if (_enclosingClass == null) {
14353 return false;
14354 }
14355 InterfaceType enclosingType = _enclosingClass.type;
14356 ExecutableElement superElement;
14357 superElement = enclosingType.lookUpGetterInSuperclass(name, _currentLibrary) ;
14358 if (superElement == null) {
14359 superElement = enclosingType.lookUpSetterInSuperclass(name, _currentLibrar y);
14360 }
14361 if (superElement == null) {
14362 superElement = enclosingType.lookUpMethodInSuperclass(name, _currentLibrar y);
14363 }
14364 if (superElement == null) {
14365 return false;
14366 }
14367 if (!superElement.isStatic) {
14368 return false;
14369 }
14370 ClassElement superElementClass = superElement.enclosingElement as ClassEleme nt;
14371 InterfaceType superElementType = superElementClass.type;
14372 if (node.isGetter) {
14373 _errorReporter.reportError2(StaticWarningCode.CONFLICTING_INSTANCE_GETTER_ AND_SUPERCLASS_MEMBER, nameNode, [superElementType.displayName]);
14374 } else {
14375 _errorReporter.reportError2(StaticWarningCode.CONFLICTING_INSTANCE_SETTER_ AND_SUPERCLASS_MEMBER, nameNode, [superElementType.displayName]);
14376 }
14377 return true;
14378 }
14379
14380 /**
14381 * This verifies that the enclosing class does not have an instance member wit h the same name as
14382 * the passed static getter method declaration.
14383 *
14384 * @param node the method declaration to evaluate
14385 * @return `true` if and only if an error code is generated on the passed node
14386 * @see StaticWarningCode#CONFLICTING_STATIC_GETTER_AND_INSTANCE_SETTER
14387 */
14388 bool checkForConflictingStaticGetterAndInstanceSetter(MethodDeclaration node) {
14389 if (!node.isStatic) {
14390 return false;
14391 }
14392 SimpleIdentifier nameNode = node.name;
14393 if (nameNode == null) {
14394 return false;
14395 }
14396 String name = nameNode.name;
14397 if (_enclosingClass == null) {
14398 return false;
14399 }
14400 InterfaceType enclosingType = _enclosingClass.type;
14401 ExecutableElement setter = enclosingType.lookUpSetter(name, _currentLibrary) ;
14402 if (setter == null) {
14403 return false;
14404 }
14405 if (setter.isStatic) {
14406 return false;
14407 }
14408 ClassElement setterClass = setter.enclosingElement as ClassElement;
14409 InterfaceType setterType = setterClass.type;
14410 _errorReporter.reportError2(StaticWarningCode.CONFLICTING_STATIC_GETTER_AND_ INSTANCE_SETTER, nameNode, [setterType.displayName]);
14411 return true;
14412 }
14413
14414 /**
14415 * This verifies that the enclosing class does not have an instance member wit h the same name as
14416 * the passed static getter method declaration.
14417 *
14418 * @param node the method declaration to evaluate
14419 * @return `true` if and only if an error code is generated on the passed node
14420 * @see StaticWarningCode#CONFLICTING_STATIC_SETTER_AND_INSTANCE_MEMBER
14421 */
14422 bool checkForConflictingStaticSetterAndInstanceMember(MethodDeclaration node) {
14423 if (!node.isStatic) {
14424 return false;
14425 }
14426 SimpleIdentifier nameNode = node.name;
14427 if (nameNode == null) {
14428 return false;
14429 }
14430 String name = nameNode.name;
14431 if (_enclosingClass == null) {
14432 return false;
14433 }
14434 InterfaceType enclosingType = _enclosingClass.type;
14435 ExecutableElement member;
14436 member = enclosingType.lookUpMethod(name, _currentLibrary);
14437 if (member == null) {
14438 member = enclosingType.lookUpGetter(name, _currentLibrary);
14439 }
14440 if (member == null) {
14441 member = enclosingType.lookUpSetter(name, _currentLibrary);
14442 }
14443 if (member == null) {
14444 return false;
14445 }
14446 if (member.isStatic) {
14447 return false;
14448 }
14449 ClassElement memberClass = member.enclosingElement as ClassElement;
14450 InterfaceType memberType = memberClass.type;
14451 _errorReporter.reportError2(StaticWarningCode.CONFLICTING_STATIC_SETTER_AND_ INSTANCE_MEMBER, nameNode, [memberType.displayName]);
14452 return true;
14453 }
14454
14455 /**
14456 * This verifies all conflicts between type variable and enclosing class. TODO (scheglov)
14457 *
14458 * @param node the class declaration to evaluate
14459 * @return `true` if and only if an error code is generated on the passed node
14460 * @see CompileTimeErrorCode#CONFLICTING_TYPE_VARIABLE_AND_CLASS
14461 * @see CompileTimeErrorCode#CONFLICTING_TYPE_VARIABLE_AND_MEMBER
14462 */
14463 bool checkForConflictingTypeVariableErrorCodes(ClassDeclaration node) {
14464 bool problemReported = false;
14465 for (TypeParameterElement typeParameter in _enclosingClass.typeParameters) {
14466 String name = typeParameter.name;
14467 if (_enclosingClass.name == name) {
14468 _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_TYPE_VARIAB LE_AND_CLASS, typeParameter.nameOffset, name.length, [name]);
14469 problemReported = true;
14470 }
14471 if (_enclosingClass.getMethod(name) != null || _enclosingClass.getGetter(n ame) != null || _enclosingClass.getSetter(name) != null) {
14472 _errorReporter.reportError3(CompileTimeErrorCode.CONFLICTING_TYPE_VARIAB LE_AND_MEMBER, typeParameter.nameOffset, name.length, [name]);
14473 problemReported = true;
14474 }
14475 }
14476 return problemReported;
14477 }
14478
14479 /**
14480 * This verifies that if the passed constructor declaration is 'const' then th ere are no
14481 * invocations of non-'const' super constructors.
14482 *
14483 * @param node the constructor declaration to evaluate
14484 * @return `true` if and only if an error code is generated on the passed node
14485 * @see CompileTimeErrorCode#CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER
14486 */
14487 bool checkForConstConstructorWithNonConstSuper(ConstructorDeclaration node) {
14488 if (!_isEnclosingConstructorConst) {
14489 return false;
14490 }
14491 if (node.factoryKeyword != null) {
14492 return false;
14493 }
14494 for (ConstructorInitializer initializer in node.initializers) {
14495 if (initializer is SuperConstructorInvocation) {
14496 SuperConstructorInvocation superInvocation = initializer as SuperConstru ctorInvocation;
14497 ConstructorElement element = superInvocation.staticElement;
14498 if (element.isConst) {
14499 return false;
14500 }
14501 _errorReporter.reportError2(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_ NON_CONST_SUPER, superInvocation, []);
14502 return true;
14503 }
14504 }
14505 InterfaceType supertype = _enclosingClass.supertype;
14506 if (supertype == null) {
14507 return false;
14508 }
14509 if (supertype.isObject) {
14510 return false;
14511 }
14512 ConstructorElement unnamedConstructor = supertype.element.unnamedConstructor ;
14513 if (unnamedConstructor == null) {
14514 return false;
14515 }
14516 if (unnamedConstructor.isConst) {
14517 return false;
14518 }
14519 _errorReporter.reportError2(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_ CONST_SUPER, node, []);
14520 return true;
14521 }
14522
14523 /**
14524 * This verifies that if the passed constructor declaration is 'const' then th ere are no non-final
14525 * instance variable.
14526 *
14527 * @param node the constructor declaration to evaluate
14528 * @return `true` if and only if an error code is generated on the passed node
14529 * @see CompileTimeErrorCode#CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
14530 */
14531 bool checkForConstConstructorWithNonFinalField(ConstructorDeclaration node) {
14532 if (!_isEnclosingConstructorConst) {
14533 return false;
14534 }
14535 ConstructorElement constructorElement = node.element;
14536 ClassElement classElement = constructorElement.enclosingElement;
14537 if (!classElement.hasNonFinalField()) {
14538 return false;
14539 }
14540 _errorReporter.reportError2(CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_ FINAL_FIELD, node, []);
14541 return true;
14542 }
14543
14544 /**
14545 * This verifies that the passed throw expression is not enclosed in a 'const' constructor
14546 * declaration.
14547 *
14548 * @param node the throw expression expression to evaluate
14549 * @return `true` if and only if an error code is generated on the passed node
14550 * @see CompileTimeErrorCode#CONST_CONSTRUCTOR_THROWS_EXCEPTION
14551 */
14552 bool checkForConstEvalThrowsException(ThrowExpression node) {
14553 if (_isEnclosingConstructorConst) {
14554 _errorReporter.reportError2(CompileTimeErrorCode.CONST_CONSTRUCTOR_THROWS_ EXCEPTION, node, []);
14555 return true;
14556 }
14557 return false;
14558 }
14559
14560 /**
14561 * This verifies that the passed normal formal parameter is not 'const'.
14562 *
14563 * @param node the normal formal parameter to evaluate
14564 * @return `true` if and only if an error code is generated on the passed node
14565 * @see CompileTimeErrorCode#CONST_FORMAL_PARAMETER
14566 */
14567 bool checkForConstFormalParameter(NormalFormalParameter node) {
14568 if (node.isConst) {
14569 _errorReporter.reportError2(CompileTimeErrorCode.CONST_FORMAL_PARAMETER, n ode, []);
14570 return true;
14571 }
14572 return false;
14573 }
14574
14575 /**
14576 * This verifies that the passed expression (used as a key in constant map) ha s class type that
14577 * does not declare operator <i>==<i>.
14578 *
14579 * @param key the expression to evaluate
14580 * @return `true` if and only if an error code is generated on the passed node
14581 * @see CompileTimeErrorCode#CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
14582 */
14583 bool checkForConstMapKeyExpressionTypeImplementsEquals(Expression key) {
14584 Type2 type = key.staticType;
14585 if (!implementsEqualsWhenNotAllowed(type)) {
14586 return false;
14587 }
14588 _errorReporter.reportError2(CompileTimeErrorCode.CONST_MAP_KEY_EXPRESSION_TY PE_IMPLEMENTS_EQUALS, key, [type.displayName]);
14589 return true;
14590 }
14591
14592 /**
14593 * This verifies that the all keys of the passed map literal have class type t hat does not declare
14594 * operator <i>==<i>.
14595 *
14596 * @param key the map literal to evaluate
14597 * @return `true` if and only if an error code is generated on the passed node
14598 * @see CompileTimeErrorCode#CONST_MAP_KEY_EXPRESSION_TYPE_IMPLEMENTS_EQUALS
14599 */
14600 bool checkForConstMapKeyExpressionTypeImplementsEquals2(MapLiteral node) {
14601 if (node.constKeyword == null) {
14602 return false;
14603 }
14604 bool hasProblems = false;
14605 for (MapLiteralEntry entry in node.entries) {
14606 Expression key = entry.key;
14607 hasProblems = javaBooleanOr(hasProblems, checkForConstMapKeyExpressionType ImplementsEquals(key));
14608 }
14609 return hasProblems;
14610 }
14611
14612 /**
14613 * This verifies that the passed instance creation expression is not being inv oked on an abstract
14614 * class.
14615 *
14616 * @param node the instance creation expression to evaluate
14617 * @param typeName the [TypeName] of the [ConstructorName] from the
14618 * [InstanceCreationExpression], this is the AST node that the error is attached to
14619 * @param type the type being constructed with this [InstanceCreationExpressio n]
14620 * @return `true` if and only if an error code is generated on the passed node
14621 * @see StaticWarningCode#CONST_WITH_ABSTRACT_CLASS
14622 * @see StaticWarningCode#NEW_WITH_ABSTRACT_CLASS
14623 */
14624 bool checkForConstOrNewWithAbstractClass(InstanceCreationExpression node, Type Name typeName, InterfaceType type) {
14625 if (type.element.isAbstract) {
14626 ConstructorElement element = node.staticElement;
14627 if (element != null && !element.isFactory) {
14628 if (identical(((node.keyword as sc.KeywordToken)).keyword, sc.Keyword.CO NST)) {
14629 _errorReporter.reportError2(StaticWarningCode.CONST_WITH_ABSTRACT_CLAS S, typeName, []);
14630 } else {
14631 _errorReporter.reportError2(StaticWarningCode.NEW_WITH_ABSTRACT_CLASS, typeName, []);
14632 }
14633 return true;
14634 }
14635 }
14636 return false;
14637 }
14638
14639 /**
14640 * This verifies that the passed 'const' instance creation expression is not b eing invoked on a
14641 * constructor that is not 'const'.
14642 *
14643 * This method assumes that the instance creation was tested to be 'const' bef ore being called.
14644 *
14645 * @param node the instance creation expression to evaluate
14646 * @return `true` if and only if an error code is generated on the passed node
14647 * @see CompileTimeErrorCode#CONST_WITH_NON_CONST
14648 */
14649 bool checkForConstWithNonConst(InstanceCreationExpression node) {
14650 ConstructorElement constructorElement = node.staticElement;
14651 if (constructorElement != null && !constructorElement.isConst) {
14652 _errorReporter.reportError2(CompileTimeErrorCode.CONST_WITH_NON_CONST, nod e, []);
14653 return true;
14654 }
14655 return false;
14656 }
14657
14658 /**
14659 * This verifies that the passed 'const' instance creation expression does not reference any type
14660 * parameters.
14661 *
14662 * This method assumes that the instance creation was tested to be 'const' bef ore being called.
14663 *
14664 * @param node the instance creation expression to evaluate
14665 * @return `true` if and only if an error code is generated on the passed node
14666 * @see CompileTimeErrorCode#CONST_WITH_TYPE_PARAMETERS
14667 */
14668 bool checkForConstWithTypeParameters(InstanceCreationExpression node) {
14669 ConstructorName constructorName = node.constructorName;
14670 if (constructorName == null) {
14671 return false;
14672 }
14673 TypeName typeName = constructorName.type;
14674 return checkForConstWithTypeParameters2(typeName);
14675 }
14676
14677 /**
14678 * This verifies that the passed type name does not reference any type paramet ers.
14679 *
14680 * @param typeName the type name to evaluate
14681 * @return `true` if and only if an error code is generated on the passed node
14682 * @see CompileTimeErrorCode#CONST_WITH_TYPE_PARAMETERS
14683 */
14684 bool checkForConstWithTypeParameters2(TypeName typeName) {
14685 if (typeName == null) {
14686 return false;
14687 }
14688 Identifier name = typeName.name;
14689 if (name == null) {
14690 return false;
14691 }
14692 if (name.staticElement is TypeParameterElement) {
14693 _errorReporter.reportError2(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETER S, name, []);
14694 }
14695 TypeArgumentList typeArguments = typeName.typeArguments;
14696 if (typeArguments != null) {
14697 bool hasError = false;
14698 for (TypeName argument in typeArguments.arguments) {
14699 hasError = javaBooleanOr(hasError, checkForConstWithTypeParameters2(argu ment));
14700 }
14701 return hasError;
14702 }
14703 return false;
14704 }
14705
14706 /**
14707 * This verifies that if the passed 'const' instance creation expression is be ing invoked on the
14708 * resolved constructor.
14709 *
14710 * This method assumes that the instance creation was tested to be 'const' bef ore being called.
14711 *
14712 * @param node the instance creation expression to evaluate
14713 * @return `true` if and only if an error code is generated on the passed node
14714 * @see CompileTimeErrorCode#CONST_WITH_UNDEFINED_CONSTRUCTOR
14715 * @see CompileTimeErrorCode#CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
14716 */
14717 bool checkForConstWithUndefinedConstructor(InstanceCreationExpression node) {
14718 if (node.staticElement != null) {
14719 return false;
14720 }
14721 ConstructorName constructorName = node.constructorName;
14722 if (constructorName == null) {
14723 return false;
14724 }
14725 TypeName type = constructorName.type;
14726 if (type == null) {
14727 return false;
14728 }
14729 Identifier className = type.name;
14730 SimpleIdentifier name = constructorName.name;
14731 if (name != null) {
14732 _errorReporter.reportError2(CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONS TRUCTOR, name, [className, name]);
14733 } else {
14734 _errorReporter.reportError2(CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONS TRUCTOR_DEFAULT, constructorName, [className]);
14735 }
14736 return true;
14737 }
14738
14739 /**
14740 * This verifies that there are no default parameters in the passed function t ype alias.
14741 *
14742 * @param node the function type alias to evaluate
14743 * @return `true` if and only if an error code is generated on the passed node
14744 * @see CompileTimeErrorCode#DEFAULT_VALUE_IN_FUNCTION_TYPE_ALIAS
14745 */
14746 bool checkForDefaultValueInFunctionTypeAlias(FunctionTypeAlias node) {
14747 bool result = false;
14748 FormalParameterList formalParameterList = node.parameters;
14749 NodeList<FormalParameter> parameters = formalParameterList.parameters;
14750 for (FormalParameter formalParameter in parameters) {
14751 if (formalParameter is DefaultFormalParameter) {
14752 DefaultFormalParameter defaultFormalParameter = formalParameter as Defau ltFormalParameter;
14753 if (defaultFormalParameter.defaultValue != null) {
14754 _errorReporter.reportError2(CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNC TION_TYPE_ALIAS, node, []);
14755 result = true;
14756 }
14757 }
14758 }
14759 return result;
14760 }
14761
14762 /**
14763 * This verifies that the given default formal parameter is not part of a func tion typed
14764 * parameter.
14765 *
14766 * @param node the default formal parameter to evaluate
14767 * @return `true` if and only if an error code is generated on the passed node
14768 * @see CompileTimeErrorCode#DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER
14769 */
14770 bool checkForDefaultValueInFunctionTypedParameter(DefaultFormalParameter node) {
14771 if (!_isInFunctionTypedFormalParameter) {
14772 return false;
14773 }
14774 if (node.defaultValue == null) {
14775 return false;
14776 }
14777 _errorReporter.reportError2(CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_T YPED_PARAMETER, node, []);
14778 return true;
14779 }
14780
14781 /**
14782 * This verifies that the enclosing class does not have an instance member wit h the given name of
14783 * the static member.
14784 *
14785 * @return `true` if and only if an error code is generated on the passed node
14786 * @see CompileTimeErrorCode#DUPLICATE_DEFINITION_INHERITANCE
14787 */
14788 bool checkForDuplicateDefinitionInheritance() {
14789 if (_enclosingClass == null) {
14790 return false;
14791 }
14792 bool hasProblem = false;
14793 for (ExecutableElement member in _enclosingClass.methods) {
14794 if (!member.isStatic) {
14795 continue;
14796 }
14797 hasProblem = javaBooleanOr(hasProblem, checkForDuplicateDefinitionInherita nce2(member));
14798 }
14799 for (ExecutableElement member in _enclosingClass.accessors) {
14800 if (!member.isStatic) {
14801 continue;
14802 }
14803 hasProblem = javaBooleanOr(hasProblem, checkForDuplicateDefinitionInherita nce2(member));
14804 }
14805 return hasProblem;
14806 }
14807
14808 /**
14809 * This verifies that the enclosing class does not have an instance member wit h the given name of
14810 * the static member.
14811 *
14812 * @param staticMember the static member to check conflict for
14813 * @return `true` if and only if an error code is generated on the passed node
14814 * @see CompileTimeErrorCode#DUPLICATE_DEFINITION_INHERITANCE
14815 */
14816 bool checkForDuplicateDefinitionInheritance2(ExecutableElement staticMember) {
14817 String name = staticMember.name;
14818 if (name == null) {
14819 return false;
14820 }
14821 ExecutableElement inheritedMember = _inheritanceManager.lookupInheritance(_e nclosingClass, name);
14822 if (inheritedMember == null) {
14823 return false;
14824 }
14825 if (inheritedMember.isStatic) {
14826 return false;
14827 }
14828 _errorReporter.reportError3(CompileTimeErrorCode.DUPLICATE_DEFINITION_INHERI TANCE, staticMember.nameOffset, name.length, [name, inheritedMember.enclosingEle ment.displayName]);
14829 return true;
14830 }
14831
14832 /**
14833 * This verifies if the passed list literal has type arguments then there is e xactly one.
14834 *
14835 * @param node the list literal to evaluate
14836 * @return `true` if and only if an error code is generated on the passed node
14837 * @see StaticTypeWarningCode#EXPECTED_ONE_LIST_TYPE_ARGUMENTS
14838 */
14839 bool checkForExpectedOneListTypeArgument(ListLiteral node) {
14840 TypeArgumentList typeArguments = node.typeArguments;
14841 if (typeArguments == null) {
14842 return false;
14843 }
14844 int num = typeArguments.arguments.length;
14845 if (num == 1) {
14846 return false;
14847 }
14848 _errorReporter.reportError2(StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARG UMENTS, typeArguments, [num]);
14849 return true;
14850 }
14851
14852 /**
14853 * This verifies the passed import has unique name among other exported librar ies.
14854 *
14855 * @param node the export directive to evaluate
14856 * @return `true` if and only if an error code is generated on the passed node
14857 * @see CompileTimeErrorCode#EXPORT_DUPLICATED_LIBRARY_NAME
14858 */
14859 bool checkForExportDuplicateLibraryName(ExportDirective node) {
14860 Element nodeElement = node.element;
14861 if (nodeElement is! ExportElement) {
14862 return false;
14863 }
14864 ExportElement nodeExportElement = nodeElement as ExportElement;
14865 LibraryElement nodeLibrary = nodeExportElement.exportedLibrary;
14866 if (nodeLibrary == null) {
14867 return false;
14868 }
14869 String name = nodeLibrary.name;
14870 LibraryElement prevLibrary = _nameToExportElement[name];
14871 if (prevLibrary != null) {
14872 if (prevLibrary != nodeLibrary) {
14873 _errorReporter.reportError2(StaticWarningCode.EXPORT_DUPLICATED_LIBRARY_ NAME, node, [
14874 prevLibrary.definingCompilationUnit.displayName,
14875 nodeLibrary.definingCompilationUnit.displayName,
14876 name]);
14877 return true;
14878 }
14879 } else {
14880 _nameToExportElement[name] = nodeLibrary;
14881 }
14882 return false;
14883 }
14884
14885 /**
14886 * Check that if the visiting library is not system, then any passed library s hould not be SDK
14887 * internal library.
14888 *
14889 * @param node the export directive to evaluate
14890 * @return `true` if and only if an error code is generated on the passed node
14891 * @see CompileTimeErrorCode#EXPORT_INTERNAL_LIBRARY
14892 */
14893 bool checkForExportInternalLibrary(ExportDirective node) {
14894 if (_isInSystemLibrary) {
14895 return false;
14896 }
14897 Element element = node.element;
14898 if (element is! ExportElement) {
14899 return false;
14900 }
14901 ExportElement exportElement = element as ExportElement;
14902 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk;
14903 String uri = exportElement.uri;
14904 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri);
14905 if (sdkLibrary == null) {
14906 return false;
14907 }
14908 if (!sdkLibrary.isInternal) {
14909 return false;
14910 }
14911 _errorReporter.reportError2(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, no de, [node.uri]);
14912 return true;
14913 }
14914
14915 /**
14916 * This verifies that the passed extends clause does not extend classes such a s num or String.
14917 *
14918 * @param node the extends clause to test
14919 * @return `true` if and only if an error code is generated on the passed node
14920 * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
14921 */
14922 bool checkForExtendsDisallowedClass(ExtendsClause extendsClause) {
14923 if (extendsClause == null) {
14924 return false;
14925 }
14926 return checkForExtendsOrImplementsDisallowedClass(extendsClause.superclass, CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS);
14927 }
14928
14929 /**
14930 * This verifies that the passed type name does not extend or implement classe s such as 'num' or
14931 * 'String'.
14932 *
14933 * @param node the type name to test
14934 * @return `true` if and only if an error code is generated on the passed node
14935 * @see #checkForExtendsDisallowedClass(ExtendsClause)
14936 * @see #checkForImplementsDisallowedClass(ImplementsClause)
14937 * @see CompileTimeErrorCode#EXTENDS_DISALLOWED_CLASS
14938 * @see CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS
14939 */
14940 bool checkForExtendsOrImplementsDisallowedClass(TypeName typeName, ErrorCode e rrorCode) {
14941 if (typeName.isSynthetic) {
14942 return false;
14943 }
14944 Type2 superType = typeName.type;
14945 for (InterfaceType disallowedType in _DISALLOWED_TYPES_TO_EXTEND_OR_IMPLEMEN T) {
14946 if (superType != null && superType == disallowedType) {
14947 if (superType == _typeProvider.numType) {
14948 ASTNode grandParent = typeName.parent.parent;
14949 if (grandParent is ClassDeclaration) {
14950 ClassElement classElement = ((grandParent as ClassDeclaration)).elem ent;
14951 Type2 classType = classElement.type;
14952 if (classType != null && (classType == _typeProvider.intType || clas sType == _typeProvider.doubleType)) {
14953 return false;
14954 }
14955 }
14956 }
14957 _errorReporter.reportError2(errorCode, typeName, [disallowedType.display Name]);
14958 return true;
14959 }
14960 }
14961 return false;
14962 }
14963
14964 /**
14965 * This verifies that the passed constructor field initializer has compatible field and
14966 * initializer expression types.
14967 *
14968 * @param node the constructor field initializer to test
14969 * @return `true` if and only if an error code is generated on the passed node
14970 * @see CompileTimeErrorCode#CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE
14971 * @see StaticWarningCode#FIELD_INITIALIZER_NOT_ASSIGNABLE
14972 */
14973 bool checkForFieldInitializerNotAssignable(ConstructorFieldInitializer node) {
14974 Element fieldNameElement = node.fieldName.staticElement;
14975 if (fieldNameElement is! FieldElement) {
14976 return false;
14977 }
14978 FieldElement fieldElement = fieldNameElement as FieldElement;
14979 Type2 fieldType = fieldElement.type;
14980 Expression expression = node.expression;
14981 if (expression == null) {
14982 return false;
14983 }
14984 Type2 staticType = getStaticType(expression);
14985 if (staticType == null) {
14986 return false;
14987 }
14988 if (staticType.isAssignableTo(fieldType)) {
14989 return false;
14990 } else if (_strictMode) {
14991 if (_isEnclosingConstructorConst) {
14992 _errorReporter.reportError2(CompileTimeErrorCode.CONST_FIELD_INITIALIZER _NOT_ASSIGNABLE, expression, [staticType.displayName, fieldType.displayName]);
14993 } else {
14994 _errorReporter.reportError2(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSI GNABLE, expression, [staticType.displayName, fieldType.displayName]);
14995 }
14996 return true;
14997 }
14998 Type2 propagatedType = expression.propagatedType;
14999 if (propagatedType != null && propagatedType.isAssignableTo(fieldType)) {
15000 return false;
15001 }
15002 if (_isEnclosingConstructorConst) {
15003 _errorReporter.reportError2(CompileTimeErrorCode.CONST_FIELD_INITIALIZER_N OT_ASSIGNABLE, expression, [
15004 (propagatedType == null ? staticType : propagatedType).displayName,
15005 fieldType.displayName]);
15006 } else {
15007 _errorReporter.reportError2(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGN ABLE, expression, [
15008 (propagatedType == null ? staticType : propagatedType).displayName,
15009 fieldType.displayName]);
15010 }
15011 return true;
15012 }
15013
15014 /**
15015 * This verifies that the passed field formal parameter is in a constructor de claration.
15016 *
15017 * @param node the field formal parameter to test
15018 * @return `true` if and only if an error code is generated on the passed node
15019 * @see CompileTimeErrorCode#FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
15020 */
15021 bool checkForFieldInitializingFormalRedirectingConstructor(FieldFormalParamete r node) {
15022 ConstructorDeclaration constructor = node.getAncestor(ConstructorDeclaration );
15023 if (constructor == null) {
15024 _errorReporter.reportError2(CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE _CONSTRUCTOR, node, []);
15025 return true;
15026 }
15027 if (constructor.factoryKeyword != null) {
15028 _errorReporter.reportError2(CompileTimeErrorCode.FIELD_INITIALIZER_FACTORY _CONSTRUCTOR, node, []);
15029 return true;
15030 }
15031 for (ConstructorInitializer initializer in constructor.initializers) {
15032 if (initializer is RedirectingConstructorInvocation) {
15033 _errorReporter.reportError2(CompileTimeErrorCode.FIELD_INITIALIZER_REDIR ECTING_CONSTRUCTOR, node, []);
15034 return true;
15035 }
15036 }
15037 return false;
15038 }
15039
15040 /**
15041 * This verifies that final fields that are declared, without any constructors in the enclosing
15042 * class, are initialized. Cases in which there is at least one constructor ar e handled at the end
15043 * of [checkForAllFinalInitializedErrorCodes].
15044 *
15045 * @param node the class declaration to test
15046 * @return `true` if and only if an error code is generated on the passed node
15047 * @see CompileTimeErrorCode#CONST_NOT_INITIALIZED
15048 * @see StaticWarningCode#FINAL_NOT_INITIALIZED
15049 */
15050 bool checkForFinalNotInitialized(ClassDeclaration node) {
15051 NodeList<ClassMember> classMembers = node.members;
15052 for (ClassMember classMember in classMembers) {
15053 if (classMember is ConstructorDeclaration) {
15054 return false;
15055 }
15056 }
15057 bool foundError = false;
15058 for (ClassMember classMember in classMembers) {
15059 if (classMember is FieldDeclaration) {
15060 FieldDeclaration field = classMember as FieldDeclaration;
15061 foundError = javaBooleanOr(foundError, checkForFinalNotInitialized2(fiel d.fields));
15062 }
15063 }
15064 return foundError;
15065 }
15066
15067 /**
15068 * This verifies that the passed variable declaration list has only initialize d variables if the
15069 * list is final or const. This method is called by
15070 * [checkForFinalNotInitialized],
15071 * [visitTopLevelVariableDeclaration] and
15072 * [visitVariableDeclarationStatement].
15073 *
15074 * @param node the class declaration to test
15075 * @return `true` if and only if an error code is generated on the passed node
15076 * @see CompileTimeErrorCode#CONST_NOT_INITIALIZED
15077 * @see StaticWarningCode#FINAL_NOT_INITIALIZED
15078 */
15079 bool checkForFinalNotInitialized2(VariableDeclarationList node) {
15080 if (_isInNativeClass) {
15081 return false;
15082 }
15083 bool foundError = false;
15084 if (!node.isSynthetic) {
15085 NodeList<VariableDeclaration> variables = node.variables;
15086 for (VariableDeclaration variable in variables) {
15087 if (variable.initializer == null) {
15088 if (node.isConst) {
15089 _errorReporter.reportError2(CompileTimeErrorCode.CONST_NOT_INITIALIZ ED, variable.name, [variable.name.name]);
15090 } else if (node.isFinal) {
15091 _errorReporter.reportError2(StaticWarningCode.FINAL_NOT_INITIALIZED, variable.name, [variable.name.name]);
15092 }
15093 foundError = true;
15094 }
15095 }
15096 }
15097 return foundError;
15098 }
15099
15100 /**
15101 * This verifies that the passed implements clause does not implement classes such as 'num' or
15102 * 'String'.
15103 *
15104 * @param node the implements clause to test
15105 * @return `true` if and only if an error code is generated on the passed node
15106 * @see CompileTimeErrorCode#IMPLEMENTS_DISALLOWED_CLASS
15107 */
15108 bool checkForImplementsDisallowedClass(ImplementsClause implementsClause) {
15109 if (implementsClause == null) {
15110 return false;
15111 }
15112 bool foundError = false;
15113 for (TypeName type in implementsClause.interfaces) {
15114 foundError = javaBooleanOr(foundError, checkForExtendsOrImplementsDisallow edClass(type, CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS));
15115 }
15116 return foundError;
15117 }
15118
15119 /**
15120 * This verifies that if the passed identifier is part of constructor initiali zer, then it does
15121 * not reference implicitly 'this' expression.
15122 *
15123 * @param node the simple identifier to test
15124 * @return `true` if and only if an error code is generated on the passed node
15125 * @see CompileTimeErrorCode#IMPLICIT_THIS_REFERENCE_IN_INITIALIZER
15126 * @see CompileTimeErrorCode#INSTANCE_MEMBER_ACCESS_FROM_STATIC TODO(scheglov) rename thid method
15127 */
15128 bool checkForImplicitThisReferenceInInitializer(SimpleIdentifier node) {
15129 if (!_isInConstructorInitializer && !_isInStaticMethod && !_isInInstanceVari ableInitializer && !_isInStaticVariableDeclaration) {
15130 return false;
15131 }
15132 Element element = node.staticElement;
15133 if (!(element is MethodElement || element is PropertyAccessorElement)) {
15134 return false;
15135 }
15136 ExecutableElement executableElement = element as ExecutableElement;
15137 if (executableElement.isStatic) {
15138 return false;
15139 }
15140 Element enclosingElement = element.enclosingElement;
15141 if (enclosingElement is! ClassElement) {
15142 return false;
15143 }
15144 ASTNode parent = node.parent;
15145 if (parent is CommentReference) {
15146 return false;
15147 }
15148 if (parent is MethodInvocation) {
15149 MethodInvocation invocation = parent as MethodInvocation;
15150 if (identical(invocation.methodName, node) && invocation.realTarget != nul l) {
15151 return false;
15152 }
15153 }
15154 if (parent is PropertyAccess) {
15155 PropertyAccess access = parent as PropertyAccess;
15156 if (identical(access.propertyName, node) && access.realTarget != null) {
15157 return false;
15158 }
15159 }
15160 if (parent is PrefixedIdentifier) {
15161 PrefixedIdentifier prefixed = parent as PrefixedIdentifier;
15162 if (identical(prefixed.identifier, node)) {
15163 return false;
15164 }
15165 }
15166 if (_isInStaticMethod) {
15167 _errorReporter.reportError2(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FR OM_STATIC, node, []);
15168 } else {
15169 _errorReporter.reportError2(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_I N_INITIALIZER, node, []);
15170 }
15171 return true;
15172 }
15173
15174 /**
15175 * This verifies the passed import has unique name among other imported librar ies.
15176 *
15177 * @param node the import directive to evaluate
15178 * @return `true` if and only if an error code is generated on the passed node
15179 * @see CompileTimeErrorCode#IMPORT_DUPLICATED_LIBRARY_NAME
15180 */
15181 bool checkForImportDuplicateLibraryName(ImportDirective node) {
15182 ImportElement nodeImportElement = node.element;
15183 if (nodeImportElement == null) {
15184 return false;
15185 }
15186 LibraryElement nodeLibrary = nodeImportElement.importedLibrary;
15187 if (nodeLibrary == null) {
15188 return false;
15189 }
15190 String name = nodeLibrary.name;
15191 LibraryElement prevLibrary = _nameToImportElement[name];
15192 if (prevLibrary != null) {
15193 if (prevLibrary != nodeLibrary) {
15194 _errorReporter.reportError2(StaticWarningCode.IMPORT_DUPLICATED_LIBRARY_ NAME, node, [
15195 prevLibrary.definingCompilationUnit.displayName,
15196 nodeLibrary.definingCompilationUnit.displayName,
15197 name]);
15198 return true;
15199 }
15200 } else {
15201 _nameToImportElement[name] = nodeLibrary;
15202 }
15203 return false;
15204 }
15205
15206 /**
15207 * Check that if the visiting library is not system, then any passed library s hould not be SDK
15208 * internal library.
15209 *
15210 * @param node the import directive to evaluate
15211 * @return `true` if and only if an error code is generated on the passed node
15212 * @see CompileTimeErrorCode#IMPORT_INTERNAL_LIBRARY
15213 */
15214 bool checkForImportInternalLibrary(ImportDirective node) {
15215 if (_isInSystemLibrary) {
15216 return false;
15217 }
15218 ImportElement importElement = node.element;
15219 if (importElement == null) {
15220 return false;
15221 }
15222 DartSdk sdk = _currentLibrary.context.sourceFactory.dartSdk;
15223 String uri = importElement.uri;
15224 SdkLibrary sdkLibrary = sdk.getSdkLibrary(uri);
15225 if (sdkLibrary == null) {
15226 return false;
15227 }
15228 if (!sdkLibrary.isInternal) {
15229 return false;
15230 }
15231 _errorReporter.reportError2(CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY, no de, [node.uri]);
15232 return true;
15233 }
15234
15235 /**
15236 * This verifies that the passed switch statement case expressions all have th e same type.
15237 *
15238 * @param node the switch statement to evaluate
15239 * @return `true` if and only if an error code is generated on the passed node
15240 * @see CompileTimeErrorCode#INCONSISTENT_CASE_EXPRESSION_TYPES
15241 */
15242 bool checkForInconsistentCaseExpressionTypes(SwitchStatement node) {
15243 NodeList<SwitchMember> switchMembers = node.members;
15244 bool foundError = false;
15245 Type2 firstType = null;
15246 for (SwitchMember switchMember in switchMembers) {
15247 if (switchMember is SwitchCase) {
15248 SwitchCase switchCase = switchMember as SwitchCase;
15249 Expression expression = switchCase.expression;
15250 if (firstType == null) {
15251 firstType = expression.bestType;
15252 } else {
15253 Type2 nType = expression.bestType;
15254 if (firstType != nType) {
15255 _errorReporter.reportError2(CompileTimeErrorCode.INCONSISTENT_CASE_E XPRESSION_TYPES, expression, [expression.toSource(), firstType.displayName]);
15256 foundError = true;
15257 }
15258 }
15259 }
15260 }
15261 if (!foundError) {
15262 checkForCaseExpressionTypeImplementsEquals(node, firstType);
15263 }
15264 return foundError;
15265 }
15266
15267 /**
15268 * For each class declaration, this method is called which verifies that all i nherited members are
15269 * inherited consistently.
15270 *
15271 * @return `true` if and only if an error code is generated on the passed node
15272 * @see StaticTypeWarningCode#INCONSISTENT_METHOD_INHERITANCE
15273 */
15274 bool checkForInconsistentMethodInheritance() {
15275 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(_enclosingClass);
15276 Set<AnalysisError> errors = _inheritanceManager.getErrors(_enclosingClass);
15277 if (errors == null || errors.isEmpty) {
15278 return false;
15279 }
15280 for (AnalysisError error in errors) {
15281 _errorReporter.reportError(error);
15282 }
15283 return true;
15284 }
15285
15286 /**
15287 * This checks that if the given "target" is not a type reference then the "na me" is reference to
15288 * an instance member.
15289 *
15290 * @param target the target of the name access to evaluate
15291 * @param name the accessed name to evaluate
15292 * @return `true` if and only if an error code is generated on the passed node
15293 * @see StaticTypeWarningCode#INSTANCE_ACCESS_TO_STATIC_MEMBER
15294 */
15295 bool checkForInstanceAccessToStaticMember(Expression target, SimpleIdentifier name) {
15296 if (target == null) {
15297 return false;
15298 }
15299 if (_isInComment) {
15300 return false;
15301 }
15302 Element element = name.staticElement;
15303 if (element is! ExecutableElement) {
15304 return false;
15305 }
15306 ExecutableElement executableElement = element as ExecutableElement;
15307 if (executableElement.enclosingElement is! ClassElement) {
15308 return false;
15309 }
15310 if (!executableElement.isStatic) {
15311 return false;
15312 }
15313 if (isTypeReference(target)) {
15314 return false;
15315 }
15316 _errorReporter.reportError2(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_ MEMBER, name, [name.name]);
15317 return true;
15318 }
15319
15320 /**
15321 * This verifies that an 'int' can be assigned to the parameter corresponding to the given
15322 * expression. This is used for prefix and postfix expressions where the argum ent value is
15323 * implicit.
15324 *
15325 * @param argument the expression to which the operator is being applied
15326 * @return `true` if and only if an error code is generated on the passed node
15327 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
15328 */
15329 bool checkForIntNotAssignable(Expression argument) {
15330 if (argument == null) {
15331 return false;
15332 }
15333 ParameterElement staticParameterElement = argument.staticParameterElement;
15334 Type2 staticParameterType = staticParameterElement == null ? null : staticPa rameterElement.type;
15335 ParameterElement propagatedParameterElement = argument.propagatedParameterEl ement;
15336 Type2 propagatedParameterType = propagatedParameterElement == null ? null : propagatedParameterElement.type;
15337 return checkForArgumentTypeNotAssignable4(argument, staticParameterType, _ty peProvider.intType, propagatedParameterType, _typeProvider.intType, StaticWarnin gCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
15338 }
15339
15340 /**
15341 * Given an assignment using a compound assignment operator, this verifies tha t the given
15342 * assignment is valid.
15343 *
15344 * @param node the assignment expression being tested
15345 * @return `true` if and only if an error code is generated on the passed node
15346 * @see StaticTypeWarningCode#INVALID_ASSIGNMENT
15347 */
15348 bool checkForInvalidAssignment(AssignmentExpression node) {
15349 Expression lhs = node.leftHandSide;
15350 if (lhs == null) {
15351 return false;
15352 }
15353 VariableElement leftElement = getVariableElement(lhs);
15354 Type2 leftType = (leftElement == null) ? getStaticType(lhs) : leftElement.ty pe;
15355 MethodElement invokedMethod = node.staticElement;
15356 if (invokedMethod == null) {
15357 return false;
15358 }
15359 Type2 rightType = invokedMethod.type.returnType;
15360 if (leftType == null || rightType == null) {
15361 return false;
15362 }
15363 if (!rightType.isAssignableTo(leftType)) {
15364 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, node .rightHandSide, [rightType.displayName, leftType.displayName]);
15365 return true;
15366 }
15367 return false;
15368 }
15369
15370 /**
15371 * This verifies that the passed left hand side and right hand side represent a valid assignment.
15372 *
15373 * @param lhs the left hand side expression
15374 * @param rhs the right hand side expression
15375 * @return `true` if and only if an error code is generated on the passed node
15376 * @see StaticTypeWarningCode#INVALID_ASSIGNMENT
15377 */
15378 bool checkForInvalidAssignment2(Expression lhs, Expression rhs) {
15379 if (lhs == null || rhs == null) {
15380 return false;
15381 }
15382 VariableElement leftElement = getVariableElement(lhs);
15383 Type2 leftType = (leftElement == null) ? getStaticType(lhs) : leftElement.ty pe;
15384 Type2 staticRightType = getStaticType(rhs);
15385 bool isStaticAssignable = staticRightType.isAssignableTo(leftType);
15386 Type2 propagatedRightType = rhs.propagatedType;
15387 if (_strictMode || propagatedRightType == null) {
15388 if (!isStaticAssignable) {
15389 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, rh s, [staticRightType.displayName, leftType.displayName]);
15390 return true;
15391 }
15392 } else {
15393 bool isPropagatedAssignable = propagatedRightType.isAssignableTo(leftType) ;
15394 if (!isStaticAssignable && !isPropagatedAssignable) {
15395 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, rh s, [staticRightType.displayName, leftType.displayName]);
15396 return true;
15397 }
15398 }
15399 return false;
15400 }
15401
15402 /**
15403 * This verifies that the usage of the passed 'this' is valid.
15404 *
15405 * @param node the 'this' expression to evaluate
15406 * @return `true` if and only if an error code is generated on the passed node
15407 * @see CompileTimeErrorCode#INVALID_REFERENCE_TO_THIS
15408 */
15409 bool checkForInvalidReferenceToThis(ThisExpression node) {
15410 if (!isThisInValidContext(node)) {
15411 _errorReporter.reportError2(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS , node, []);
15412 return true;
15413 }
15414 return false;
15415 }
15416
15417 /**
15418 * Checks to ensure that the passed [ListLiteral] or [MapLiteral] does not hav e a type
15419 * parameter as a type argument.
15420 *
15421 * @param arguments a non-`null`, non-empty [TypeName] node list from the resp ective
15422 * [ListLiteral] or [MapLiteral]
15423 * @param errorCode either [CompileTimeErrorCode#INVALID_TYPE_ARGUMENT_IN_CONS T_LIST] or
15424 * [CompileTimeErrorCode#INVALID_TYPE_ARGUMENT_IN_CONST_MAP]
15425 * @return `true` if and only if an error code is generated on the passed node
15426 */
15427 bool checkForInvalidTypeArgumentInConstTypedLiteral(NodeList<TypeName> argumen ts, ErrorCode errorCode) {
15428 bool foundError = false;
15429 for (TypeName typeName in arguments) {
15430 if (typeName.type is TypeParameterType) {
15431 _errorReporter.reportError2(errorCode, typeName, [typeName.name]);
15432 foundError = true;
15433 }
15434 }
15435 return foundError;
15436 }
15437
15438 /**
15439 * This verifies that the elements given [ListLiteral] are subtypes of the spe cified element
15440 * type.
15441 *
15442 * @param node the list literal to evaluate
15443 * @return `true` if and only if an error code is generated on the passed node
15444 * @see CompileTimeErrorCode#LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
15445 * @see StaticWarningCode#LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
15446 */
15447 bool checkForListElementTypeNotAssignable(ListLiteral node) {
15448 TypeArgumentList typeArgumentList = node.typeArguments;
15449 if (typeArgumentList == null) {
15450 return false;
15451 }
15452 NodeList<TypeName> typeArguments = typeArgumentList.arguments;
15453 if (typeArguments.length < 1) {
15454 return false;
15455 }
15456 Type2 listElementType = typeArguments[0].type;
15457 ErrorCode errorCode;
15458 if (node.constKeyword != null) {
15459 errorCode = CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE;
15460 } else {
15461 errorCode = StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE;
15462 }
15463 bool hasProblems = false;
15464 for (Expression element in node.elements) {
15465 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(element, listElementType, null, errorCode));
15466 }
15467 return hasProblems;
15468 }
15469
15470 /**
15471 * This verifies that the key/value of entries of the given [MapLiteral] are s ubtypes of the
15472 * key/value types specified in the type arguments.
15473 *
15474 * @param node the map literal to evaluate
15475 * @return `true` if and only if an error code is generated on the passed node
15476 * @see CompileTimeErrorCode#MAP_KEY_TYPE_NOT_ASSIGNABLE
15477 * @see CompileTimeErrorCode#MAP_VALUE_TYPE_NOT_ASSIGNABLE
15478 * @see StaticWarningCode#MAP_KEY_TYPE_NOT_ASSIGNABLE
15479 * @see StaticWarningCode#MAP_VALUE_TYPE_NOT_ASSIGNABLE
15480 */
15481 bool checkForMapTypeNotAssignable(MapLiteral node) {
15482 TypeArgumentList typeArgumentList = node.typeArguments;
15483 if (typeArgumentList == null) {
15484 return false;
15485 }
15486 NodeList<TypeName> typeArguments = typeArgumentList.arguments;
15487 if (typeArguments.length < 2) {
15488 return false;
15489 }
15490 Type2 keyType = typeArguments[0].type;
15491 Type2 valueType = typeArguments[1].type;
15492 ErrorCode keyErrorCode;
15493 ErrorCode valueErrorCode;
15494 if (node.constKeyword != null) {
15495 keyErrorCode = CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE;
15496 valueErrorCode = CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE;
15497 } else {
15498 keyErrorCode = StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE;
15499 valueErrorCode = StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE;
15500 }
15501 bool hasProblems = false;
15502 NodeList<MapLiteralEntry> entries = node.entries;
15503 for (MapLiteralEntry entry in entries) {
15504 Expression key = entry.key;
15505 Expression value = entry.value;
15506 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(key, keyType, null, keyErrorCode));
15507 hasProblems = javaBooleanOr(hasProblems, checkForArgumentTypeNotAssignable 3(value, valueType, null, valueErrorCode));
15508 }
15509 return hasProblems;
15510 }
15511
15512 /**
15513 * This verifies that the [enclosingClass] does not define members with the sa me name as
15514 * the enclosing class.
15515 *
15516 * @return `true` if and only if an error code is generated on the passed node
15517 * @see CompileTimeErrorCode#MEMBER_WITH_CLASS_NAME
15518 */
15519 bool checkForMemberWithClassName() {
15520 if (_enclosingClass == null) {
15521 return false;
15522 }
15523 String className = _enclosingClass.name;
15524 if (className == null) {
15525 return false;
15526 }
15527 bool problemReported = false;
15528 for (PropertyAccessorElement accessor in _enclosingClass.accessors) {
15529 if (className == accessor.name) {
15530 _errorReporter.reportError3(CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME, accessor.nameOffset, className.length, []);
15531 problemReported = true;
15532 }
15533 }
15534 return problemReported;
15535 }
15536
15537 /**
15538 * Check to make sure that all similarly typed accessors are of the same type (including inherited
15539 * accessors).
15540 *
15541 * @param node the accessor currently being visited
15542 * @return `true` if and only if an error code is generated on the passed node
15543 * @see StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES
15544 * @see StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES_FROM_SUPERTYPE
15545 */
15546 bool checkForMismatchedAccessorTypes(Declaration accessorDeclaration, String a ccessorTextName) {
15547 ExecutableElement accessorElement = accessorDeclaration.element as Executabl eElement;
15548 if (accessorElement is! PropertyAccessorElement) {
15549 return false;
15550 }
15551 PropertyAccessorElement propertyAccessorElement = accessorElement as Propert yAccessorElement;
15552 PropertyAccessorElement counterpartAccessor = null;
15553 ClassElement enclosingClassForCounterpart = null;
15554 if (propertyAccessorElement.isGetter) {
15555 counterpartAccessor = propertyAccessorElement.correspondingSetter;
15556 } else {
15557 counterpartAccessor = propertyAccessorElement.correspondingGetter;
15558 if (counterpartAccessor != null && identical(counterpartAccessor.enclosing Element, propertyAccessorElement.enclosingElement)) {
15559 return false;
15560 }
15561 }
15562 if (counterpartAccessor == null) {
15563 if (_enclosingClass != null) {
15564 String lookupIdentifier = propertyAccessorElement.name;
15565 if (lookupIdentifier.endsWith("=")) {
15566 lookupIdentifier = lookupIdentifier.substring(0, lookupIdentifier.leng th - 1);
15567 } else {
15568 lookupIdentifier += "=";
15569 }
15570 ExecutableElement elementFromInheritance = _inheritanceManager.lookupInh eritance(_enclosingClass, lookupIdentifier);
15571 if (elementFromInheritance != null && elementFromInheritance is Property AccessorElement) {
15572 enclosingClassForCounterpart = elementFromInheritance.enclosingElement as ClassElement;
15573 counterpartAccessor = elementFromInheritance as PropertyAccessorElemen t;
15574 }
15575 }
15576 if (counterpartAccessor == null) {
15577 return false;
15578 }
15579 }
15580 Type2 getterType = null;
15581 Type2 setterType = null;
15582 if (propertyAccessorElement.isGetter) {
15583 getterType = getGetterType(propertyAccessorElement);
15584 setterType = getSetterType(counterpartAccessor);
15585 } else if (propertyAccessorElement.isSetter) {
15586 setterType = getSetterType(propertyAccessorElement);
15587 getterType = getGetterType(counterpartAccessor);
15588 }
15589 if (setterType != null && getterType != null && !getterType.isAssignableTo(s etterType)) {
15590 if (enclosingClassForCounterpart == null) {
15591 _errorReporter.reportError2(StaticWarningCode.MISMATCHED_GETTER_AND_SETT ER_TYPES, accessorDeclaration, [
15592 accessorTextName,
15593 setterType.displayName,
15594 getterType.displayName]);
15595 return true;
15596 } else {
15597 _errorReporter.reportError2(StaticWarningCode.MISMATCHED_GETTER_AND_SETT ER_TYPES_FROM_SUPERTYPE, accessorDeclaration, [
15598 accessorTextName,
15599 setterType.displayName,
15600 getterType.displayName,
15601 enclosingClassForCounterpart.displayName]);
15602 }
15603 }
15604 return false;
15605 }
15606
15607 /**
15608 * This verifies that the given function body does not contain return statemen ts that both have
15609 * and do not have return values.
15610 *
15611 * @param node the function body being tested
15612 * @return `true` if and only if an error code is generated on the passed node
15613 * @see StaticWarningCode#MIXED_RETURN_TYPES
15614 */
15615 bool checkForMixedReturns(BlockFunctionBody node) {
15616 if (_returnWithCount > 0 && _returnWithoutCount > 0) {
15617 _errorReporter.reportError2(StaticWarningCode.MIXED_RETURN_TYPES, node, [] );
15618 return true;
15619 }
15620 return false;
15621 }
15622
15623 /**
15624 * This verifies that the passed mixin does not have an explicitly declared co nstructor.
15625 *
15626 * @param mixinName the node to report problem on
15627 * @param mixinElement the mixing to evaluate
15628 * @return `true` if and only if an error code is generated on the passed node
15629 * @see CompileTimeErrorCode#MIXIN_DECLARES_CONSTRUCTOR
15630 */
15631 bool checkForMixinDeclaresConstructor(TypeName mixinName, ClassElement mixinEl ement) {
15632 for (ConstructorElement constructor in mixinElement.constructors) {
15633 if (!constructor.isSynthetic && !constructor.isFactory) {
15634 _errorReporter.reportError2(CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUC TOR, mixinName, [mixinElement.name]);
15635 return true;
15636 }
15637 }
15638 return false;
15639 }
15640
15641 /**
15642 * This verifies that the passed mixin has the 'Object' superclass.
15643 *
15644 * @param mixinName the node to report problem on
15645 * @param mixinElement the mixing to evaluate
15646 * @return `true` if and only if an error code is generated on the passed node
15647 * @see CompileTimeErrorCode#MIXIN_INHERITS_FROM_NOT_OBJECT
15648 */
15649 bool checkForMixinInheritsNotFromObject(TypeName mixinName, ClassElement mixin Element) {
15650 InterfaceType mixinSupertype = mixinElement.supertype;
15651 if (mixinSupertype != null) {
15652 if (!mixinSupertype.isObject || !mixinElement.isTypedef && mixinElement.mi xins.length != 0) {
15653 _errorReporter.reportError2(CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT _OBJECT, mixinName, [mixinElement.name]);
15654 return true;
15655 }
15656 }
15657 return false;
15658 }
15659
15660 /**
15661 * This verifies that the passed mixin does not reference 'super'.
15662 *
15663 * @param mixinName the node to report problem on
15664 * @param mixinElement the mixing to evaluate
15665 * @return `true` if and only if an error code is generated on the passed node
15666 * @see CompileTimeErrorCode#MIXIN_REFERENCES_SUPER
15667 */
15668 bool checkForMixinReferencesSuper(TypeName mixinName, ClassElement mixinElemen t) {
15669 if (mixinElement.hasReferenceToSuper()) {
15670 _errorReporter.reportError2(CompileTimeErrorCode.MIXIN_REFERENCES_SUPER, m ixinName, [mixinElement.name]);
15671 }
15672 return false;
15673 }
15674
15675 /**
15676 * This verifies that the passed constructor has at most one 'super' initializ er.
15677 *
15678 * @param node the constructor declaration to evaluate
15679 * @return `true` if and only if an error code is generated on the passed node
15680 * @see CompileTimeErrorCode#MULTIPLE_SUPER_INITIALIZERS
15681 */
15682 bool checkForMultipleSuperInitializers(ConstructorDeclaration node) {
15683 int numSuperInitializers = 0;
15684 for (ConstructorInitializer initializer in node.initializers) {
15685 if (initializer is SuperConstructorInvocation) {
15686 numSuperInitializers++;
15687 if (numSuperInitializers > 1) {
15688 _errorReporter.reportError2(CompileTimeErrorCode.MULTIPLE_SUPER_INITIA LIZERS, initializer, []);
15689 }
15690 }
15691 }
15692 return numSuperInitializers > 0;
15693 }
15694
15695 /**
15696 * Checks to ensure that native function bodies can only in SDK code.
15697 *
15698 * @param node the native function body to test
15699 * @return `true` if and only if an error code is generated on the passed node
15700 * @see ParserErrorCode#NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
15701 */
15702 bool checkForNativeFunctionBodyInNonSDKCode(NativeFunctionBody node) {
15703 if (!_isInSystemLibrary) {
15704 _errorReporter.reportError2(ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SD K_CODE, node, []);
15705 return true;
15706 }
15707 return false;
15708 }
15709
15710 /**
15711 * This verifies that the passed 'new' instance creation expression invokes ex isting constructor.
15712 *
15713 * This method assumes that the instance creation was tested to be 'new' befor e being called.
15714 *
15715 * @param node the instance creation expression to evaluate
15716 * @return `true` if and only if an error code is generated on the passed node
15717 * @see StaticWarningCode#NEW_WITH_UNDEFINED_CONSTRUCTOR
15718 */
15719 bool checkForNewWithUndefinedConstructor(InstanceCreationExpression node) {
15720 if (node.staticElement != null) {
15721 return false;
15722 }
15723 ConstructorName constructorName = node.constructorName;
15724 if (constructorName == null) {
15725 return false;
15726 }
15727 TypeName type = constructorName.type;
15728 if (type == null) {
15729 return false;
15730 }
15731 Identifier className = type.name;
15732 SimpleIdentifier name = constructorName.name;
15733 if (name != null) {
15734 _errorReporter.reportError2(StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCT OR, name, [className, name]);
15735 } else {
15736 _errorReporter.reportError2(StaticWarningCode.NEW_WITH_UNDEFINED_CONSTRUCT OR_DEFAULT, constructorName, [className]);
15737 }
15738 return true;
15739 }
15740
15741 /**
15742 * This checks that if the passed class declaration implicitly calls default c onstructor of its
15743 * superclass, there should be such default constructor - implicit or explicit .
15744 *
15745 * @param node the [ClassDeclaration] to evaluate
15746 * @return `true` if and only if an error code is generated on the passed node
15747 * @see CompileTimeErrorCode#NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT
15748 */
15749 bool checkForNoDefaultSuperConstructorImplicit(ClassDeclaration node) {
15750 List<ConstructorElement> constructors = _enclosingClass.constructors;
15751 if (!constructors[0].isSynthetic) {
15752 return false;
15753 }
15754 InterfaceType superType = _enclosingClass.supertype;
15755 if (superType == null) {
15756 return false;
15757 }
15758 ClassElement superElement = superType.element;
15759 ConstructorElement superUnnamedConstructor = superElement.unnamedConstructor ;
15760 if (superUnnamedConstructor != null) {
15761 if (superUnnamedConstructor.isFactory) {
15762 _errorReporter.reportError2(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUC TOR, node.name, [superUnnamedConstructor]);
15763 return true;
15764 }
15765 if (superUnnamedConstructor.isDefaultConstructor) {
15766 return true;
15767 }
15768 }
15769 _errorReporter.reportError2(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTO R_IMPLICIT, node.name, [superType.displayName]);
15770 return true;
15771 }
15772
15773 /**
15774 * This checks that passed class declaration overrides all members required by its superclasses
15775 * and interfaces.
15776 *
15777 * @param node the [ClassDeclaration] to evaluate
15778 * @return `true` if and only if an error code is generated on the passed node
15779 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE
15780 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO
15781 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE
15782 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR
15783 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLU S
15784 */
15785 bool checkForNonAbstractClassInheritsAbstractMember(ClassDeclaration node) {
15786 if (_enclosingClass.isAbstract) {
15787 return false;
15788 }
15789 List<MethodElement> methods = _enclosingClass.methods;
15790 List<PropertyAccessorElement> accessors = _enclosingClass.accessors;
15791 Set<String> methodsInEnclosingClass = new Set<String>();
15792 for (MethodElement method in methods) {
15793 String methodName = method.name;
15794 if (methodName == ElementResolver.NO_SUCH_METHOD_METHOD_NAME) {
15795 return false;
15796 }
15797 javaSetAdd(methodsInEnclosingClass, methodName);
15798 }
15799 Set<String> accessorsInEnclosingClass = new Set<String>();
15800 for (PropertyAccessorElement accessor in accessors) {
15801 javaSetAdd(accessorsInEnclosingClass, accessor.name);
15802 }
15803 Set<ExecutableElement> missingOverrides = new Set<ExecutableElement>();
15804 MemberMap membersInheritedFromInterfaces = _inheritanceManager.getMapOfMembe rsInheritedFromInterfaces(_enclosingClass);
15805 MemberMap membersInheritedFromSuperclasses = _inheritanceManager.getMapOfMem bersInheritedFromClasses(_enclosingClass);
15806 for (int i = 0; i < membersInheritedFromInterfaces.size; i++) {
15807 String memberName = membersInheritedFromInterfaces.getKey(i);
15808 ExecutableElement executableElt = membersInheritedFromInterfaces.getValue( i);
15809 if (memberName == null) {
15810 break;
15811 }
15812 ExecutableElement elt = membersInheritedFromSuperclasses.get(executableElt .name);
15813 if (elt != null) {
15814 if (elt is MethodElement && !((elt as MethodElement)).isAbstract) {
15815 continue;
15816 } else if (elt is PropertyAccessorElement && !((elt as PropertyAccessorE lement)).isAbstract) {
15817 continue;
15818 }
15819 }
15820 if (executableElt is MethodElement) {
15821 if (!methodsInEnclosingClass.contains(memberName) && !memberHasConcreteM ethodImplementationInSuperclassChain(_enclosingClass, memberName, new List<Class Element>())) {
15822 javaSetAdd(missingOverrides, executableElt);
15823 }
15824 } else if (executableElt is PropertyAccessorElement) {
15825 if (!accessorsInEnclosingClass.contains(memberName) && !memberHasConcret eAccessorImplementationInSuperclassChain(_enclosingClass, memberName, new List<C lassElement>())) {
15826 javaSetAdd(missingOverrides, executableElt);
15827 }
15828 }
15829 }
15830 int missingOverridesSize = missingOverrides.length;
15831 if (missingOverridesSize == 0) {
15832 return false;
15833 }
15834 List<ExecutableElement> missingOverridesArray = new List.from(missingOverrid es);
15835 List<String> stringMembersArrayListSet = new List<String>();
15836 for (int i = 0; i < missingOverridesArray.length; i++) {
15837 String newStrMember = "${missingOverridesArray[i].enclosingElement.display Name}.${missingOverridesArray[i].displayName}";
15838 if (!stringMembersArrayListSet.contains(newStrMember)) {
15839 stringMembersArrayListSet.add(newStrMember);
15840 }
15841 }
15842 List<String> stringMembersArray = new List.from(stringMembersArrayListSet);
15843 AnalysisErrorWithProperties analysisError;
15844 if (stringMembersArray.length == 1) {
15845 analysisError = _errorReporter.newErrorWithProperties(StaticWarningCode.NO N_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE, node.name, [stringMembersArray[0] ]);
15846 } else if (stringMembersArray.length == 2) {
15847 analysisError = _errorReporter.newErrorWithProperties(StaticWarningCode.NO N_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO, node.name, [stringMembersArray[0] , stringMembersArray[1]]);
15848 } else if (stringMembersArray.length == 3) {
15849 analysisError = _errorReporter.newErrorWithProperties(StaticWarningCode.NO N_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE, node.name, [
15850 stringMembersArray[0],
15851 stringMembersArray[1],
15852 stringMembersArray[2]]);
15853 } else if (stringMembersArray.length == 4) {
15854 analysisError = _errorReporter.newErrorWithProperties(StaticWarningCode.NO N_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR, node.name, [
15855 stringMembersArray[0],
15856 stringMembersArray[1],
15857 stringMembersArray[2],
15858 stringMembersArray[3]]);
15859 } else {
15860 analysisError = _errorReporter.newErrorWithProperties(StaticWarningCode.NO N_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS, node.name, [
15861 stringMembersArray[0],
15862 stringMembersArray[1],
15863 stringMembersArray[2],
15864 stringMembersArray[3],
15865 stringMembersArray.length - 4]);
15866 }
15867 analysisError.setProperty(ErrorProperty.UNIMPLEMENTED_METHODS, missingOverri desArray);
15868 _errorReporter.reportError(analysisError);
15869 return true;
15870 }
15871
15872 /**
15873 * Checks to ensure that the expressions that need to be of type bool, are. Ot herwise an error is
15874 * reported on the expression.
15875 *
15876 * @param condition the conditional expression to test
15877 * @return `true` if and only if an error code is generated on the passed node
15878 * @see StaticTypeWarningCode#NON_BOOL_CONDITION
15879 */
15880 bool checkForNonBoolCondition(Expression condition) {
15881 Type2 conditionType = getStaticType(condition);
15882 if (conditionType != null && !conditionType.isAssignableTo(_typeProvider.boo lType)) {
15883 _errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_CONDITION, cond ition, []);
15884 return true;
15885 }
15886 return false;
15887 }
15888
15889 /**
15890 * This verifies that the passed assert statement has either a 'bool' or '() - > bool' input.
15891 *
15892 * @param node the assert statement to evaluate
15893 * @return `true` if and only if an error code is generated on the passed node
15894 * @see StaticTypeWarningCode#NON_BOOL_EXPRESSION
15895 */
15896 bool checkForNonBoolExpression(AssertStatement node) {
15897 Expression expression = node.condition;
15898 Type2 type = getStaticType(expression);
15899 if (type is InterfaceType) {
15900 if (!type.isAssignableTo(_typeProvider.boolType)) {
15901 _errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_EXPRESSION, e xpression, []);
15902 return true;
15903 }
15904 } else if (type is FunctionType) {
15905 FunctionType functionType = type as FunctionType;
15906 if (functionType.typeArguments.length == 0 && !functionType.returnType.isA ssignableTo(_typeProvider.boolType)) {
15907 _errorReporter.reportError2(StaticTypeWarningCode.NON_BOOL_EXPRESSION, e xpression, []);
15908 return true;
15909 }
15910 }
15911 return false;
15912 }
15913
15914 /**
15915 * This verifies the passed map literal either:
15916 *
15917 * * has `const modifier`
15918 * * has explicit type arguments
15919 * * is not start of the statement
15920 *
15921 *
15922 * @param node the map literal to evaluate
15923 * @return `true` if and only if an error code is generated on the passed node
15924 * @see CompileTimeErrorCode#NON_CONST_MAP_AS_EXPRESSION_STATEMENT
15925 */
15926 bool checkForNonConstMapAsExpressionStatement(MapLiteral node) {
15927 if (node.constKeyword != null) {
15928 return false;
15929 }
15930 if (node.typeArguments != null) {
15931 return false;
15932 }
15933 Statement statement = node.getAncestor(ExpressionStatement);
15934 if (statement == null) {
15935 return false;
15936 }
15937 if (statement.beginToken != node.beginToken) {
15938 return false;
15939 }
15940 _errorReporter.reportError2(CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION _STATEMENT, node, []);
15941 return true;
15942 }
15943
15944 /**
15945 * This verifies the passed method declaration of operator `[]=`, has `void` r eturn
15946 * type.
15947 *
15948 * @param node the method declaration to evaluate
15949 * @return `true` if and only if an error code is generated on the passed node
15950 * @see StaticWarningCode#NON_VOID_RETURN_FOR_OPERATOR
15951 */
15952 bool checkForNonVoidReturnTypeForOperator(MethodDeclaration node) {
15953 SimpleIdentifier name = node.name;
15954 if (name.name != "[]=") {
15955 return false;
15956 }
15957 TypeName typeName = node.returnType;
15958 if (typeName != null) {
15959 Type2 type = typeName.type;
15960 if (type != null && !type.isVoid) {
15961 _errorReporter.reportError2(StaticWarningCode.NON_VOID_RETURN_FOR_OPERAT OR, typeName, []);
15962 }
15963 }
15964 return false;
15965 }
15966
15967 /**
15968 * This verifies the passed setter has no return type or the `void` return typ e.
15969 *
15970 * @param typeName the type name to evaluate
15971 * @return `true` if and only if an error code is generated on the passed node
15972 * @see StaticWarningCode#NON_VOID_RETURN_FOR_SETTER
15973 */
15974 bool checkForNonVoidReturnTypeForSetter(TypeName typeName) {
15975 if (typeName != null) {
15976 Type2 type = typeName.type;
15977 if (type != null && !type.isVoid) {
15978 _errorReporter.reportError2(StaticWarningCode.NON_VOID_RETURN_FOR_SETTER , typeName, []);
15979 }
15980 }
15981 return false;
15982 }
15983
15984 /**
15985 * This verifies the passed operator-method declaration, does not have an opti onal parameter.
15986 *
15987 * This method assumes that the method declaration was tested to be an operato r declaration before
15988 * being called.
15989 *
15990 * @param node the method declaration to evaluate
15991 * @return `true` if and only if an error code is generated on the passed node
15992 * @see CompileTimeErrorCode#OPTIONAL_PARAMETER_IN_OPERATOR
15993 */
15994 bool checkForOptionalParameterInOperator(MethodDeclaration node) {
15995 FormalParameterList parameterList = node.parameters;
15996 if (parameterList == null) {
15997 return false;
15998 }
15999 bool foundError = false;
16000 NodeList<FormalParameter> formalParameters = parameterList.parameters;
16001 for (FormalParameter formalParameter in formalParameters) {
16002 if (formalParameter.kind.isOptional) {
16003 _errorReporter.reportError2(CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_O PERATOR, formalParameter, []);
16004 foundError = true;
16005 }
16006 }
16007 return foundError;
16008 }
16009
16010 /**
16011 * This checks for named optional parameters that begin with '_'.
16012 *
16013 * @param node the default formal parameter to evaluate
16014 * @return `true` if and only if an error code is generated on the passed node
16015 * @see CompileTimeErrorCode#PRIVATE_OPTIONAL_PARAMETER
16016 */
16017 bool checkForPrivateOptionalParameter(FormalParameter node) {
16018 if (node.kind != ParameterKind.NAMED) {
16019 return false;
16020 }
16021 SimpleIdentifier name = node.identifier;
16022 if (name.isSynthetic || !name.name.startsWith("_")) {
16023 return false;
16024 }
16025 _errorReporter.reportError2(CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER, node, []);
16026 return true;
16027 }
16028
16029 /**
16030 * This checks if the passed constructor declaration is the redirecting genera tive constructor and
16031 * references itself directly or indirectly.
16032 *
16033 * @param node the constructor declaration to evaluate
16034 * @return `true` if and only if an error code is generated on the passed node
16035 * @see CompileTimeErrorCode#RECURSIVE_CONSTRUCTOR_REDIRECT
16036 */
16037 bool checkForRecursiveConstructorRedirect(ConstructorDeclaration node) {
16038 if (node.factoryKeyword != null) {
16039 return false;
16040 }
16041 for (ConstructorInitializer initializer in node.initializers) {
16042 if (initializer is RedirectingConstructorInvocation) {
16043 ConstructorElement element = node.element;
16044 if (!hasRedirectingFactoryConstructorCycle(element)) {
16045 return false;
16046 }
16047 _errorReporter.reportError2(CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_R EDIRECT, initializer, []);
16048 return true;
16049 }
16050 }
16051 return false;
16052 }
16053
16054 /**
16055 * This checks if the passed constructor declaration has redirected constructo r and references
16056 * itself directly or indirectly.
16057 *
16058 * @param node the constructor declaration to evaluate
16059 * @return `true` if and only if an error code is generated on the passed node
16060 * @see CompileTimeErrorCode#RECURSIVE_FACTORY_REDIRECT
16061 */
16062 bool checkForRecursiveFactoryRedirect(ConstructorDeclaration node) {
16063 ConstructorName redirectedConstructorNode = node.redirectedConstructor;
16064 if (redirectedConstructorNode == null) {
16065 return false;
16066 }
16067 ConstructorElement element = node.element;
16068 if (!hasRedirectingFactoryConstructorCycle(element)) {
16069 return false;
16070 }
16071 _errorReporter.reportError2(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, redirectedConstructorNode, []);
16072 return true;
16073 }
16074
16075 /**
16076 * This checks the class declaration is not a superinterface to itself.
16077 *
16078 * @param classElt the class element to test
16079 * @return `true` if and only if an error code is generated on the passed elem ent
16080 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE
16081 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS
16082 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEME NTS
16083 */
16084 bool checkForRecursiveInterfaceInheritance(ClassElement classElt) {
16085 if (classElt == null) {
16086 return false;
16087 }
16088 return checkForRecursiveInterfaceInheritance2(classElt, new List<ClassElemen t>());
16089 }
16090
16091 /**
16092 * This checks the class declaration is not a superinterface to itself.
16093 *
16094 * @param classElt the class element to test
16095 * @param path a list containing the potentially cyclic implements path
16096 * @return `true` if and only if an error code is generated on the passed elem ent
16097 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE
16098 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS
16099 * @see CompileTimeErrorCode#RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEME NTS
16100 */
16101 bool checkForRecursiveInterfaceInheritance2(ClassElement classElt, List<ClassE lement> path) {
16102 int size = path.length;
16103 if (size > 0 && _enclosingClass == classElt) {
16104 String enclosingClassName = _enclosingClass.displayName;
16105 if (size > 1) {
16106 String separator = ", ";
16107 JavaStringBuilder builder = new JavaStringBuilder();
16108 for (int i = 0; i < size; i++) {
16109 builder.append(path[i].displayName);
16110 builder.append(separator);
16111 }
16112 builder.append(classElt.displayName);
16113 _errorReporter.reportError3(CompileTimeErrorCode.RECURSIVE_INTERFACE_INH ERITANCE, _enclosingClass.nameOffset, enclosingClassName.length, [enclosingClass Name, builder.toString()]);
16114 return true;
16115 } else {
16116 InterfaceType supertype = classElt.supertype;
16117 ErrorCode errorCode = (supertype != null && _enclosingClass == supertype .element ? CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTEND S : CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS) a s ErrorCode;
16118 _errorReporter.reportError3(errorCode, _enclosingClass.nameOffset, enclo singClassName.length, [enclosingClassName]);
16119 return true;
16120 }
16121 }
16122 if (path.indexOf(classElt) > 0) {
16123 return false;
16124 }
16125 path.add(classElt);
16126 InterfaceType supertype = classElt.supertype;
16127 if (supertype != null && checkForRecursiveInterfaceInheritance2(supertype.el ement, path)) {
16128 return true;
16129 }
16130 List<InterfaceType> interfaceTypes = classElt.interfaces;
16131 for (InterfaceType interfaceType in interfaceTypes) {
16132 if (checkForRecursiveInterfaceInheritance2(interfaceType.element, path)) {
16133 return true;
16134 }
16135 }
16136 path.removeAt(path.length - 1);
16137 return false;
16138 }
16139
16140 /**
16141 * This checks the passed constructor declaration has a valid combination of r edirected
16142 * constructor invocation(s), super constructor invocations and field initiali zers.
16143 *
16144 * @param node the constructor declaration to evaluate
16145 * @return `true` if and only if an error code is generated on the passed node
16146 * @see CompileTimeErrorCode#DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR
16147 * @see CompileTimeErrorCode#FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR
16148 * @see CompileTimeErrorCode#MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS
16149 * @see CompileTimeErrorCode#SUPER_IN_REDIRECTING_CONSTRUCTOR
16150 */
16151 bool checkForRedirectingConstructorErrorCodes(ConstructorDeclaration node) {
16152 bool errorReported = false;
16153 ConstructorName redirectedConstructor = node.redirectedConstructor;
16154 if (redirectedConstructor != null) {
16155 for (FormalParameter parameter in node.parameters.parameters) {
16156 if (parameter is DefaultFormalParameter && ((parameter as DefaultFormalP arameter)).defaultValue != null) {
16157 _errorReporter.reportError2(CompileTimeErrorCode.DEFAULT_VALUE_IN_REDI RECTING_FACTORY_CONSTRUCTOR, parameter.identifier, []);
16158 errorReported = true;
16159 }
16160 }
16161 }
16162 int numRedirections = 0;
16163 for (ConstructorInitializer initializer in node.initializers) {
16164 if (initializer is RedirectingConstructorInvocation) {
16165 if (numRedirections > 0) {
16166 _errorReporter.reportError2(CompileTimeErrorCode.MULTIPLE_REDIRECTING_ CONSTRUCTOR_INVOCATIONS, initializer, []);
16167 errorReported = true;
16168 }
16169 numRedirections++;
16170 }
16171 }
16172 if (numRedirections > 0) {
16173 for (ConstructorInitializer initializer in node.initializers) {
16174 if (initializer is SuperConstructorInvocation) {
16175 _errorReporter.reportError2(CompileTimeErrorCode.SUPER_IN_REDIRECTING_ CONSTRUCTOR, initializer, []);
16176 errorReported = true;
16177 }
16178 if (initializer is ConstructorFieldInitializer) {
16179 _errorReporter.reportError2(CompileTimeErrorCode.FIELD_INITIALIZER_RED IRECTING_CONSTRUCTOR, initializer, []);
16180 errorReported = true;
16181 }
16182 }
16183 }
16184 return errorReported;
16185 }
16186
16187 /**
16188 * This checks if the passed constructor declaration has redirected constructo r and references
16189 * itself directly or indirectly.
16190 *
16191 * @param node the constructor declaration to evaluate
16192 * @return `true` if and only if an error code is generated on the passed node
16193 * @see CompileTimeErrorCode#REDIRECT_TO_NON_CONST_CONSTRUCTOR
16194 */
16195 bool checkForRedirectToNonConstConstructor(ConstructorDeclaration node) {
16196 ConstructorName redirectedConstructorNode = node.redirectedConstructor;
16197 if (redirectedConstructorNode == null) {
16198 return false;
16199 }
16200 ConstructorElement element = node.element;
16201 if (element == null) {
16202 return false;
16203 }
16204 if (!element.isConst) {
16205 return false;
16206 }
16207 ConstructorElement redirectedConstructor = element.redirectedConstructor;
16208 if (redirectedConstructor == null) {
16209 return false;
16210 }
16211 if (redirectedConstructor.isConst) {
16212 return false;
16213 }
16214 _errorReporter.reportError2(CompileTimeErrorCode.REDIRECT_TO_NON_CONST_CONST RUCTOR, redirectedConstructorNode, []);
16215 return true;
16216 }
16217
16218 /**
16219 * This checks if the passed identifier is banned because it is part of the va riable declaration
16220 * with the same name.
16221 *
16222 * @param node the identifier to evaluate
16223 * @return `true` if and only if an error code is generated on the passed node
16224 * @see CompileTimeErrorCode#REFERENCE_TO_DECLARED_VARIABLE_IN_INITIALIZER
16225 */
16226 bool checkForReferenceToDeclaredVariableInInitializer(SimpleIdentifier node) {
16227 ASTNode parent = node.parent;
16228 if (parent is PrefixedIdentifier) {
16229 PrefixedIdentifier prefixedIdentifier = parent as PrefixedIdentifier;
16230 if (identical(prefixedIdentifier.identifier, node)) {
16231 return false;
16232 }
16233 }
16234 if (parent is PropertyAccess) {
16235 PropertyAccess propertyAccess = parent as PropertyAccess;
16236 if (identical(propertyAccess.propertyName, node)) {
16237 return false;
16238 }
16239 }
16240 if (parent is MethodInvocation) {
16241 MethodInvocation methodInvocation = parent as MethodInvocation;
16242 if (methodInvocation.target != null && identical(methodInvocation.methodNa me, node)) {
16243 return false;
16244 }
16245 }
16246 if (parent is ConstructorName) {
16247 ConstructorName constructorName = parent as ConstructorName;
16248 if (identical(constructorName.name, node)) {
16249 return false;
16250 }
16251 }
16252 if (parent is Label) {
16253 Label label = parent as Label;
16254 if (identical(label.label, node)) {
16255 return false;
16256 }
16257 }
16258 String name = node.name;
16259 if (!_namesForReferenceToDeclaredVariableInInitializer.contains(name)) {
16260 return false;
16261 }
16262 _errorReporter.reportError2(CompileTimeErrorCode.REFERENCE_TO_DECLARED_VARIA BLE_IN_INITIALIZER, node, [name]);
16263 return true;
16264 }
16265
16266 /**
16267 * This checks that the rethrow is inside of a catch clause.
16268 *
16269 * @param node the rethrow expression to evaluate
16270 * @return `true` if and only if an error code is generated on the passed node
16271 * @see CompileTimeErrorCode#RETHROW_OUTSIDE_CATCH
16272 */
16273 bool checkForRethrowOutsideCatch(RethrowExpression node) {
16274 if (!_isInCatchClause) {
16275 _errorReporter.reportError2(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, no de, []);
16276 return true;
16277 }
16278 return false;
16279 }
16280
16281 /**
16282 * This checks that if the the given constructor declaration is generative, th en it does not have
16283 * an expression function body.
16284 *
16285 * @param node the constructor to evaluate
16286 * @return `true` if and only if an error code is generated on the passed node
16287 * @see CompileTimeErrorCode#RETURN_IN_GENERATIVE_CONSTRUCTOR
16288 */
16289 bool checkForReturnInGenerativeConstructor(ConstructorDeclaration node) {
16290 if (node.factoryKeyword != null) {
16291 return false;
16292 }
16293 FunctionBody body = node.body;
16294 if (body is! ExpressionFunctionBody) {
16295 return false;
16296 }
16297 _errorReporter.reportError2(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTR UCTOR, body, []);
16298 return true;
16299 }
16300
16301 /**
16302 * This checks that a type mis-match between the return type and the expressed return type by the
16303 * enclosing method or function.
16304 *
16305 * This method is called both by [checkForAllReturnStatementErrorCodes]
16306 * and [visitExpressionFunctionBody].
16307 *
16308 * @param returnExpression the returned expression to evaluate
16309 * @param expectedReturnType the expressed return type by the enclosing method or function
16310 * @return `true` if and only if an error code is generated on the passed node
16311 * @see StaticTypeWarningCode#RETURN_OF_INVALID_TYPE
16312 */
16313 bool checkForReturnOfInvalidType(Expression returnExpression, Type2 expectedRe turnType) {
16314 Type2 staticReturnType = getStaticType(returnExpression);
16315 if (expectedReturnType.isVoid) {
16316 if (staticReturnType.isVoid || staticReturnType.isDynamic || staticReturnT ype.isBottom) {
16317 return false;
16318 }
16319 _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [
16320 staticReturnType.displayName,
16321 expectedReturnType.displayName,
16322 _enclosingFunction.displayName]);
16323 return true;
16324 }
16325 bool isStaticAssignable = staticReturnType.isAssignableTo(expectedReturnType );
16326 Type2 propagatedReturnType = returnExpression.propagatedType;
16327 if (_strictMode || propagatedReturnType == null) {
16328 if (isStaticAssignable) {
16329 return false;
16330 }
16331 _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [
16332 staticReturnType.displayName,
16333 expectedReturnType.displayName,
16334 _enclosingFunction.displayName]);
16335 return true;
16336 } else {
16337 bool isPropagatedAssignable = propagatedReturnType.isAssignableTo(expected ReturnType);
16338 if (isStaticAssignable || isPropagatedAssignable) {
16339 return false;
16340 }
16341 _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [
16342 staticReturnType.displayName,
16343 expectedReturnType.displayName,
16344 _enclosingFunction.displayName]);
16345 return true;
16346 }
16347 }
16348
16349 /**
16350 * This checks that if the given "target" is the type reference then the "name " is not the
16351 * reference to a instance member.
16352 *
16353 * @param target the target of the name access to evaluate
16354 * @param name the accessed name to evaluate
16355 * @return `true` if and only if an error code is generated on the passed node
16356 * @see StaticWarningCode#STATIC_ACCESS_TO_INSTANCE_MEMBER
16357 */
16358 bool checkForStaticAccessToInstanceMember(Expression target, SimpleIdentifier name) {
16359 Element element = name.staticElement;
16360 if (element is! ExecutableElement) {
16361 return false;
16362 }
16363 ExecutableElement memberElement = element as ExecutableElement;
16364 if (memberElement.isStatic) {
16365 return false;
16366 }
16367 if (!isTypeReference(target)) {
16368 return false;
16369 }
16370 _errorReporter.reportError2(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMB ER, name, [name.name]);
16371 return true;
16372 }
16373
16374 /**
16375 * This checks that the type of the passed 'switch' expression is assignable t o the type of the
16376 * 'case' members.
16377 *
16378 * @param node the 'switch' statement to evaluate
16379 * @return `true` if and only if an error code is generated on the passed node
16380 * @see StaticWarningCode#SWITCH_EXPRESSION_NOT_ASSIGNABLE
16381 */
16382 bool checkForSwitchExpressionNotAssignable(SwitchStatement node) {
16383 Expression expression = node.expression;
16384 Type2 expressionType = getStaticType(expression);
16385 if (expressionType == null) {
16386 return false;
16387 }
16388 NodeList<SwitchMember> members = node.members;
16389 for (SwitchMember switchMember in members) {
16390 if (switchMember is! SwitchCase) {
16391 continue;
16392 }
16393 SwitchCase switchCase = switchMember as SwitchCase;
16394 Expression caseExpression = switchCase.expression;
16395 Type2 caseType = getStaticType(caseExpression);
16396 if (expressionType.isAssignableTo(caseType)) {
16397 return false;
16398 }
16399 _errorReporter.reportError2(StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGN ABLE, expression, [expressionType, caseType]);
16400 return true;
16401 }
16402 return false;
16403 }
16404
16405 /**
16406 * This verifies that the passed function type alias does not reference itself directly.
16407 *
16408 * @param node the function type alias to evaluate
16409 * @return `true` if and only if an error code is generated on the passed node
16410 * @see CompileTimeErrorCode#TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
16411 */
16412 bool checkForTypeAliasCannotReferenceItself_function(FunctionTypeAlias node) {
16413 FunctionTypeAliasElement element = node.element;
16414 if (!hasTypedefSelfReference(element)) {
16415 return false;
16416 }
16417 _errorReporter.reportError2(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE _ITSELF, node, []);
16418 return true;
16419 }
16420
16421 /**
16422 * This verifies that the given class type alias does not reference itself.
16423 *
16424 * @return `true` if and only if an error code is generated on the passed node
16425 * @see CompileTimeErrorCode#TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
16426 */
16427 bool checkForTypeAliasCannotReferenceItself_mixin(ClassTypeAlias node) {
16428 ClassElement element = node.element;
16429 if (!hasTypedefSelfReference(element)) {
16430 return false;
16431 }
16432 _errorReporter.reportError2(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE _ITSELF, node, []);
16433 return true;
16434 }
16435
16436 /**
16437 * This verifies that the type arguments in the passed type name are all withi n their bounds.
16438 *
16439 * @param node the [TypeName] to evaluate
16440 * @return `true` if and only if an error code is generated on the passed node
16441 * @see StaticTypeWarningCode#TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
16442 */
16443 bool checkForTypeArgumentNotMatchingBounds(TypeName node) {
16444 if (node.typeArguments == null) {
16445 return false;
16446 }
16447 Type2 type = node.type;
16448 if (type == null) {
16449 return false;
16450 }
16451 Element element = type.element;
16452 if (element is! ClassElement) {
16453 return false;
16454 }
16455 ClassElement classElement = element as ClassElement;
16456 List<Type2> typeParameters = classElement.type.typeArguments;
16457 List<TypeParameterElement> boundingElts = classElement.typeParameters;
16458 NodeList<TypeName> typeNameArgList = node.typeArguments.arguments;
16459 List<Type2> typeArguments = ((type as InterfaceType)).typeArguments;
16460 int loopThroughIndex = Math.min(typeNameArgList.length, boundingElts.length) ;
16461 bool foundError = false;
16462 for (int i = 0; i < loopThroughIndex; i++) {
16463 TypeName argTypeName = typeNameArgList[i];
16464 Type2 argType = argTypeName.type;
16465 Type2 boundType = boundingElts[i].bound;
16466 if (argType != null && boundType != null) {
16467 boundType = boundType.substitute2(typeArguments, typeParameters);
16468 if (!argType.isSubtypeOf(boundType)) {
16469 ErrorCode errorCode;
16470 if (isInConstConstructorInvocation(node)) {
16471 errorCode = CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
16472 } else {
16473 errorCode = StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS;
16474 }
16475 _errorReporter.reportError2(errorCode, argTypeName, [argType.displayNa me, boundType.displayName]);
16476 foundError = true;
16477 }
16478 }
16479 }
16480 return foundError;
16481 }
16482
16483 /**
16484 * This checks that if the passed type name is a type parameter being used to define a static
16485 * member.
16486 *
16487 * @param node the type name to evaluate
16488 * @return `true` if and only if an error code is generated on the passed node
16489 * @see StaticWarningCode#TYPE_PARAMETER_REFERENCED_BY_STATIC
16490 */
16491 bool checkForTypeParameterReferencedByStatic(TypeName node) {
16492 if (_isInStaticMethod || _isInStaticVariableDeclaration) {
16493 Type2 type = node.type;
16494 if (type is TypeParameterType) {
16495 _errorReporter.reportError2(StaticWarningCode.TYPE_PARAMETER_REFERENCED_ BY_STATIC, node, []);
16496 return true;
16497 }
16498 }
16499 return false;
16500 }
16501
16502 /**
16503 * This checks that if the passed type parameter is a supertype of its bound.
16504 *
16505 * @param node the type parameter to evaluate
16506 * @return `true` if and only if an error code is generated on the passed node
16507 * @see StaticTypeWarningCode#TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND
16508 */
16509 bool checkForTypeParameterSupertypeOfItsBound(TypeParameter node) {
16510 TypeParameterElement element = node.element;
16511 Type2 bound = element.bound;
16512 if (bound == null) {
16513 return false;
16514 }
16515 if (!bound.isMoreSpecificThan(element.type)) {
16516 return false;
16517 }
16518 _errorReporter.reportError2(StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_O F_ITS_BOUND, node, [element.displayName]);
16519 return true;
16520 }
16521
16522 /**
16523 * This checks that if the passed generative constructor has neither an explic it super constructor
16524 * invocation nor a redirecting constructor invocation, that the superclass ha s a default
16525 * generative constructor.
16526 *
16527 * @param node the constructor declaration to evaluate
16528 * @return `true` if and only if an error code is generated on the passed node
16529 * @see CompileTimeErrorCode#UNDEFINED_CONSTRUCTOR_IN_INITIALIZER_DEFAULT
16530 * @see CompileTimeErrorCode#NON_GENERATIVE_CONSTRUCTOR
16531 * @see StaticWarningCode#NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT
16532 */
16533 bool checkForUndefinedConstructorInInitializerImplicit(ConstructorDeclaration node) {
16534 if (node.factoryKeyword != null) {
16535 return false;
16536 }
16537 for (ConstructorInitializer constructorInitializer in node.initializers) {
16538 if (constructorInitializer is SuperConstructorInvocation || constructorIni tializer is RedirectingConstructorInvocation) {
16539 return false;
16540 }
16541 }
16542 if (_enclosingClass == null) {
16543 return false;
16544 }
16545 InterfaceType superType = _enclosingClass.supertype;
16546 if (superType == null) {
16547 return false;
16548 }
16549 ClassElement superElement = superType.element;
16550 ConstructorElement superUnnamedConstructor = superElement.unnamedConstructor ;
16551 if (superUnnamedConstructor != null) {
16552 if (superUnnamedConstructor.isFactory) {
16553 _errorReporter.reportError2(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUC TOR, node.returnType, [superUnnamedConstructor]);
16554 return true;
16555 }
16556 if (!superUnnamedConstructor.isDefaultConstructor) {
16557 int offset;
16558 int length;
16559 {
16560 Identifier returnType = node.returnType;
16561 SimpleIdentifier name = node.name;
16562 offset = returnType.offset;
16563 length = (name != null ? name.end : returnType.end) - offset;
16564 }
16565 _errorReporter.reportError3(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTR UCTOR_EXPLICIT, offset, length, [superType.displayName]);
16566 }
16567 return false;
16568 }
16569 _errorReporter.reportError2(CompileTimeErrorCode.UNDEFINED_CONSTRUCTOR_IN_IN ITIALIZER_DEFAULT, node.returnType, [superElement.name]);
16570 return true;
16571 }
16572
16573 /**
16574 * This checks that if the given name is a reference to a static member it is defined in the
16575 * enclosing class rather than in a superclass.
16576 *
16577 * @param name the name to be evaluated
16578 * @return `true` if and only if an error code is generated on the passed node
16579 * @see StaticTypeWarningCode#UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER
16580 */
16581 bool checkForUnqualifiedReferenceToNonLocalStaticMember(SimpleIdentifier name) {
16582 Element element = name.staticElement;
16583 if (element == null || element is TypeParameterElement) {
16584 return false;
16585 }
16586 Element enclosingElement = element.enclosingElement;
16587 if (enclosingElement is! ClassElement) {
16588 return false;
16589 }
16590 if ((element is MethodElement && !((element as MethodElement)).isStatic) || (element is PropertyAccessorElement && !((element as PropertyAccessorElement)).i sStatic)) {
16591 return false;
16592 }
16593 if (identical(enclosingElement, _enclosingClass)) {
16594 return false;
16595 }
16596 _errorReporter.reportError2(StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_N ON_LOCAL_STATIC_MEMBER, name, [name.name]);
16597 return true;
16598 }
16599
16600 /**
16601 * This verifies the passed operator-method declaration, has correct number of parameters.
16602 *
16603 * This method assumes that the method declaration was tested to be an operato r declaration before
16604 * being called.
16605 *
16606 * @param node the method declaration to evaluate
16607 * @return `true` if and only if an error code is generated on the passed node
16608 * @see CompileTimeErrorCode#WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR
16609 */
16610 bool checkForWrongNumberOfParametersForOperator(MethodDeclaration node) {
16611 FormalParameterList parameterList = node.parameters;
16612 if (parameterList == null) {
16613 return false;
16614 }
16615 int numParameters = parameterList.parameters.length;
16616 SimpleIdentifier nameNode = node.name;
16617 if (nameNode == null) {
16618 return false;
16619 }
16620 String name = nameNode.name;
16621 int expected = -1;
16622 if ("[]=" == name) {
16623 expected = 2;
16624 } else if ("<" == name || ">" == name || "<=" == name || ">=" == name || "== " == name || "+" == name || "/" == name || "~/" == name || "*" == name || "%" == name || "|" == name || "^" == name || "&" == name || "<<" == name || ">>" == na me || "[]" == name) {
16625 expected = 1;
16626 } else if ("~" == name) {
16627 expected = 0;
16628 }
16629 if (expected != -1 && numParameters != expected) {
16630 _errorReporter.reportError2(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETER S_FOR_OPERATOR, nameNode, [name, expected, numParameters]);
16631 return true;
16632 }
16633 if ("-" == name && numParameters > 1) {
16634 _errorReporter.reportError2(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETER S_FOR_OPERATOR_MINUS, nameNode, [numParameters]);
16635 return true;
16636 }
16637 return false;
16638 }
16639
16640 /**
16641 * This verifies if the passed setter parameter list have only one required pa rameter.
16642 *
16643 * This method assumes that the method declaration was tested to be a setter b efore being called.
16644 *
16645 * @param setterName the name of the setter to report problems on
16646 * @param parameterList the parameter list to evaluate
16647 * @return `true` if and only if an error code is generated on the passed node
16648 * @see CompileTimeErrorCode#WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER
16649 */
16650 bool checkForWrongNumberOfParametersForSetter(SimpleIdentifier setterName, For malParameterList parameterList) {
16651 if (setterName == null) {
16652 return false;
16653 }
16654 if (parameterList == null) {
16655 return false;
16656 }
16657 NodeList<FormalParameter> parameters = parameterList.parameters;
16658 if (parameters.length != 1 || parameters[0].kind != ParameterKind.REQUIRED) {
16659 _errorReporter.reportError2(CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETER S_FOR_SETTER, setterName, []);
16660 return true;
16661 }
16662 return false;
16663 }
16664
16665 /**
16666 * This verifies that if the given class declaration implements the class Func tion that it has a
16667 * concrete implementation of the call method.
16668 *
16669 * @return `true` if and only if an error code is generated on the passed node
16670 * @see StaticWarningCode#FUNCTION_WITHOUT_CALL
16671 */
16672 bool checkImplementsFunctionWithoutCall(ClassDeclaration node) {
16673 if (node.abstractKeyword != null) {
16674 return false;
16675 }
16676 ClassElement classElement = node.element;
16677 if (classElement == null) {
16678 return false;
16679 }
16680 if (!classElement.type.isSubtypeOf(_typeProvider.functionType)) {
16681 return false;
16682 }
16683 ExecutableElement callMethod = _inheritanceManager.lookupMember(classElement , "call");
16684 if (callMethod == null || callMethod is! MethodElement || ((callMethod as Me thodElement)).isAbstract) {
16685 _errorReporter.reportError2(StaticWarningCode.FUNCTION_WITHOUT_CALL, node. name, []);
16686 return true;
16687 }
16688 return false;
16689 }
16690
16691 /**
16692 * This verifies that the given class declaration does not have the same class in the 'extends'
16693 * and 'implements' clauses.
16694 *
16695 * @return `true` if and only if an error code is generated on the passed node
16696 * @see CompileTimeErrorCode#IMPLEMENTS_SUPER_CLASS
16697 */
16698 bool checkImplementsSuperClass(ClassDeclaration node) {
16699 InterfaceType superType = _enclosingClass.supertype;
16700 if (superType == null) {
16701 return false;
16702 }
16703 ImplementsClause implementsClause = node.implementsClause;
16704 if (implementsClause == null) {
16705 return false;
16706 }
16707 bool hasProblem = false;
16708 for (TypeName interfaceNode in implementsClause.interfaces) {
16709 if (interfaceNode.type == superType) {
16710 hasProblem = true;
16711 _errorReporter.reportError2(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, interfaceNode, [superType.displayName]);
16712 }
16713 }
16714 return hasProblem;
16715 }
16716
16717 /**
16718 * Returns the Type (return type) for a given getter.
16719 *
16720 * @param propertyAccessorElement
16721 * @return The type of the given getter.
16722 */
16723 Type2 getGetterType(PropertyAccessorElement propertyAccessorElement) {
16724 FunctionType functionType = propertyAccessorElement.type;
16725 if (functionType != null) {
16726 return functionType.returnType;
16727 } else {
16728 return null;
16729 }
16730 }
16731
16732 /**
16733 * Returns the Type (first and only parameter) for a given setter.
16734 *
16735 * @param propertyAccessorElement
16736 * @return The type of the given setter.
16737 */
16738 Type2 getSetterType(PropertyAccessorElement propertyAccessorElement) {
16739 List<ParameterElement> setterParameters = propertyAccessorElement.parameters ;
16740 if (setterParameters.length == 0) {
16741 return null;
16742 }
16743 return setterParameters[0].type;
16744 }
16745
16746 /**
16747 * Return the static type of the given expression that is to be used for type analysis.
16748 *
16749 * @param expression the expression whose type is to be returned
16750 * @return the static type of the given expression
16751 */
16752 Type2 getStaticType(Expression expression) {
16753 Type2 type = expression.staticType;
16754 if (type == null) {
16755 return _dynamicType;
16756 }
16757 return type;
16758 }
16759
16760 /**
16761 * Return the variable element represented by the given expression, or `null` if there is no
16762 * such element.
16763 *
16764 * @param expression the expression whose element is to be returned
16765 * @return the variable element represented by the expression
16766 */
16767 VariableElement getVariableElement(Expression expression) {
16768 if (expression is Identifier) {
16769 Element element = ((expression as Identifier)).staticElement;
16770 if (element is VariableElement) {
16771 return element as VariableElement;
16772 }
16773 }
16774 return null;
16775 }
16776
16777 /**
16778 * @return `true` if the given constructor redirects to itself, directly or in directly
16779 */
16780 bool hasRedirectingFactoryConstructorCycle(ConstructorElement element) {
16781 Set<ConstructorElement> constructors = new Set<ConstructorElement>();
16782 ConstructorElement current = element;
16783 while (current != null) {
16784 if (constructors.contains(current)) {
16785 return identical(current, element);
16786 }
16787 javaSetAdd(constructors, current);
16788 current = current.redirectedConstructor;
16789 if (current is ConstructorMember) {
16790 current = ((current as ConstructorMember)).baseElement;
16791 }
16792 }
16793 return false;
16794 }
16795
16796 /**
16797 * @return <code>true</code> if given [Element] has direct or indirect referen ce to itself
16798 * from anywhere except [ClassElement] or type parameter bounds.
16799 */
16800 bool hasTypedefSelfReference(Element target) {
16801 Set<Element> checked = new Set<Element>();
16802 List<Element> toCheck = new List<Element>();
16803 toCheck.add(target);
16804 bool firstIteration = true;
16805 while (true) {
16806 Element current;
16807 while (true) {
16808 if (toCheck.isEmpty) {
16809 return false;
16810 }
16811 current = toCheck.removeAt(toCheck.length - 1);
16812 if (target == current) {
16813 if (firstIteration) {
16814 firstIteration = false;
16815 break;
16816 } else {
16817 return true;
16818 }
16819 }
16820 if (current != null && !checked.contains(current)) {
16821 break;
16822 }
16823 }
16824 current.accept(new GeneralizingElementVisitor_14(target, toCheck));
16825 javaSetAdd(checked, current);
16826 }
16827 }
16828
16829 /**
16830 * @return `true` if given [Type] implements operator <i>==</i>, and it is not
16831 * <i>int</i> or <i>String</i>.
16832 */
16833 bool implementsEqualsWhenNotAllowed(Type2 type) {
16834 if (type == null || type == _typeProvider.intType || type == _typeProvider.s tringType) {
16835 return false;
16836 }
16837 Element element = type.element;
16838 if (element is! ClassElement) {
16839 return false;
16840 }
16841 ClassElement classElement = element as ClassElement;
16842 MethodElement method = classElement.lookUpMethod("==", _currentLibrary);
16843 if (method == null || method.enclosingElement.type.isObject) {
16844 return false;
16845 }
16846 return true;
16847 }
16848 bool isFunctionType(Type2 type) {
16849 if (type.isDynamic || type.isBottom) {
16850 return true;
16851 } else if (type is FunctionType || type.isDartCoreFunction) {
16852 return true;
16853 } else if (type is InterfaceType) {
16854 MethodElement callMethod = ((type as InterfaceType)).lookUpMethod(ElementR esolver.CALL_METHOD_NAME, _currentLibrary);
16855 return callMethod != null;
16856 }
16857 return false;
16858 }
16859
16860 /**
16861 * @return `true` if the given [ASTNode] is the part of constant constructor
16862 * invocation.
16863 */
16864 bool isInConstConstructorInvocation(ASTNode node) {
16865 InstanceCreationExpression creation = node.getAncestor(InstanceCreationExpre ssion);
16866 if (creation == null) {
16867 return false;
16868 }
16869 return creation.isConst;
16870 }
16871
16872 /**
16873 * @param node the 'this' expression to analyze
16874 * @return `true` if the given 'this' expression is in the valid context
16875 */
16876 bool isThisInValidContext(ThisExpression node) {
16877 for (ASTNode n = node; n != null; n = n.parent) {
16878 if (n is CompilationUnit) {
16879 return false;
16880 }
16881 if (n is ConstructorDeclaration) {
16882 ConstructorDeclaration constructor = n as ConstructorDeclaration;
16883 return constructor.factoryKeyword == null;
16884 }
16885 if (n is ConstructorInitializer) {
16886 return false;
16887 }
16888 if (n is MethodDeclaration) {
16889 MethodDeclaration method = n as MethodDeclaration;
16890 return !method.isStatic;
16891 }
16892 }
16893 return false;
16894 }
16895
16896 /**
16897 * Return `true` if the given identifier is in a location where it is allowed to resolve to
16898 * a static member of a supertype.
16899 *
16900 * @param node the node being tested
16901 * @return `true` if the given identifier is in a location where it is allowed to resolve to
16902 * a static member of a supertype
16903 */
16904 bool isUnqualifiedReferenceToNonLocalStaticMemberAllowed(SimpleIdentifier node ) {
16905 if (node.inDeclarationContext()) {
16906 return true;
16907 }
16908 ASTNode parent = node.parent;
16909 if (parent is ConstructorName || parent is MethodInvocation || parent is Pro pertyAccess || parent is SuperConstructorInvocation) {
16910 return true;
16911 }
16912 if (parent is PrefixedIdentifier && identical(((parent as PrefixedIdentifier )).identifier, node)) {
16913 return true;
16914 }
16915 if (parent is Annotation && identical(((parent as Annotation)).constructorNa me, node)) {
16916 return true;
16917 }
16918 return false;
16919 }
16920
16921 /**
16922 * Return `true` iff the passed [ClassElement] has a concrete implementation o f the
16923 * passed accessor name in the superclass chain.
16924 */
16925 bool memberHasConcreteAccessorImplementationInSuperclassChain(ClassElement cla ssElement, String accessorName, List<ClassElement> superclassChain) {
16926 if (superclassChain.contains(classElement)) {
16927 return false;
16928 } else {
16929 superclassChain.add(classElement);
16930 }
16931 for (PropertyAccessorElement accessor in classElement.accessors) {
16932 if (accessor.name == accessorName) {
16933 if (!accessor.isAbstract) {
16934 return true;
16935 }
16936 }
16937 }
16938 for (InterfaceType mixinType in classElement.mixins) {
16939 if (mixinType != null) {
16940 ClassElement mixinElement = mixinType.element;
16941 if (mixinElement != null) {
16942 for (PropertyAccessorElement accessor in mixinElement.accessors) {
16943 if (accessor.name == accessorName) {
16944 if (!accessor.isAbstract) {
16945 return true;
16946 }
16947 }
16948 }
16949 }
16950 }
16951 }
16952 InterfaceType superType = classElement.supertype;
16953 if (superType != null) {
16954 ClassElement superClassElt = superType.element;
16955 if (superClassElt != null) {
16956 return memberHasConcreteAccessorImplementationInSuperclassChain(superCla ssElt, accessorName, superclassChain);
16957 }
16958 }
16959 return false;
16960 }
16961
16962 /**
16963 * Return `true` iff the passed [ClassElement] has a concrete implementation o f the
16964 * passed method name in the superclass chain.
16965 */
16966 bool memberHasConcreteMethodImplementationInSuperclassChain(ClassElement class Element, String methodName, List<ClassElement> superclassChain) {
16967 if (superclassChain.contains(classElement)) {
16968 return false;
16969 } else {
16970 superclassChain.add(classElement);
16971 }
16972 for (MethodElement method in classElement.methods) {
16973 if (method.name == methodName) {
16974 if (!method.isAbstract) {
16975 return true;
16976 }
16977 }
16978 }
16979 for (InterfaceType mixinType in classElement.mixins) {
16980 if (mixinType != null) {
16981 ClassElement mixinElement = mixinType.element;
16982 if (mixinElement != null) {
16983 for (MethodElement method in mixinElement.methods) {
16984 if (method.name == methodName) {
16985 if (!method.isAbstract) {
16986 return true;
16987 }
16988 }
16989 }
16990 }
16991 }
16992 }
16993 InterfaceType superType = classElement.supertype;
16994 if (superType != null) {
16995 ClassElement superClassElt = superType.element;
16996 if (superClassElt != null) {
16997 return memberHasConcreteMethodImplementationInSuperclassChain(superClass Elt, methodName, superclassChain);
16998 }
16999 }
17000 return false;
17001 }
17002 }
17003 /**
17004 * This enum holds one of four states of a field initialization state through a constructor
17005 * signature, not initialized, initialized in the field declaration, initialized in the field
17006 * formal, and finally, initialized in the initializers list.
17007 */
17008 class INIT_STATE extends Enum<INIT_STATE> {
17009 static final INIT_STATE NOT_INIT = new INIT_STATE('NOT_INIT', 0);
17010 static final INIT_STATE INIT_IN_DECLARATION = new INIT_STATE('INIT_IN_DECLARAT ION', 1);
17011 static final INIT_STATE INIT_IN_FIELD_FORMAL = new INIT_STATE('INIT_IN_FIELD_F ORMAL', 2);
17012 static final INIT_STATE INIT_IN_INITIALIZERS = new INIT_STATE('INIT_IN_INITIAL IZERS', 3);
17013 static final List<INIT_STATE> values = [
17014 NOT_INIT,
17015 INIT_IN_DECLARATION,
17016 INIT_IN_FIELD_FORMAL,
17017 INIT_IN_INITIALIZERS];
17018 INIT_STATE(String name, int ordinal) : super(name, ordinal);
17019 }
17020 class GeneralizingElementVisitor_14 extends GeneralizingElementVisitor<Object> {
17021 Element target;
17022 List<Element> toCheck;
17023 GeneralizingElementVisitor_14(this.target, this.toCheck) : super();
17024 bool _inClass = false;
17025 Object visitClassElement(ClassElement element) {
17026 addTypeToCheck(element.supertype);
17027 for (InterfaceType mixin in element.mixins) {
17028 addTypeToCheck(mixin);
17029 }
17030 _inClass = !element.isTypedef;
17031 try {
17032 return super.visitClassElement(element);
17033 } finally {
17034 _inClass = false;
17035 }
17036 }
17037 Object visitExecutableElement(ExecutableElement element) {
17038 if (element.isSynthetic) {
17039 return null;
17040 }
17041 addTypeToCheck(element.returnType);
17042 return super.visitExecutableElement(element);
17043 }
17044 Object visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
17045 addTypeToCheck(element.returnType);
17046 return super.visitFunctionTypeAliasElement(element);
17047 }
17048 Object visitParameterElement(ParameterElement element) {
17049 addTypeToCheck(element.type);
17050 return super.visitParameterElement(element);
17051 }
17052 Object visitTypeParameterElement(TypeParameterElement element) {
17053 addTypeToCheck(element.bound);
17054 return super.visitTypeParameterElement(element);
17055 }
17056 Object visitVariableElement(VariableElement element) {
17057 addTypeToCheck(element.type);
17058 return super.visitVariableElement(element);
17059 }
17060 void addTypeToCheck(Type2 type) {
17061 if (type == null) {
17062 return;
17063 }
17064 Element element = type.element;
17065 if (_inClass && target == element) {
17066 return;
17067 }
17068 toCheck.add(element);
17069 if (type is InterfaceType) {
17070 InterfaceType interfaceType = type as InterfaceType;
17071 for (Type2 typeArgument in interfaceType.typeArguments) {
17072 addTypeToCheck(typeArgument);
17073 }
17074 }
17075 }
17076 }
17077 /**
17078 * The enumeration `ResolverErrorCode` defines the error codes used for errors d etected by the
17079 * resolver. The convention for this class is for the name of the error code to indicate the problem
17080 * that caused the error to be generated and for the error message to explain wh at is wrong and,
17081 * when appropriate, how the problem can be corrected.
17082 *
17083 * @coverage dart.engine.resolver
17084 */
17085 class ResolverErrorCode extends Enum<ResolverErrorCode> implements ErrorCode {
17086 static final ResolverErrorCode BREAK_LABEL_ON_SWITCH_MEMBER = new ResolverErro rCode.con1('BREAK_LABEL_ON_SWITCH_MEMBER', 0, ErrorType.COMPILE_TIME_ERROR, "Bre ak label resolves to case or default statement");
17087 static final ResolverErrorCode CONTINUE_LABEL_ON_SWITCH = new ResolverErrorCod e.con1('CONTINUE_LABEL_ON_SWITCH', 1, ErrorType.COMPILE_TIME_ERROR, "A continue label resolves to switch, must be loop or switch member");
17088 static final ResolverErrorCode MISSING_LIBRARY_DIRECTIVE_WITH_PART = new Resol verErrorCode.con1('MISSING_LIBRARY_DIRECTIVE_WITH_PART', 2, ErrorType.COMPILE_TI ME_ERROR, "Libraries that have parts must have a library directive");
17089 static final List<ResolverErrorCode> values = [
17090 BREAK_LABEL_ON_SWITCH_MEMBER,
17091 CONTINUE_LABEL_ON_SWITCH,
17092 MISSING_LIBRARY_DIRECTIVE_WITH_PART];
17093
17094 /**
17095 * The type of this error.
17096 */
17097 ErrorType _type;
17098
17099 /**
17100 * The template used to create the message to be displayed for this error.
17101 */
17102 String _message;
17103
17104 /**
17105 * The template used to create the correction to be displayed for this error, or `null` if
17106 * there is no correction information for this error.
17107 */
17108 String correction9;
17109
17110 /**
17111 * Initialize a newly created error code to have the given type and message.
17112 *
17113 * @param type the type of this error
17114 * @param message the message template used to create the message to be displa yed for the error
17115 */
17116 ResolverErrorCode.con1(String name, int ordinal, ErrorType type, String messag e) : super(name, ordinal) {
17117 this._type = type;
17118 this._message = message;
17119 }
17120
17121 /**
17122 * Initialize a newly created error code to have the given type, message and c orrection.
17123 *
17124 * @param type the type of this error
17125 * @param message the template used to create the message to be displayed for the error
17126 * @param correction the template used to create the correction to be displaye d for the error
17127 */
17128 ResolverErrorCode.con2(String name, int ordinal, ErrorType type, String messag e, String correction) : super(name, ordinal) {
17129 this._type = type;
17130 this._message = message;
17131 this.correction9 = correction;
17132 }
17133 String get correction => correction9;
17134 ErrorSeverity get errorSeverity => _type.severity;
17135 String get message => _message;
17136 ErrorType get type => _type;
17137 }
OLDNEW
« no previous file with comments | « pkg/analyzer_experimental/lib/src/generated/parser.dart ('k') | pkg/analyzer_experimental/lib/src/generated/scanner.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698