OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library analyzer.test.generated.resolver_test; | 5 library analyzer.test.generated.resolver_test; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
11 import 'package:analyzer/dart/ast/visitor.dart'; | 11 import 'package:analyzer/dart/ast/visitor.dart'; |
12 import 'package:analyzer/dart/element/element.dart'; | 12 import 'package:analyzer/dart/element/element.dart'; |
13 import 'package:analyzer/dart/element/type.dart'; | 13 import 'package:analyzer/dart/element/type.dart'; |
14 import 'package:analyzer/src/context/context.dart'; | 14 import 'package:analyzer/src/context/context.dart'; |
15 import 'package:analyzer/src/dart/element/element.dart'; | 15 import 'package:analyzer/src/dart/element/element.dart'; |
16 import 'package:analyzer/src/dart/element/member.dart'; | |
17 import 'package:analyzer/src/dart/element/type.dart'; | 16 import 'package:analyzer/src/dart/element/type.dart'; |
18 import 'package:analyzer/src/generated/element_resolver.dart'; | |
19 import 'package:analyzer/src/generated/engine.dart'; | 17 import 'package:analyzer/src/generated/engine.dart'; |
20 import 'package:analyzer/src/generated/error.dart'; | 18 import 'package:analyzer/src/generated/error.dart'; |
21 import 'package:analyzer/src/generated/java_core.dart'; | 19 import 'package:analyzer/src/generated/java_core.dart'; |
22 import 'package:analyzer/src/generated/java_engine.dart'; | |
23 import 'package:analyzer/src/generated/java_engine_io.dart'; | 20 import 'package:analyzer/src/generated/java_engine_io.dart'; |
24 import 'package:analyzer/src/generated/java_io.dart'; | |
25 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode; | 21 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode; |
26 import 'package:analyzer/src/generated/resolver.dart'; | 22 import 'package:analyzer/src/generated/resolver.dart'; |
27 import 'package:analyzer/src/generated/sdk.dart'; | |
28 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk; | |
29 import 'package:analyzer/src/generated/source_io.dart'; | 23 import 'package:analyzer/src/generated/source_io.dart'; |
30 import 'package:analyzer/src/generated/static_type_analyzer.dart'; | |
31 import 'package:analyzer/src/generated/testing/ast_factory.dart'; | 24 import 'package:analyzer/src/generated/testing/ast_factory.dart'; |
32 import 'package:analyzer/src/generated/testing/element_factory.dart'; | 25 import 'package:analyzer/src/generated/testing/element_factory.dart'; |
33 import 'package:analyzer/src/generated/testing/test_type_provider.dart'; | 26 import 'package:analyzer/src/generated/testing/test_type_provider.dart'; |
34 import 'package:analyzer/src/generated/testing/token_factory.dart'; | |
35 import 'package:analyzer/src/generated/utilities_dart.dart'; | 27 import 'package:analyzer/src/generated/utilities_dart.dart'; |
36 import 'package:analyzer/src/string_source.dart'; | |
37 import 'package:unittest/unittest.dart'; | 28 import 'package:unittest/unittest.dart'; |
38 | 29 |
39 import '../reflective_tests.dart'; | 30 import '../reflective_tests.dart'; |
40 import '../utils.dart'; | 31 import '../utils.dart'; |
| 32 import 'analysis_context_factory.dart'; |
| 33 import 'resolver_test_case.dart'; |
41 import 'test_support.dart'; | 34 import 'test_support.dart'; |
42 | 35 |
43 main() { | 36 main() { |
44 initializeTestEnvironment(); | 37 initializeTestEnvironment(); |
45 runReflectiveTests(AnalysisDeltaTest); | 38 runReflectiveTests(AnalysisDeltaTest); |
46 runReflectiveTests(ChangeSetTest); | 39 runReflectiveTests(ChangeSetTest); |
47 runReflectiveTests(CheckedModeCompileTimeErrorCodeTest); | |
48 runReflectiveTests(DisableAsyncTestCase); | 40 runReflectiveTests(DisableAsyncTestCase); |
49 runReflectiveTests(ElementResolverTest); | |
50 runReflectiveTests(EnclosedScopeTest); | 41 runReflectiveTests(EnclosedScopeTest); |
51 runReflectiveTests(ErrorResolverTest); | 42 runReflectiveTests(ErrorResolverTest); |
52 runReflectiveTests(HintCodeTest); | |
53 runReflectiveTests(InheritanceManagerTest); | |
54 runReflectiveTests(LibraryImportScopeTest); | 43 runReflectiveTests(LibraryImportScopeTest); |
55 runReflectiveTests(LibraryScopeTest); | 44 runReflectiveTests(LibraryScopeTest); |
56 runReflectiveTests(MemberMapTest); | 45 runReflectiveTests(MemberMapTest); |
57 runReflectiveTests(NonHintCodeTest); | |
58 runReflectiveTests(ScopeTest); | 46 runReflectiveTests(ScopeTest); |
59 runReflectiveTests(SimpleResolverTest); | |
60 runReflectiveTests(StaticTypeAnalyzerTest); | |
61 runReflectiveTests(StaticTypeAnalyzer2Test); | |
62 runReflectiveTests(StrictModeTest); | 47 runReflectiveTests(StrictModeTest); |
63 runReflectiveTests(StrongModeDownwardsInferenceTest); | |
64 runReflectiveTests(StrongModeStaticTypeAnalyzer2Test); | |
65 runReflectiveTests(StrongModeTypePropagationTest); | |
66 runReflectiveTests(SubtypeManagerTest); | 48 runReflectiveTests(SubtypeManagerTest); |
67 runReflectiveTests(TypeOverrideManagerTest); | 49 runReflectiveTests(TypeOverrideManagerTest); |
68 runReflectiveTests(TypePropagationTest); | 50 runReflectiveTests(TypePropagationTest); |
69 runReflectiveTests(TypeProviderImplTest); | 51 runReflectiveTests(TypeProviderImplTest); |
70 runReflectiveTests(TypeResolverVisitorTest); | 52 runReflectiveTests(TypeResolverVisitorTest); |
71 } | 53 } |
72 | 54 |
73 /** | |
74 * The class `AnalysisContextFactory` defines utility methods used to create ana
lysis contexts | |
75 * for testing purposes. | |
76 */ | |
77 class AnalysisContextFactory { | |
78 static String _DART_MATH = "dart:math"; | |
79 | |
80 static String _DART_INTERCEPTORS = "dart:_interceptors"; | |
81 | |
82 static String _DART_JS_HELPER = "dart:_js_helper"; | |
83 | |
84 /** | |
85 * Create an analysis context that has a fake core library already resolved. | |
86 * Return the context that was created. | |
87 */ | |
88 static InternalAnalysisContext contextWithCore() { | |
89 AnalysisContextForTests context = new AnalysisContextForTests(); | |
90 return initContextWithCore(context); | |
91 } | |
92 | |
93 /** | |
94 * Create an analysis context that uses the given [options] and has a fake | |
95 * core library already resolved. Return the context that was created. | |
96 */ | |
97 static InternalAnalysisContext contextWithCoreAndOptions( | |
98 AnalysisOptions options) { | |
99 AnalysisContextForTests context = new AnalysisContextForTests(); | |
100 context._internalSetAnalysisOptions(options); | |
101 return initContextWithCore(context); | |
102 } | |
103 | |
104 static InternalAnalysisContext contextWithCoreAndPackages( | |
105 Map<String, String> packages) { | |
106 AnalysisContextForTests context = new AnalysisContextForTests(); | |
107 return initContextWithCore(context, new TestPackageUriResolver(packages)); | |
108 } | |
109 | |
110 /** | |
111 * Initialize the given analysis context with a fake core library already reso
lved. | |
112 * | |
113 * @param context the context to be initialized (not `null`) | |
114 * @return the analysis context that was created | |
115 */ | |
116 static InternalAnalysisContext initContextWithCore( | |
117 InternalAnalysisContext context, | |
118 [UriResolver contributedResolver]) { | |
119 DirectoryBasedDartSdk sdk = new _AnalysisContextFactory_initContextWithCore( | |
120 new JavaFile("/fake/sdk"), | |
121 enableAsync: context.analysisOptions.enableAsync); | |
122 List<UriResolver> resolvers = <UriResolver>[ | |
123 new DartUriResolver(sdk), | |
124 new FileUriResolver() | |
125 ]; | |
126 if (contributedResolver != null) { | |
127 resolvers.add(contributedResolver); | |
128 } | |
129 SourceFactory sourceFactory = new SourceFactory(resolvers); | |
130 context.sourceFactory = sourceFactory; | |
131 AnalysisContext coreContext = sdk.context; | |
132 (coreContext.analysisOptions as AnalysisOptionsImpl).strongMode = | |
133 context.analysisOptions.strongMode; | |
134 // | |
135 // dart:core | |
136 // | |
137 TestTypeProvider provider = new TestTypeProvider(); | |
138 CompilationUnitElementImpl coreUnit = | |
139 new CompilationUnitElementImpl("core.dart"); | |
140 Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE); | |
141 coreContext.setContents(coreSource, ""); | |
142 coreUnit.librarySource = coreUnit.source = coreSource; | |
143 ClassElementImpl proxyClassElement = ElementFactory.classElement2("_Proxy"); | |
144 proxyClassElement.constructors = <ConstructorElement>[ | |
145 ElementFactory.constructorElement(proxyClassElement, '', true) | |
146 ..isCycleFree = true | |
147 ..constantInitializers = <ConstructorInitializer>[] | |
148 ]; | |
149 ClassElement objectClassElement = provider.objectType.element; | |
150 coreUnit.types = <ClassElement>[ | |
151 provider.boolType.element, | |
152 provider.deprecatedType.element, | |
153 provider.doubleType.element, | |
154 provider.functionType.element, | |
155 provider.intType.element, | |
156 provider.iterableType.element, | |
157 provider.iteratorType.element, | |
158 provider.listType.element, | |
159 provider.mapType.element, | |
160 provider.nullType.element, | |
161 provider.numType.element, | |
162 objectClassElement, | |
163 proxyClassElement, | |
164 provider.stackTraceType.element, | |
165 provider.stringType.element, | |
166 provider.symbolType.element, | |
167 provider.typeType.element | |
168 ]; | |
169 coreUnit.functions = <FunctionElement>[ | |
170 ElementFactory.functionElement3("identical", provider.boolType.element, | |
171 <ClassElement>[objectClassElement, objectClassElement], null), | |
172 ElementFactory.functionElement3("print", VoidTypeImpl.instance.element, | |
173 <ClassElement>[objectClassElement], null) | |
174 ]; | |
175 TopLevelVariableElement proxyTopLevelVariableElt = ElementFactory | |
176 .topLevelVariableElement3("proxy", true, false, proxyClassElement.type); | |
177 ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt = | |
178 ElementFactory.topLevelVariableElement3( | |
179 "deprecated", true, false, provider.deprecatedType); | |
180 { | |
181 ClassElement deprecatedElement = provider.deprecatedType.element; | |
182 InstanceCreationExpression initializer = AstFactory | |
183 .instanceCreationExpression2( | |
184 Keyword.CONST, | |
185 AstFactory.typeName(deprecatedElement), | |
186 [AstFactory.string2('next release')]); | |
187 ConstructorElement constructor = deprecatedElement.constructors.single; | |
188 initializer.staticElement = constructor; | |
189 initializer.constructorName.staticElement = constructor; | |
190 deprecatedTopLevelVariableElt.constantInitializer = initializer; | |
191 } | |
192 coreUnit.accessors = <PropertyAccessorElement>[ | |
193 proxyTopLevelVariableElt.getter, | |
194 deprecatedTopLevelVariableElt.getter | |
195 ]; | |
196 coreUnit.topLevelVariables = <TopLevelVariableElement>[ | |
197 proxyTopLevelVariableElt, | |
198 deprecatedTopLevelVariableElt | |
199 ]; | |
200 LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode( | |
201 coreContext, AstFactory.libraryIdentifier2(["dart", "core"])); | |
202 coreLibrary.definingCompilationUnit = coreUnit; | |
203 // | |
204 // dart:async | |
205 // | |
206 Source asyncSource; | |
207 LibraryElementImpl asyncLibrary; | |
208 if (context.analysisOptions.enableAsync) { | |
209 asyncLibrary = new LibraryElementImpl.forNode( | |
210 coreContext, AstFactory.libraryIdentifier2(["dart", "async"])); | |
211 CompilationUnitElementImpl asyncUnit = | |
212 new CompilationUnitElementImpl("async.dart"); | |
213 asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC); | |
214 coreContext.setContents(asyncSource, ""); | |
215 asyncUnit.librarySource = asyncUnit.source = asyncSource; | |
216 asyncLibrary.definingCompilationUnit = asyncUnit; | |
217 // Future | |
218 ClassElementImpl futureElement = | |
219 ElementFactory.classElement2("Future", ["T"]); | |
220 futureElement.enclosingElement = asyncUnit; | |
221 // factory Future.value([value]) | |
222 ConstructorElementImpl futureConstructor = | |
223 ElementFactory.constructorElement2(futureElement, "value"); | |
224 futureConstructor.parameters = <ParameterElement>[ | |
225 ElementFactory.positionalParameter2("value", provider.dynamicType) | |
226 ]; | |
227 futureConstructor.factory = true; | |
228 futureElement.constructors = <ConstructorElement>[futureConstructor]; | |
229 // Future then(onValue(T value), { Function onError }); | |
230 TypeDefiningElement futureThenR = DynamicElementImpl.instance; | |
231 if (context.analysisOptions.strongMode) { | |
232 futureThenR = ElementFactory.typeParameterWithType('R'); | |
233 } | |
234 FunctionElementImpl thenOnValue = ElementFactory.functionElement3( | |
235 'onValue', futureThenR, [futureElement.typeParameters[0]], null); | |
236 thenOnValue.synthetic = true; | |
237 | |
238 DartType futureRType = futureElement.type.instantiate([futureThenR.type]); | |
239 MethodElementImpl thenMethod = ElementFactory | |
240 .methodElementWithParameters(futureElement, "then", futureRType, [ | |
241 ElementFactory.requiredParameter2("onValue", thenOnValue.type), | |
242 ElementFactory.namedParameter2("onError", provider.functionType) | |
243 ]); | |
244 if (!futureThenR.type.isDynamic) { | |
245 thenMethod.typeParameters = [futureThenR]; | |
246 } | |
247 thenOnValue.enclosingElement = thenMethod; | |
248 thenOnValue.type = new FunctionTypeImpl(thenOnValue); | |
249 (thenMethod.parameters[0] as ParameterElementImpl).type = | |
250 thenOnValue.type; | |
251 thenMethod.type = new FunctionTypeImpl(thenMethod); | |
252 | |
253 futureElement.methods = <MethodElement>[thenMethod]; | |
254 // Completer | |
255 ClassElementImpl completerElement = | |
256 ElementFactory.classElement2("Completer", ["T"]); | |
257 ConstructorElementImpl completerConstructor = | |
258 ElementFactory.constructorElement2(completerElement, null); | |
259 completerElement.constructors = <ConstructorElement>[ | |
260 completerConstructor | |
261 ]; | |
262 // StreamSubscription | |
263 ClassElementImpl streamSubscriptionElement = | |
264 ElementFactory.classElement2("StreamSubscription", ["T"]); | |
265 // Stream | |
266 ClassElementImpl streamElement = | |
267 ElementFactory.classElement2("Stream", ["T"]); | |
268 streamElement.constructors = <ConstructorElement>[ | |
269 ElementFactory.constructorElement2(streamElement, null) | |
270 ]; | |
271 DartType returnType = streamSubscriptionElement.type | |
272 .instantiate(streamElement.type.typeArguments); | |
273 FunctionElementImpl listenOnData = ElementFactory.functionElement3( | |
274 'onData', | |
275 VoidTypeImpl.instance.element, | |
276 <TypeDefiningElement>[streamElement.typeParameters[0]], | |
277 null); | |
278 listenOnData.synthetic = true; | |
279 List<DartType> parameterTypes = <DartType>[listenOnData.type,]; | |
280 // TODO(brianwilkerson) This is missing the optional parameters. | |
281 MethodElementImpl listenMethod = | |
282 ElementFactory.methodElement('listen', returnType, parameterTypes); | |
283 streamElement.methods = <MethodElement>[listenMethod]; | |
284 listenMethod.type = new FunctionTypeImpl(listenMethod); | |
285 | |
286 FunctionElementImpl listenParamFunction = parameterTypes[0].element; | |
287 listenParamFunction.enclosingElement = listenMethod; | |
288 listenParamFunction.type = new FunctionTypeImpl(listenParamFunction); | |
289 ParameterElementImpl listenParam = listenMethod.parameters[0]; | |
290 listenParam.type = listenParamFunction.type; | |
291 | |
292 asyncUnit.types = <ClassElement>[ | |
293 completerElement, | |
294 futureElement, | |
295 streamElement, | |
296 streamSubscriptionElement | |
297 ]; | |
298 } | |
299 // | |
300 // dart:html | |
301 // | |
302 CompilationUnitElementImpl htmlUnit = | |
303 new CompilationUnitElementImpl("html_dartium.dart"); | |
304 Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML); | |
305 coreContext.setContents(htmlSource, ""); | |
306 htmlUnit.librarySource = htmlUnit.source = htmlSource; | |
307 ClassElementImpl elementElement = ElementFactory.classElement2("Element"); | |
308 InterfaceType elementType = elementElement.type; | |
309 ClassElementImpl canvasElement = | |
310 ElementFactory.classElement("CanvasElement", elementType); | |
311 ClassElementImpl contextElement = | |
312 ElementFactory.classElement2("CanvasRenderingContext"); | |
313 InterfaceType contextElementType = contextElement.type; | |
314 ClassElementImpl context2dElement = ElementFactory.classElement( | |
315 "CanvasRenderingContext2D", contextElementType); | |
316 canvasElement.methods = <MethodElement>[ | |
317 ElementFactory.methodElement( | |
318 "getContext", contextElementType, [provider.stringType]) | |
319 ]; | |
320 canvasElement.accessors = <PropertyAccessorElement>[ | |
321 ElementFactory.getterElement("context2D", false, context2dElement.type) | |
322 ]; | |
323 canvasElement.fields = canvasElement.accessors | |
324 .map((PropertyAccessorElement accessor) => accessor.variable) | |
325 .toList(); | |
326 ClassElementImpl documentElement = | |
327 ElementFactory.classElement("Document", elementType); | |
328 ClassElementImpl htmlDocumentElement = | |
329 ElementFactory.classElement("HtmlDocument", documentElement.type); | |
330 htmlDocumentElement.methods = <MethodElement>[ | |
331 ElementFactory | |
332 .methodElement("query", elementType, <DartType>[provider.stringType]) | |
333 ]; | |
334 htmlUnit.types = <ClassElement>[ | |
335 ElementFactory.classElement("AnchorElement", elementType), | |
336 ElementFactory.classElement("BodyElement", elementType), | |
337 ElementFactory.classElement("ButtonElement", elementType), | |
338 canvasElement, | |
339 contextElement, | |
340 context2dElement, | |
341 ElementFactory.classElement("DivElement", elementType), | |
342 documentElement, | |
343 elementElement, | |
344 htmlDocumentElement, | |
345 ElementFactory.classElement("InputElement", elementType), | |
346 ElementFactory.classElement("SelectElement", elementType) | |
347 ]; | |
348 htmlUnit.functions = <FunctionElement>[ | |
349 ElementFactory.functionElement3("query", elementElement, | |
350 <ClassElement>[provider.stringType.element], ClassElement.EMPTY_LIST) | |
351 ]; | |
352 TopLevelVariableElementImpl document = | |
353 ElementFactory.topLevelVariableElement3( | |
354 "document", false, true, htmlDocumentElement.type); | |
355 htmlUnit.topLevelVariables = <TopLevelVariableElement>[document]; | |
356 htmlUnit.accessors = <PropertyAccessorElement>[document.getter]; | |
357 LibraryElementImpl htmlLibrary = new LibraryElementImpl.forNode( | |
358 coreContext, AstFactory.libraryIdentifier2(["dart", "dom", "html"])); | |
359 htmlLibrary.definingCompilationUnit = htmlUnit; | |
360 // | |
361 // dart:math | |
362 // | |
363 CompilationUnitElementImpl mathUnit = | |
364 new CompilationUnitElementImpl("math.dart"); | |
365 Source mathSource = sourceFactory.forUri(_DART_MATH); | |
366 coreContext.setContents(mathSource, ""); | |
367 mathUnit.librarySource = mathUnit.source = mathSource; | |
368 FunctionElement cosElement = ElementFactory.functionElement3( | |
369 "cos", | |
370 provider.doubleType.element, | |
371 <ClassElement>[provider.numType.element], | |
372 ClassElement.EMPTY_LIST); | |
373 TopLevelVariableElement ln10Element = ElementFactory | |
374 .topLevelVariableElement3("LN10", true, false, provider.doubleType); | |
375 TypeParameterElement maxT = | |
376 ElementFactory.typeParameterWithType('T', provider.numType); | |
377 FunctionElementImpl maxElement = ElementFactory.functionElement3( | |
378 "max", maxT, [maxT, maxT], ClassElement.EMPTY_LIST); | |
379 maxElement.typeParameters = [maxT]; | |
380 maxElement.type = new FunctionTypeImpl(maxElement); | |
381 TopLevelVariableElement piElement = ElementFactory.topLevelVariableElement3( | |
382 "PI", true, false, provider.doubleType); | |
383 ClassElementImpl randomElement = ElementFactory.classElement2("Random"); | |
384 randomElement.abstract = true; | |
385 ConstructorElementImpl randomConstructor = | |
386 ElementFactory.constructorElement2(randomElement, null); | |
387 randomConstructor.factory = true; | |
388 ParameterElementImpl seedParam = new ParameterElementImpl("seed", 0); | |
389 seedParam.parameterKind = ParameterKind.POSITIONAL; | |
390 seedParam.type = provider.intType; | |
391 randomConstructor.parameters = <ParameterElement>[seedParam]; | |
392 randomElement.constructors = <ConstructorElement>[randomConstructor]; | |
393 FunctionElement sinElement = ElementFactory.functionElement3( | |
394 "sin", | |
395 provider.doubleType.element, | |
396 <ClassElement>[provider.numType.element], | |
397 ClassElement.EMPTY_LIST); | |
398 FunctionElement sqrtElement = ElementFactory.functionElement3( | |
399 "sqrt", | |
400 provider.doubleType.element, | |
401 <ClassElement>[provider.numType.element], | |
402 ClassElement.EMPTY_LIST); | |
403 mathUnit.accessors = <PropertyAccessorElement>[ | |
404 ln10Element.getter, | |
405 piElement.getter | |
406 ]; | |
407 mathUnit.functions = <FunctionElement>[ | |
408 cosElement, | |
409 maxElement, | |
410 sinElement, | |
411 sqrtElement | |
412 ]; | |
413 mathUnit.topLevelVariables = <TopLevelVariableElement>[ | |
414 ln10Element, | |
415 piElement | |
416 ]; | |
417 mathUnit.types = <ClassElement>[randomElement]; | |
418 LibraryElementImpl mathLibrary = new LibraryElementImpl.forNode( | |
419 coreContext, AstFactory.libraryIdentifier2(["dart", "math"])); | |
420 mathLibrary.definingCompilationUnit = mathUnit; | |
421 // | |
422 // Set empty sources for the rest of the libraries. | |
423 // | |
424 Source source = sourceFactory.forUri(_DART_INTERCEPTORS); | |
425 coreContext.setContents(source, ""); | |
426 source = sourceFactory.forUri(_DART_JS_HELPER); | |
427 coreContext.setContents(source, ""); | |
428 // | |
429 // Record the elements. | |
430 // | |
431 HashMap<Source, LibraryElement> elementMap = | |
432 new HashMap<Source, LibraryElement>(); | |
433 elementMap[coreSource] = coreLibrary; | |
434 if (asyncSource != null) { | |
435 elementMap[asyncSource] = asyncLibrary; | |
436 } | |
437 elementMap[htmlSource] = htmlLibrary; | |
438 elementMap[mathSource] = mathLibrary; | |
439 // | |
440 // Set the public and export namespaces. We don't use exports in the fake | |
441 // core library so public and export namespaces are the same. | |
442 // | |
443 for (LibraryElementImpl library in elementMap.values) { | |
444 Namespace namespace = | |
445 new NamespaceBuilder().createPublicNamespaceForLibrary(library); | |
446 library.exportNamespace = namespace; | |
447 library.publicNamespace = namespace; | |
448 } | |
449 context.recordLibraryElements(elementMap); | |
450 // Create the synthetic element for `loadLibrary`. | |
451 for (LibraryElementImpl library in elementMap.values) { | |
452 library.createLoadLibraryFunction(context.typeProvider); | |
453 } | |
454 return context; | |
455 } | |
456 } | |
457 | |
458 /** | |
459 * An analysis context that has a fake SDK that is much smaller and faster for | |
460 * testing purposes. | |
461 */ | |
462 class AnalysisContextForTests extends AnalysisContextImpl { | |
463 @override | |
464 void set analysisOptions(AnalysisOptions options) { | |
465 AnalysisOptions currentOptions = analysisOptions; | |
466 bool needsRecompute = currentOptions.analyzeFunctionBodiesPredicate != | |
467 options.analyzeFunctionBodiesPredicate || | |
468 currentOptions.generateImplicitErrors != | |
469 options.generateImplicitErrors || | |
470 currentOptions.generateSdkErrors != options.generateSdkErrors || | |
471 currentOptions.dart2jsHint != options.dart2jsHint || | |
472 (currentOptions.hint && !options.hint) || | |
473 currentOptions.preserveComments != options.preserveComments || | |
474 currentOptions.enableStrictCallChecks != options.enableStrictCallChecks; | |
475 if (needsRecompute) { | |
476 fail( | |
477 "Cannot set options that cause the sources to be reanalyzed in a test
context"); | |
478 } | |
479 super.analysisOptions = options; | |
480 } | |
481 | |
482 @override | |
483 bool exists(Source source) => | |
484 super.exists(source) || sourceFactory.dartSdk.context.exists(source); | |
485 | |
486 @override | |
487 TimestampedData<String> getContents(Source source) { | |
488 if (source.isInSystemLibrary) { | |
489 return sourceFactory.dartSdk.context.getContents(source); | |
490 } | |
491 return super.getContents(source); | |
492 } | |
493 | |
494 @override | |
495 int getModificationStamp(Source source) { | |
496 if (source.isInSystemLibrary) { | |
497 return sourceFactory.dartSdk.context.getModificationStamp(source); | |
498 } | |
499 return super.getModificationStamp(source); | |
500 } | |
501 | |
502 /** | |
503 * Set the analysis options, even if they would force re-analysis. This method
should only be | |
504 * invoked before the fake SDK is initialized. | |
505 * | |
506 * @param options the analysis options to be set | |
507 */ | |
508 void _internalSetAnalysisOptions(AnalysisOptions options) { | |
509 super.analysisOptions = options; | |
510 } | |
511 } | |
512 | |
513 /** | |
514 * Helper for creating and managing single [AnalysisContext]. | |
515 */ | |
516 class AnalysisContextHelper { | |
517 AnalysisContext context; | |
518 | |
519 /** | |
520 * Creates new [AnalysisContext] using [AnalysisContextFactory]. | |
521 */ | |
522 AnalysisContextHelper([AnalysisOptionsImpl options]) { | |
523 if (options == null) { | |
524 options = new AnalysisOptionsImpl(); | |
525 } | |
526 options.cacheSize = 256; | |
527 context = AnalysisContextFactory.contextWithCoreAndOptions(options); | |
528 } | |
529 | |
530 Source addSource(String path, String code) { | |
531 Source source = new FileBasedSource(FileUtilities2.createFile(path)); | |
532 if (path.endsWith(".dart") || path.endsWith(".html")) { | |
533 ChangeSet changeSet = new ChangeSet(); | |
534 changeSet.addedSource(source); | |
535 context.applyChanges(changeSet); | |
536 } | |
537 context.setContents(source, code); | |
538 return source; | |
539 } | |
540 | |
541 CompilationUnitElement getDefiningUnitElement(Source source) => | |
542 context.getCompilationUnitElement(source, source); | |
543 | |
544 CompilationUnit resolveDefiningUnit(Source source) { | |
545 LibraryElement libraryElement = context.computeLibraryElement(source); | |
546 return context.resolveCompilationUnit(source, libraryElement); | |
547 } | |
548 | |
549 void runTasks() { | |
550 AnalysisResult result = context.performAnalysisTask(); | |
551 while (result.changeNotices != null) { | |
552 result = context.performAnalysisTask(); | |
553 } | |
554 } | |
555 } | |
556 | |
557 @reflectiveTest | 55 @reflectiveTest |
558 class AnalysisDeltaTest extends EngineTestCase { | 56 class AnalysisDeltaTest extends EngineTestCase { |
559 TestSource source1 = new TestSource('/1.dart'); | 57 TestSource source1 = new TestSource('/1.dart'); |
560 TestSource source2 = new TestSource('/2.dart'); | 58 TestSource source2 = new TestSource('/2.dart'); |
561 TestSource source3 = new TestSource('/3.dart'); | 59 TestSource source3 = new TestSource('/3.dart'); |
562 | 60 |
563 void test_getAddedSources() { | 61 void test_getAddedSources() { |
564 AnalysisDelta delta = new AnalysisDelta(); | 62 AnalysisDelta delta = new AnalysisDelta(); |
565 delta.setAnalysisLevel(source1, AnalysisLevel.ALL); | 63 delta.setAnalysisLevel(source1, AnalysisLevel.ALL); |
566 delta.setAnalysisLevel(source2, AnalysisLevel.ERRORS); | 64 delta.setAnalysisLevel(source2, AnalysisLevel.ERRORS); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 changeSet.changedRange(new TestSource(), "", 0, 0, 0); | 139 changeSet.changedRange(new TestSource(), "", 0, 0, 0); |
642 changeSet.deletedSource(new TestSource()); | 140 changeSet.deletedSource(new TestSource()); |
643 changeSet.removedSource(new TestSource()); | 141 changeSet.removedSource(new TestSource()); |
644 changeSet | 142 changeSet |
645 .removedContainer(new SourceContainer_ChangeSetTest_test_toString()); | 143 .removedContainer(new SourceContainer_ChangeSetTest_test_toString()); |
646 expect(changeSet.toString(), isNotNull); | 144 expect(changeSet.toString(), isNotNull); |
647 } | 145 } |
648 } | 146 } |
649 | 147 |
650 @reflectiveTest | 148 @reflectiveTest |
651 class CheckedModeCompileTimeErrorCodeTest extends ResolverTestCase { | |
652 void test_fieldFormalParameterAssignableToField_extends() { | |
653 // According to checked-mode type checking rules, a value of type B is | |
654 // assignable to a field of type A, because B extends A (and hence is a | |
655 // subtype of A). | |
656 Source source = addSource(r''' | |
657 class A { | |
658 const A(); | |
659 } | |
660 class B extends A { | |
661 const B(); | |
662 } | |
663 class C { | |
664 final A a; | |
665 const C(this.a); | |
666 } | |
667 var v = const C(const B());'''); | |
668 computeLibrarySourceErrors(source); | |
669 assertNoErrors(source); | |
670 verify([source]); | |
671 } | |
672 | |
673 void test_fieldFormalParameterAssignableToField_fieldType_unresolved_null() { | |
674 // Null always passes runtime type checks, even when the type is | |
675 // unresolved. | |
676 Source source = addSource(r''' | |
677 class A { | |
678 final Unresolved x; | |
679 const A(String this.x); | |
680 } | |
681 var v = const A(null);'''); | |
682 computeLibrarySourceErrors(source); | |
683 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); | |
684 verify([source]); | |
685 } | |
686 | |
687 void test_fieldFormalParameterAssignableToField_implements() { | |
688 // According to checked-mode type checking rules, a value of type B is | |
689 // assignable to a field of type A, because B implements A (and hence is a | |
690 // subtype of A). | |
691 Source source = addSource(r''' | |
692 class A {} | |
693 class B implements A { | |
694 const B(); | |
695 } | |
696 class C { | |
697 final A a; | |
698 const C(this.a); | |
699 } | |
700 var v = const C(const B());'''); | |
701 computeLibrarySourceErrors(source); | |
702 assertNoErrors(source); | |
703 verify([source]); | |
704 } | |
705 | |
706 void test_fieldFormalParameterAssignableToField_list_dynamic() { | |
707 // [1, 2, 3] has type List<dynamic>, which is a subtype of List<int>. | |
708 Source source = addSource(r''' | |
709 class A { | |
710 const A(List<int> x); | |
711 } | |
712 var x = const A(const [1, 2, 3]);'''); | |
713 computeLibrarySourceErrors(source); | |
714 assertNoErrors(source); | |
715 verify([source]); | |
716 } | |
717 | |
718 void test_fieldFormalParameterAssignableToField_list_nonDynamic() { | |
719 // <int>[1, 2, 3] has type List<int>, which is a subtype of List<num>. | |
720 Source source = addSource(r''' | |
721 class A { | |
722 const A(List<num> x); | |
723 } | |
724 var x = const A(const <int>[1, 2, 3]);'''); | |
725 computeLibrarySourceErrors(source); | |
726 assertNoErrors(source); | |
727 verify([source]); | |
728 } | |
729 | |
730 void test_fieldFormalParameterAssignableToField_map_dynamic() { | |
731 // {1: 2} has type Map<dynamic, dynamic>, which is a subtype of | |
732 // Map<int, int>. | |
733 Source source = addSource(r''' | |
734 class A { | |
735 const A(Map<int, int> x); | |
736 } | |
737 var x = const A(const {1: 2});'''); | |
738 computeLibrarySourceErrors(source); | |
739 assertNoErrors(source); | |
740 verify([source]); | |
741 } | |
742 | |
743 void test_fieldFormalParameterAssignableToField_map_keyDifferent() { | |
744 // <int, int>{1: 2} has type Map<int, int>, which is a subtype of | |
745 // Map<num, int>. | |
746 Source source = addSource(r''' | |
747 class A { | |
748 const A(Map<num, int> x); | |
749 } | |
750 var x = const A(const <int, int>{1: 2});'''); | |
751 computeLibrarySourceErrors(source); | |
752 assertNoErrors(source); | |
753 verify([source]); | |
754 } | |
755 | |
756 void test_fieldFormalParameterAssignableToField_map_valueDifferent() { | |
757 // <int, int>{1: 2} has type Map<int, int>, which is a subtype of | |
758 // Map<int, num>. | |
759 Source source = addSource(r''' | |
760 class A { | |
761 const A(Map<int, num> x); | |
762 } | |
763 var x = const A(const <int, int>{1: 2});'''); | |
764 computeLibrarySourceErrors(source); | |
765 assertNoErrors(source); | |
766 verify([source]); | |
767 } | |
768 | |
769 void test_fieldFormalParameterAssignableToField_notype() { | |
770 // If a field is declared without a type, then any value may be assigned to | |
771 // it. | |
772 Source source = addSource(r''' | |
773 class A { | |
774 final x; | |
775 const A(this.x); | |
776 } | |
777 var v = const A(5);'''); | |
778 computeLibrarySourceErrors(source); | |
779 assertNoErrors(source); | |
780 verify([source]); | |
781 } | |
782 | |
783 void test_fieldFormalParameterAssignableToField_null() { | |
784 // Null is assignable to anything. | |
785 Source source = addSource(r''' | |
786 class A { | |
787 final int x; | |
788 const A(this.x); | |
789 } | |
790 var v = const A(null);'''); | |
791 computeLibrarySourceErrors(source); | |
792 assertNoErrors(source); | |
793 verify([source]); | |
794 } | |
795 | |
796 void test_fieldFormalParameterAssignableToField_typedef() { | |
797 // foo has the runtime type dynamic -> dynamic, so it should be assignable | |
798 // to A.f. | |
799 Source source = addSource(r''' | |
800 typedef String Int2String(int x); | |
801 class A { | |
802 final Int2String f; | |
803 const A(this.f); | |
804 } | |
805 foo(x) => 1; | |
806 var v = const A(foo);'''); | |
807 computeLibrarySourceErrors(source); | |
808 assertNoErrors(source); | |
809 verify([source]); | |
810 } | |
811 | |
812 void test_fieldFormalParameterAssignableToField_typeSubstitution() { | |
813 // foo has the runtime type dynamic -> dynamic, so it should be assignable | |
814 // to A.f. | |
815 Source source = addSource(r''' | |
816 class A<T> { | |
817 final T x; | |
818 const A(this.x); | |
819 } | |
820 var v = const A<int>(3);'''); | |
821 computeLibrarySourceErrors(source); | |
822 assertNoErrors(source); | |
823 verify([source]); | |
824 } | |
825 | |
826 void test_fieldFormalParameterNotAssignableToField() { | |
827 Source source = addSource(r''' | |
828 class A { | |
829 final int x; | |
830 const A(this.x); | |
831 } | |
832 var v = const A('foo');'''); | |
833 computeLibrarySourceErrors(source); | |
834 assertErrors(source, [ | |
835 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | |
836 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE | |
837 ]); | |
838 verify([source]); | |
839 } | |
840 | |
841 void test_fieldFormalParameterNotAssignableToField_extends() { | |
842 // According to checked-mode type checking rules, a value of type A is not | |
843 // assignable to a field of type B, because B extends A (the subtyping | |
844 // relationship is in the wrong direction). | |
845 Source source = addSource(r''' | |
846 class A { | |
847 const A(); | |
848 } | |
849 class B extends A { | |
850 const B(); | |
851 } | |
852 class C { | |
853 final B b; | |
854 const C(this.b); | |
855 } | |
856 var v = const C(const A());'''); | |
857 computeLibrarySourceErrors(source); | |
858 assertErrors(source, [ | |
859 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH | |
860 ]); | |
861 verify([source]); | |
862 } | |
863 | |
864 void test_fieldFormalParameterNotAssignableToField_fieldType() { | |
865 Source source = addSource(r''' | |
866 class A { | |
867 final int x; | |
868 const A(String this.x); | |
869 } | |
870 var v = const A('foo');'''); | |
871 computeLibrarySourceErrors(source); | |
872 assertErrors(source, [ | |
873 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | |
874 StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE | |
875 ]); | |
876 verify([source]); | |
877 } | |
878 | |
879 void test_fieldFormalParameterNotAssignableToField_fieldType_unresolved() { | |
880 Source source = addSource(r''' | |
881 class A { | |
882 final Unresolved x; | |
883 const A(String this.x); | |
884 } | |
885 var v = const A('foo');'''); | |
886 computeLibrarySourceErrors(source); | |
887 assertErrors(source, [ | |
888 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | |
889 StaticWarningCode.UNDEFINED_CLASS | |
890 ]); | |
891 verify([source]); | |
892 } | |
893 | |
894 void test_fieldFormalParameterNotAssignableToField_implements() { | |
895 // According to checked-mode type checking rules, a value of type A is not | |
896 // assignable to a field of type B, because B implements A (the subtyping | |
897 // relationship is in the wrong direction). | |
898 Source source = addSource(r''' | |
899 class A { | |
900 const A(); | |
901 } | |
902 class B implements A {} | |
903 class C { | |
904 final B b; | |
905 const C(this.b); | |
906 } | |
907 var v = const C(const A());'''); | |
908 computeLibrarySourceErrors(source); | |
909 assertErrors(source, [ | |
910 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH | |
911 ]); | |
912 verify([source]); | |
913 } | |
914 | |
915 void test_fieldFormalParameterNotAssignableToField_list() { | |
916 // <num>[1, 2, 3] has type List<num>, which is not a subtype of List<int>. | |
917 Source source = addSource(r''' | |
918 class A { | |
919 const A(List<int> x); | |
920 } | |
921 var x = const A(const <num>[1, 2, 3]);'''); | |
922 computeLibrarySourceErrors(source); | |
923 assertErrors(source, [ | |
924 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH | |
925 ]); | |
926 verify([source]); | |
927 } | |
928 | |
929 void test_fieldFormalParameterNotAssignableToField_map_keyMismatch() { | |
930 // <num, int>{1: 2} has type Map<num, int>, which is not a subtype of | |
931 // Map<int, int>. | |
932 Source source = addSource(r''' | |
933 class A { | |
934 const A(Map<int, int> x); | |
935 } | |
936 var x = const A(const <num, int>{1: 2});'''); | |
937 computeLibrarySourceErrors(source); | |
938 assertErrors(source, [ | |
939 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH | |
940 ]); | |
941 verify([source]); | |
942 } | |
943 | |
944 void test_fieldFormalParameterNotAssignableToField_map_valueMismatch() { | |
945 // <int, num>{1: 2} has type Map<int, num>, which is not a subtype of | |
946 // Map<int, int>. | |
947 Source source = addSource(r''' | |
948 class A { | |
949 const A(Map<int, int> x); | |
950 } | |
951 var x = const A(const <int, num>{1: 2});'''); | |
952 computeLibrarySourceErrors(source); | |
953 assertErrors(source, [ | |
954 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH | |
955 ]); | |
956 verify([source]); | |
957 } | |
958 | |
959 void test_fieldFormalParameterNotAssignableToField_optional() { | |
960 Source source = addSource(r''' | |
961 class A { | |
962 final int x; | |
963 const A([this.x = 'foo']); | |
964 } | |
965 var v = const A();'''); | |
966 computeLibrarySourceErrors(source); | |
967 assertErrors(source, [ | |
968 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | |
969 StaticTypeWarningCode.INVALID_ASSIGNMENT | |
970 ]); | |
971 verify([source]); | |
972 } | |
973 | |
974 void test_fieldFormalParameterNotAssignableToField_typedef() { | |
975 // foo has the runtime type String -> int, so it should not be assignable | |
976 // to A.f (A.f requires it to be int -> String). | |
977 Source source = addSource(r''' | |
978 typedef String Int2String(int x); | |
979 class A { | |
980 final Int2String f; | |
981 const A(this.f); | |
982 } | |
983 int foo(String x) => 1; | |
984 var v = const A(foo);'''); | |
985 computeLibrarySourceErrors(source); | |
986 assertErrors(source, [ | |
987 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | |
988 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE | |
989 ]); | |
990 verify([source]); | |
991 } | |
992 | |
993 void test_fieldInitializerNotAssignable() { | |
994 Source source = addSource(r''' | |
995 class A { | |
996 final int x; | |
997 const A() : x = ''; | |
998 }'''); | |
999 computeLibrarySourceErrors(source); | |
1000 assertErrors(source, [ | |
1001 CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE, | |
1002 StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE | |
1003 ]); | |
1004 verify([source]); | |
1005 } | |
1006 | |
1007 void test_fieldTypeMismatch() { | |
1008 Source source = addSource(r''' | |
1009 class A { | |
1010 const A(x) : y = x; | |
1011 final int y; | |
1012 } | |
1013 var v = const A('foo');'''); | |
1014 computeLibrarySourceErrors(source); | |
1015 assertErrors(source, [ | |
1016 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH | |
1017 ]); | |
1018 verify([source]); | |
1019 } | |
1020 | |
1021 void test_fieldTypeMismatch_generic() { | |
1022 Source source = addSource(r''' | |
1023 class C<T> { | |
1024 final T x = y; | |
1025 const C(); | |
1026 } | |
1027 const int y = 1; | |
1028 var v = const C<String>(); | |
1029 '''); | |
1030 computeLibrarySourceErrors(source); | |
1031 assertErrors(source, [ | |
1032 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, | |
1033 StaticTypeWarningCode.INVALID_ASSIGNMENT | |
1034 ]); | |
1035 verify([source]); | |
1036 } | |
1037 | |
1038 void test_fieldTypeMismatch_unresolved() { | |
1039 Source source = addSource(r''' | |
1040 class A { | |
1041 const A(x) : y = x; | |
1042 final Unresolved y; | |
1043 } | |
1044 var v = const A('foo');'''); | |
1045 computeLibrarySourceErrors(source); | |
1046 assertErrors(source, [ | |
1047 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, | |
1048 StaticWarningCode.UNDEFINED_CLASS | |
1049 ]); | |
1050 verify([source]); | |
1051 } | |
1052 | |
1053 void test_fieldTypeOk_generic() { | |
1054 Source source = addSource(r''' | |
1055 class C<T> { | |
1056 final T x = y; | |
1057 const C(); | |
1058 } | |
1059 const int y = 1; | |
1060 var v = const C<int>(); | |
1061 '''); | |
1062 computeLibrarySourceErrors(source); | |
1063 assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); | |
1064 verify([source]); | |
1065 } | |
1066 | |
1067 void test_fieldTypeOk_null() { | |
1068 Source source = addSource(r''' | |
1069 class A { | |
1070 const A(x) : y = x; | |
1071 final int y; | |
1072 } | |
1073 var v = const A(null);'''); | |
1074 computeLibrarySourceErrors(source); | |
1075 assertNoErrors(source); | |
1076 verify([source]); | |
1077 } | |
1078 | |
1079 void test_fieldTypeOk_unresolved_null() { | |
1080 // Null always passes runtime type checks, even when the type is | |
1081 // unresolved. | |
1082 Source source = addSource(r''' | |
1083 class A { | |
1084 const A(x) : y = x; | |
1085 final Unresolved y; | |
1086 } | |
1087 var v = const A(null);'''); | |
1088 computeLibrarySourceErrors(source); | |
1089 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); | |
1090 verify([source]); | |
1091 } | |
1092 | |
1093 void test_listElementTypeNotAssignable() { | |
1094 Source source = addSource("var v = const <String> [42];"); | |
1095 computeLibrarySourceErrors(source); | |
1096 assertErrors(source, [ | |
1097 CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, | |
1098 StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE | |
1099 ]); | |
1100 verify([source]); | |
1101 } | |
1102 | |
1103 void test_mapKeyTypeNotAssignable() { | |
1104 Source source = addSource("var v = const <String, int > {1 : 2};"); | |
1105 computeLibrarySourceErrors(source); | |
1106 assertErrors(source, [ | |
1107 CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, | |
1108 StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE | |
1109 ]); | |
1110 verify([source]); | |
1111 } | |
1112 | |
1113 void test_mapValueTypeNotAssignable() { | |
1114 Source source = addSource("var v = const <String, String> {'a' : 2};"); | |
1115 computeLibrarySourceErrors(source); | |
1116 assertErrors(source, [ | |
1117 CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, | |
1118 StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE | |
1119 ]); | |
1120 verify([source]); | |
1121 } | |
1122 | |
1123 void test_parameterAssignable_null() { | |
1124 // Null is assignable to anything. | |
1125 Source source = addSource(r''' | |
1126 class A { | |
1127 const A(int x); | |
1128 } | |
1129 var v = const A(null);'''); | |
1130 computeLibrarySourceErrors(source); | |
1131 assertNoErrors(source); | |
1132 verify([source]); | |
1133 } | |
1134 | |
1135 void test_parameterAssignable_typeSubstitution() { | |
1136 Source source = addSource(r''' | |
1137 class A<T> { | |
1138 const A(T x); | |
1139 } | |
1140 var v = const A<int>(3);'''); | |
1141 computeLibrarySourceErrors(source); | |
1142 assertNoErrors(source); | |
1143 verify([source]); | |
1144 } | |
1145 | |
1146 void test_parameterAssignable_undefined_null() { | |
1147 // Null always passes runtime type checks, even when the type is | |
1148 // unresolved. | |
1149 Source source = addSource(r''' | |
1150 class A { | |
1151 const A(Unresolved x); | |
1152 } | |
1153 var v = const A(null);'''); | |
1154 computeLibrarySourceErrors(source); | |
1155 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); | |
1156 verify([source]); | |
1157 } | |
1158 | |
1159 void test_parameterNotAssignable() { | |
1160 Source source = addSource(r''' | |
1161 class A { | |
1162 const A(int x); | |
1163 } | |
1164 var v = const A('foo');'''); | |
1165 computeLibrarySourceErrors(source); | |
1166 assertErrors(source, [ | |
1167 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | |
1168 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE | |
1169 ]); | |
1170 verify([source]); | |
1171 } | |
1172 | |
1173 void test_parameterNotAssignable_typeSubstitution() { | |
1174 Source source = addSource(r''' | |
1175 class A<T> { | |
1176 const A(T x); | |
1177 } | |
1178 var v = const A<int>('foo');'''); | |
1179 computeLibrarySourceErrors(source); | |
1180 assertErrors(source, [ | |
1181 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | |
1182 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE | |
1183 ]); | |
1184 verify([source]); | |
1185 } | |
1186 | |
1187 void test_parameterNotAssignable_undefined() { | |
1188 Source source = addSource(r''' | |
1189 class A { | |
1190 const A(Unresolved x); | |
1191 } | |
1192 var v = const A('foo');'''); | |
1193 computeLibrarySourceErrors(source); | |
1194 assertErrors(source, [ | |
1195 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, | |
1196 StaticWarningCode.UNDEFINED_CLASS | |
1197 ]); | |
1198 verify([source]); | |
1199 } | |
1200 | |
1201 void test_redirectingConstructor_paramTypeMismatch() { | |
1202 Source source = addSource(r''' | |
1203 class A { | |
1204 const A.a1(x) : this.a2(x); | |
1205 const A.a2(String x); | |
1206 } | |
1207 var v = const A.a1(0);'''); | |
1208 computeLibrarySourceErrors(source); | |
1209 assertErrors(source, [ | |
1210 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH | |
1211 ]); | |
1212 verify([source]); | |
1213 } | |
1214 | |
1215 void test_topLevelVarAssignable_null() { | |
1216 Source source = addSource("const int x = null;"); | |
1217 computeLibrarySourceErrors(source); | |
1218 assertNoErrors(source); | |
1219 verify([source]); | |
1220 } | |
1221 | |
1222 void test_topLevelVarAssignable_undefined_null() { | |
1223 // Null always passes runtime type checks, even when the type is | |
1224 // unresolved. | |
1225 Source source = addSource("const Unresolved x = null;"); | |
1226 computeLibrarySourceErrors(source); | |
1227 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); | |
1228 verify([source]); | |
1229 } | |
1230 | |
1231 void test_topLevelVarNotAssignable() { | |
1232 Source source = addSource("const int x = 'foo';"); | |
1233 computeLibrarySourceErrors(source); | |
1234 assertErrors(source, [ | |
1235 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, | |
1236 StaticTypeWarningCode.INVALID_ASSIGNMENT | |
1237 ]); | |
1238 verify([source]); | |
1239 } | |
1240 | |
1241 void test_topLevelVarNotAssignable_undefined() { | |
1242 Source source = addSource("const Unresolved x = 'foo';"); | |
1243 computeLibrarySourceErrors(source); | |
1244 assertErrors(source, [ | |
1245 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, | |
1246 StaticWarningCode.UNDEFINED_CLASS | |
1247 ]); | |
1248 verify([source]); | |
1249 } | |
1250 } | |
1251 | |
1252 @reflectiveTest | |
1253 class DisableAsyncTestCase extends ResolverTestCase { | 149 class DisableAsyncTestCase extends ResolverTestCase { |
1254 @override | 150 @override |
1255 void setUp() { | 151 void setUp() { |
1256 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | 152 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
1257 options.enableAsync = false; | 153 options.enableAsync = false; |
1258 resetWithOptions(options); | 154 resetWithOptions(options); |
1259 } | 155 } |
1260 | 156 |
1261 void test_resolve() { | 157 void test_resolve() { |
1262 Source source = addSource(r''' | 158 Source source = addSource(r''' |
(...skipping 25 matching lines...) Expand all Loading... |
1288 StaticWarningCode.UNDEFINED_CLASS, | 184 StaticWarningCode.UNDEFINED_CLASS, |
1289 StaticWarningCode.UNDEFINED_CLASS, | 185 StaticWarningCode.UNDEFINED_CLASS, |
1290 StaticWarningCode.UNDEFINED_CLASS, | 186 StaticWarningCode.UNDEFINED_CLASS, |
1291 StaticWarningCode.UNDEFINED_CLASS, | 187 StaticWarningCode.UNDEFINED_CLASS, |
1292 ParserErrorCode.ASYNC_NOT_SUPPORTED | 188 ParserErrorCode.ASYNC_NOT_SUPPORTED |
1293 ]); | 189 ]); |
1294 } | 190 } |
1295 } | 191 } |
1296 | 192 |
1297 @reflectiveTest | 193 @reflectiveTest |
1298 class ElementResolverTest extends EngineTestCase { | |
1299 /** | |
1300 * The error listener to which errors will be reported. | |
1301 */ | |
1302 GatheringErrorListener _listener; | |
1303 | |
1304 /** | |
1305 * The type provider used to access the types. | |
1306 */ | |
1307 TestTypeProvider _typeProvider; | |
1308 | |
1309 /** | |
1310 * The library containing the code being resolved. | |
1311 */ | |
1312 LibraryElementImpl _definingLibrary; | |
1313 | |
1314 /** | |
1315 * The resolver visitor that maintains the state for the resolver. | |
1316 */ | |
1317 ResolverVisitor _visitor; | |
1318 | |
1319 /** | |
1320 * The resolver being used to resolve the test cases. | |
1321 */ | |
1322 ElementResolver _resolver; | |
1323 | |
1324 void fail_visitExportDirective_combinators() { | |
1325 fail("Not yet tested"); | |
1326 // Need to set up the exported library so that the identifier can be | |
1327 // resolved. | |
1328 ExportDirective directive = AstFactory.exportDirective2(null, [ | |
1329 AstFactory.hideCombinator2(["A"]) | |
1330 ]); | |
1331 _resolveNode(directive); | |
1332 _listener.assertNoErrors(); | |
1333 } | |
1334 | |
1335 void fail_visitFunctionExpressionInvocation() { | |
1336 fail("Not yet tested"); | |
1337 _listener.assertNoErrors(); | |
1338 } | |
1339 | |
1340 void fail_visitImportDirective_combinators_noPrefix() { | |
1341 fail("Not yet tested"); | |
1342 // Need to set up the imported library so that the identifier can be | |
1343 // resolved. | |
1344 ImportDirective directive = AstFactory.importDirective3(null, null, [ | |
1345 AstFactory.showCombinator2(["A"]) | |
1346 ]); | |
1347 _resolveNode(directive); | |
1348 _listener.assertNoErrors(); | |
1349 } | |
1350 | |
1351 void fail_visitImportDirective_combinators_prefix() { | |
1352 fail("Not yet tested"); | |
1353 // Need to set up the imported library so that the identifiers can be | |
1354 // resolved. | |
1355 String prefixName = "p"; | |
1356 _definingLibrary.imports = <ImportElement>[ | |
1357 ElementFactory.importFor(null, ElementFactory.prefix(prefixName)) | |
1358 ]; | |
1359 ImportDirective directive = AstFactory.importDirective3(null, prefixName, [ | |
1360 AstFactory.showCombinator2(["A"]), | |
1361 AstFactory.hideCombinator2(["B"]) | |
1362 ]); | |
1363 _resolveNode(directive); | |
1364 _listener.assertNoErrors(); | |
1365 } | |
1366 | |
1367 void fail_visitRedirectingConstructorInvocation() { | |
1368 fail("Not yet tested"); | |
1369 _listener.assertNoErrors(); | |
1370 } | |
1371 | |
1372 @override | |
1373 void setUp() { | |
1374 super.setUp(); | |
1375 _listener = new GatheringErrorListener(); | |
1376 _typeProvider = new TestTypeProvider(); | |
1377 _resolver = _createResolver(); | |
1378 } | |
1379 | |
1380 void test_lookUpMethodInInterfaces() { | |
1381 InterfaceType intType = _typeProvider.intType; | |
1382 // | |
1383 // abstract class A { int operator[](int index); } | |
1384 // | |
1385 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1386 MethodElement operator = | |
1387 ElementFactory.methodElement("[]", intType, [intType]); | |
1388 classA.methods = <MethodElement>[operator]; | |
1389 // | |
1390 // class B implements A {} | |
1391 // | |
1392 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
1393 classB.interfaces = <InterfaceType>[classA.type]; | |
1394 // | |
1395 // class C extends Object with B {} | |
1396 // | |
1397 ClassElementImpl classC = ElementFactory.classElement2("C"); | |
1398 classC.mixins = <InterfaceType>[classB.type]; | |
1399 // | |
1400 // class D extends C {} | |
1401 // | |
1402 ClassElementImpl classD = ElementFactory.classElement("D", classC.type); | |
1403 // | |
1404 // D a; | |
1405 // a[i]; | |
1406 // | |
1407 SimpleIdentifier array = AstFactory.identifier3("a"); | |
1408 array.staticType = classD.type; | |
1409 IndexExpression expression = | |
1410 AstFactory.indexExpression(array, AstFactory.identifier3("i")); | |
1411 expect(_resolveIndexExpression(expression), same(operator)); | |
1412 _listener.assertNoErrors(); | |
1413 } | |
1414 | |
1415 void test_visitAssignmentExpression_compound() { | |
1416 InterfaceType intType = _typeProvider.intType; | |
1417 SimpleIdentifier leftHandSide = AstFactory.identifier3("a"); | |
1418 leftHandSide.staticType = intType; | |
1419 AssignmentExpression assignment = AstFactory.assignmentExpression( | |
1420 leftHandSide, TokenType.PLUS_EQ, AstFactory.integer(1)); | |
1421 _resolveNode(assignment); | |
1422 expect( | |
1423 assignment.staticElement, same(getMethod(_typeProvider.numType, "+"))); | |
1424 _listener.assertNoErrors(); | |
1425 } | |
1426 | |
1427 void test_visitAssignmentExpression_simple() { | |
1428 AssignmentExpression expression = AstFactory.assignmentExpression( | |
1429 AstFactory.identifier3("x"), TokenType.EQ, AstFactory.integer(0)); | |
1430 _resolveNode(expression); | |
1431 expect(expression.staticElement, isNull); | |
1432 _listener.assertNoErrors(); | |
1433 } | |
1434 | |
1435 void test_visitBinaryExpression_bangEq() { | |
1436 // String i; | |
1437 // var j; | |
1438 // i == j | |
1439 InterfaceType stringType = _typeProvider.stringType; | |
1440 SimpleIdentifier left = AstFactory.identifier3("i"); | |
1441 left.staticType = stringType; | |
1442 BinaryExpression expression = AstFactory.binaryExpression( | |
1443 left, TokenType.BANG_EQ, AstFactory.identifier3("j")); | |
1444 _resolveNode(expression); | |
1445 var stringElement = stringType.element; | |
1446 expect(expression.staticElement, isNotNull); | |
1447 expect( | |
1448 expression.staticElement, | |
1449 stringElement.lookUpMethod( | |
1450 TokenType.EQ_EQ.lexeme, stringElement.library)); | |
1451 expect(expression.propagatedElement, isNull); | |
1452 _listener.assertNoErrors(); | |
1453 } | |
1454 | |
1455 void test_visitBinaryExpression_eq() { | |
1456 // String i; | |
1457 // var j; | |
1458 // i == j | |
1459 InterfaceType stringType = _typeProvider.stringType; | |
1460 SimpleIdentifier left = AstFactory.identifier3("i"); | |
1461 left.staticType = stringType; | |
1462 BinaryExpression expression = AstFactory.binaryExpression( | |
1463 left, TokenType.EQ_EQ, AstFactory.identifier3("j")); | |
1464 _resolveNode(expression); | |
1465 var stringElement = stringType.element; | |
1466 expect( | |
1467 expression.staticElement, | |
1468 stringElement.lookUpMethod( | |
1469 TokenType.EQ_EQ.lexeme, stringElement.library)); | |
1470 expect(expression.propagatedElement, isNull); | |
1471 _listener.assertNoErrors(); | |
1472 } | |
1473 | |
1474 void test_visitBinaryExpression_plus() { | |
1475 // num i; | |
1476 // var j; | |
1477 // i + j | |
1478 InterfaceType numType = _typeProvider.numType; | |
1479 SimpleIdentifier left = AstFactory.identifier3("i"); | |
1480 left.staticType = numType; | |
1481 BinaryExpression expression = AstFactory.binaryExpression( | |
1482 left, TokenType.PLUS, AstFactory.identifier3("j")); | |
1483 _resolveNode(expression); | |
1484 expect(expression.staticElement, getMethod(numType, "+")); | |
1485 expect(expression.propagatedElement, isNull); | |
1486 _listener.assertNoErrors(); | |
1487 } | |
1488 | |
1489 void test_visitBinaryExpression_plus_propagatedElement() { | |
1490 // var i = 1; | |
1491 // var j; | |
1492 // i + j | |
1493 InterfaceType numType = _typeProvider.numType; | |
1494 SimpleIdentifier left = AstFactory.identifier3("i"); | |
1495 left.propagatedType = numType; | |
1496 BinaryExpression expression = AstFactory.binaryExpression( | |
1497 left, TokenType.PLUS, AstFactory.identifier3("j")); | |
1498 _resolveNode(expression); | |
1499 expect(expression.staticElement, isNull); | |
1500 expect(expression.propagatedElement, getMethod(numType, "+")); | |
1501 _listener.assertNoErrors(); | |
1502 } | |
1503 | |
1504 void test_visitBreakStatement_withLabel() { | |
1505 // loop: while (true) { | |
1506 // break loop; | |
1507 // } | |
1508 String label = "loop"; | |
1509 LabelElementImpl labelElement = new LabelElementImpl.forNode( | |
1510 AstFactory.identifier3(label), false, false); | |
1511 BreakStatement breakStatement = AstFactory.breakStatement2(label); | |
1512 Expression condition = AstFactory.booleanLiteral(true); | |
1513 WhileStatement whileStatement = | |
1514 AstFactory.whileStatement(condition, breakStatement); | |
1515 expect(_resolveBreak(breakStatement, labelElement, whileStatement), | |
1516 same(labelElement)); | |
1517 expect(breakStatement.target, same(whileStatement)); | |
1518 _listener.assertNoErrors(); | |
1519 } | |
1520 | |
1521 void test_visitBreakStatement_withoutLabel() { | |
1522 BreakStatement statement = AstFactory.breakStatement(); | |
1523 _resolveStatement(statement, null, null); | |
1524 _listener.assertNoErrors(); | |
1525 } | |
1526 | |
1527 void test_visitCommentReference_prefixedIdentifier_class_getter() { | |
1528 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1529 // set accessors | |
1530 String propName = "p"; | |
1531 PropertyAccessorElement getter = | |
1532 ElementFactory.getterElement(propName, false, _typeProvider.intType); | |
1533 PropertyAccessorElement setter = | |
1534 ElementFactory.setterElement(propName, false, _typeProvider.intType); | |
1535 classA.accessors = <PropertyAccessorElement>[getter, setter]; | |
1536 // set name scope | |
1537 _visitor.nameScope = new EnclosedScope(null) | |
1538 ..defineNameWithoutChecking('A', classA); | |
1539 // prepare "A.p" | |
1540 PrefixedIdentifier prefixed = AstFactory.identifier5('A', 'p'); | |
1541 CommentReference commentReference = new CommentReference(null, prefixed); | |
1542 // resolve | |
1543 _resolveNode(commentReference); | |
1544 expect(prefixed.prefix.staticElement, classA); | |
1545 expect(prefixed.identifier.staticElement, getter); | |
1546 _listener.assertNoErrors(); | |
1547 } | |
1548 | |
1549 void test_visitCommentReference_prefixedIdentifier_class_method() { | |
1550 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1551 // set method | |
1552 MethodElement method = | |
1553 ElementFactory.methodElement("m", _typeProvider.intType); | |
1554 classA.methods = <MethodElement>[method]; | |
1555 // set name scope | |
1556 _visitor.nameScope = new EnclosedScope(null) | |
1557 ..defineNameWithoutChecking('A', classA); | |
1558 // prepare "A.m" | |
1559 PrefixedIdentifier prefixed = AstFactory.identifier5('A', 'm'); | |
1560 CommentReference commentReference = new CommentReference(null, prefixed); | |
1561 // resolve | |
1562 _resolveNode(commentReference); | |
1563 expect(prefixed.prefix.staticElement, classA); | |
1564 expect(prefixed.identifier.staticElement, method); | |
1565 _listener.assertNoErrors(); | |
1566 } | |
1567 | |
1568 void test_visitConstructorName_named() { | |
1569 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1570 String constructorName = "a"; | |
1571 ConstructorElement constructor = | |
1572 ElementFactory.constructorElement2(classA, constructorName); | |
1573 classA.constructors = <ConstructorElement>[constructor]; | |
1574 ConstructorName name = AstFactory.constructorName( | |
1575 AstFactory.typeName(classA), constructorName); | |
1576 _resolveNode(name); | |
1577 expect(name.staticElement, same(constructor)); | |
1578 _listener.assertNoErrors(); | |
1579 } | |
1580 | |
1581 void test_visitConstructorName_unnamed() { | |
1582 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1583 String constructorName = null; | |
1584 ConstructorElement constructor = | |
1585 ElementFactory.constructorElement2(classA, constructorName); | |
1586 classA.constructors = <ConstructorElement>[constructor]; | |
1587 ConstructorName name = AstFactory.constructorName( | |
1588 AstFactory.typeName(classA), constructorName); | |
1589 _resolveNode(name); | |
1590 expect(name.staticElement, same(constructor)); | |
1591 _listener.assertNoErrors(); | |
1592 } | |
1593 | |
1594 void test_visitContinueStatement_withLabel() { | |
1595 // loop: while (true) { | |
1596 // continue loop; | |
1597 // } | |
1598 String label = "loop"; | |
1599 LabelElementImpl labelElement = new LabelElementImpl.forNode( | |
1600 AstFactory.identifier3(label), false, false); | |
1601 ContinueStatement continueStatement = AstFactory.continueStatement(label); | |
1602 Expression condition = AstFactory.booleanLiteral(true); | |
1603 WhileStatement whileStatement = | |
1604 AstFactory.whileStatement(condition, continueStatement); | |
1605 expect(_resolveContinue(continueStatement, labelElement, whileStatement), | |
1606 same(labelElement)); | |
1607 expect(continueStatement.target, same(whileStatement)); | |
1608 _listener.assertNoErrors(); | |
1609 } | |
1610 | |
1611 void test_visitContinueStatement_withoutLabel() { | |
1612 ContinueStatement statement = AstFactory.continueStatement(); | |
1613 _resolveStatement(statement, null, null); | |
1614 _listener.assertNoErrors(); | |
1615 } | |
1616 | |
1617 void test_visitEnumDeclaration() { | |
1618 CompilationUnitElementImpl compilationUnitElement = | |
1619 ElementFactory.compilationUnit('foo.dart'); | |
1620 ClassElementImpl enumElement = | |
1621 ElementFactory.enumElement(_typeProvider, ('E')); | |
1622 compilationUnitElement.enums = <ClassElement>[enumElement]; | |
1623 EnumDeclaration enumNode = AstFactory.enumDeclaration2('E', []); | |
1624 Annotation annotationNode = | |
1625 AstFactory.annotation(AstFactory.identifier3('a')); | |
1626 annotationNode.element = ElementFactory.classElement2('A'); | |
1627 annotationNode.elementAnnotation = | |
1628 new ElementAnnotationImpl(compilationUnitElement); | |
1629 enumNode.metadata.add(annotationNode); | |
1630 enumNode.name.staticElement = enumElement; | |
1631 List<ElementAnnotation> metadata = <ElementAnnotation>[ | |
1632 annotationNode.elementAnnotation | |
1633 ]; | |
1634 _resolveNode(enumNode); | |
1635 expect(metadata[0].element, annotationNode.element); | |
1636 } | |
1637 | |
1638 void test_visitExportDirective_noCombinators() { | |
1639 ExportDirective directive = AstFactory.exportDirective2(null); | |
1640 directive.element = ElementFactory | |
1641 .exportFor(ElementFactory.library(_definingLibrary.context, "lib")); | |
1642 _resolveNode(directive); | |
1643 _listener.assertNoErrors(); | |
1644 } | |
1645 | |
1646 void test_visitFieldFormalParameter() { | |
1647 String fieldName = "f"; | |
1648 InterfaceType intType = _typeProvider.intType; | |
1649 FieldElementImpl fieldElement = | |
1650 ElementFactory.fieldElement(fieldName, false, false, false, intType); | |
1651 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1652 classA.fields = <FieldElement>[fieldElement]; | |
1653 FieldFormalParameter parameter = | |
1654 AstFactory.fieldFormalParameter2(fieldName); | |
1655 FieldFormalParameterElementImpl parameterElement = | |
1656 ElementFactory.fieldFormalParameter(parameter.identifier); | |
1657 parameterElement.field = fieldElement; | |
1658 parameterElement.type = intType; | |
1659 parameter.identifier.staticElement = parameterElement; | |
1660 _resolveInClass(parameter, classA); | |
1661 expect(parameter.element.type, same(intType)); | |
1662 } | |
1663 | |
1664 void test_visitImportDirective_noCombinators_noPrefix() { | |
1665 ImportDirective directive = AstFactory.importDirective3(null, null); | |
1666 directive.element = ElementFactory.importFor( | |
1667 ElementFactory.library(_definingLibrary.context, "lib"), null); | |
1668 _resolveNode(directive); | |
1669 _listener.assertNoErrors(); | |
1670 } | |
1671 | |
1672 void test_visitImportDirective_noCombinators_prefix() { | |
1673 String prefixName = "p"; | |
1674 ImportElement importElement = ElementFactory.importFor( | |
1675 ElementFactory.library(_definingLibrary.context, "lib"), | |
1676 ElementFactory.prefix(prefixName)); | |
1677 _definingLibrary.imports = <ImportElement>[importElement]; | |
1678 ImportDirective directive = AstFactory.importDirective3(null, prefixName); | |
1679 directive.element = importElement; | |
1680 _resolveNode(directive); | |
1681 _listener.assertNoErrors(); | |
1682 } | |
1683 | |
1684 void test_visitImportDirective_withCombinators() { | |
1685 ShowCombinator combinator = AstFactory.showCombinator2(["A", "B", "C"]); | |
1686 ImportDirective directive = | |
1687 AstFactory.importDirective3(null, null, [combinator]); | |
1688 LibraryElementImpl library = | |
1689 ElementFactory.library(_definingLibrary.context, "lib"); | |
1690 TopLevelVariableElementImpl varA = | |
1691 ElementFactory.topLevelVariableElement2("A"); | |
1692 TopLevelVariableElementImpl varB = | |
1693 ElementFactory.topLevelVariableElement2("B"); | |
1694 TopLevelVariableElementImpl varC = | |
1695 ElementFactory.topLevelVariableElement2("C"); | |
1696 CompilationUnitElementImpl unit = | |
1697 library.definingCompilationUnit as CompilationUnitElementImpl; | |
1698 unit.accessors = <PropertyAccessorElement>[ | |
1699 varA.getter, | |
1700 varA.setter, | |
1701 varB.getter, | |
1702 varC.setter | |
1703 ]; | |
1704 unit.topLevelVariables = <TopLevelVariableElement>[varA, varB, varC]; | |
1705 directive.element = ElementFactory.importFor(library, null); | |
1706 _resolveNode(directive); | |
1707 expect(combinator.shownNames[0].staticElement, same(varA)); | |
1708 expect(combinator.shownNames[1].staticElement, same(varB)); | |
1709 expect(combinator.shownNames[2].staticElement, same(varC)); | |
1710 _listener.assertNoErrors(); | |
1711 } | |
1712 | |
1713 void test_visitIndexExpression_get() { | |
1714 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1715 InterfaceType intType = _typeProvider.intType; | |
1716 MethodElement getter = | |
1717 ElementFactory.methodElement("[]", intType, [intType]); | |
1718 classA.methods = <MethodElement>[getter]; | |
1719 SimpleIdentifier array = AstFactory.identifier3("a"); | |
1720 array.staticType = classA.type; | |
1721 IndexExpression expression = | |
1722 AstFactory.indexExpression(array, AstFactory.identifier3("i")); | |
1723 expect(_resolveIndexExpression(expression), same(getter)); | |
1724 _listener.assertNoErrors(); | |
1725 } | |
1726 | |
1727 void test_visitIndexExpression_set() { | |
1728 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1729 InterfaceType intType = _typeProvider.intType; | |
1730 MethodElement setter = | |
1731 ElementFactory.methodElement("[]=", intType, [intType]); | |
1732 classA.methods = <MethodElement>[setter]; | |
1733 SimpleIdentifier array = AstFactory.identifier3("a"); | |
1734 array.staticType = classA.type; | |
1735 IndexExpression expression = | |
1736 AstFactory.indexExpression(array, AstFactory.identifier3("i")); | |
1737 AstFactory.assignmentExpression( | |
1738 expression, TokenType.EQ, AstFactory.integer(0)); | |
1739 expect(_resolveIndexExpression(expression), same(setter)); | |
1740 _listener.assertNoErrors(); | |
1741 } | |
1742 | |
1743 void test_visitInstanceCreationExpression_named() { | |
1744 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1745 String constructorName = "a"; | |
1746 ConstructorElement constructor = | |
1747 ElementFactory.constructorElement2(classA, constructorName); | |
1748 classA.constructors = <ConstructorElement>[constructor]; | |
1749 ConstructorName name = AstFactory.constructorName( | |
1750 AstFactory.typeName(classA), constructorName); | |
1751 name.staticElement = constructor; | |
1752 InstanceCreationExpression creation = | |
1753 AstFactory.instanceCreationExpression(Keyword.NEW, name); | |
1754 _resolveNode(creation); | |
1755 expect(creation.staticElement, same(constructor)); | |
1756 _listener.assertNoErrors(); | |
1757 } | |
1758 | |
1759 void test_visitInstanceCreationExpression_unnamed() { | |
1760 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1761 String constructorName = null; | |
1762 ConstructorElement constructor = | |
1763 ElementFactory.constructorElement2(classA, constructorName); | |
1764 classA.constructors = <ConstructorElement>[constructor]; | |
1765 ConstructorName name = AstFactory.constructorName( | |
1766 AstFactory.typeName(classA), constructorName); | |
1767 name.staticElement = constructor; | |
1768 InstanceCreationExpression creation = | |
1769 AstFactory.instanceCreationExpression(Keyword.NEW, name); | |
1770 _resolveNode(creation); | |
1771 expect(creation.staticElement, same(constructor)); | |
1772 _listener.assertNoErrors(); | |
1773 } | |
1774 | |
1775 void test_visitInstanceCreationExpression_unnamed_namedParameter() { | |
1776 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1777 String constructorName = null; | |
1778 ConstructorElementImpl constructor = | |
1779 ElementFactory.constructorElement2(classA, constructorName); | |
1780 String parameterName = "a"; | |
1781 ParameterElement parameter = ElementFactory.namedParameter(parameterName); | |
1782 constructor.parameters = <ParameterElement>[parameter]; | |
1783 classA.constructors = <ConstructorElement>[constructor]; | |
1784 ConstructorName name = AstFactory.constructorName( | |
1785 AstFactory.typeName(classA), constructorName); | |
1786 name.staticElement = constructor; | |
1787 InstanceCreationExpression creation = AstFactory.instanceCreationExpression( | |
1788 Keyword.NEW, | |
1789 name, | |
1790 [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]); | |
1791 _resolveNode(creation); | |
1792 expect(creation.staticElement, same(constructor)); | |
1793 expect( | |
1794 (creation.argumentList.arguments[0] as NamedExpression) | |
1795 .name | |
1796 .label | |
1797 .staticElement, | |
1798 same(parameter)); | |
1799 _listener.assertNoErrors(); | |
1800 } | |
1801 | |
1802 void test_visitMethodInvocation() { | |
1803 InterfaceType numType = _typeProvider.numType; | |
1804 SimpleIdentifier left = AstFactory.identifier3("i"); | |
1805 left.staticType = numType; | |
1806 String methodName = "abs"; | |
1807 MethodInvocation invocation = AstFactory.methodInvocation(left, methodName); | |
1808 _resolveNode(invocation); | |
1809 expect(invocation.methodName.staticElement, | |
1810 same(getMethod(numType, methodName))); | |
1811 _listener.assertNoErrors(); | |
1812 } | |
1813 | |
1814 void test_visitMethodInvocation_namedParameter() { | |
1815 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1816 String methodName = "m"; | |
1817 String parameterName = "p"; | |
1818 MethodElementImpl method = ElementFactory.methodElement(methodName, null); | |
1819 ParameterElement parameter = ElementFactory.namedParameter(parameterName); | |
1820 method.parameters = <ParameterElement>[parameter]; | |
1821 classA.methods = <MethodElement>[method]; | |
1822 SimpleIdentifier left = AstFactory.identifier3("i"); | |
1823 left.staticType = classA.type; | |
1824 MethodInvocation invocation = AstFactory.methodInvocation(left, methodName, | |
1825 [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]); | |
1826 _resolveNode(invocation); | |
1827 expect(invocation.methodName.staticElement, same(method)); | |
1828 expect( | |
1829 (invocation.argumentList.arguments[0] as NamedExpression) | |
1830 .name | |
1831 .label | |
1832 .staticElement, | |
1833 same(parameter)); | |
1834 _listener.assertNoErrors(); | |
1835 } | |
1836 | |
1837 void test_visitPostfixExpression() { | |
1838 InterfaceType numType = _typeProvider.numType; | |
1839 SimpleIdentifier operand = AstFactory.identifier3("i"); | |
1840 operand.staticType = numType; | |
1841 PostfixExpression expression = | |
1842 AstFactory.postfixExpression(operand, TokenType.PLUS_PLUS); | |
1843 _resolveNode(expression); | |
1844 expect(expression.staticElement, getMethod(numType, "+")); | |
1845 _listener.assertNoErrors(); | |
1846 } | |
1847 | |
1848 void test_visitPrefixedIdentifier_dynamic() { | |
1849 DartType dynamicType = _typeProvider.dynamicType; | |
1850 SimpleIdentifier target = AstFactory.identifier3("a"); | |
1851 VariableElementImpl variable = ElementFactory.localVariableElement(target); | |
1852 variable.type = dynamicType; | |
1853 target.staticElement = variable; | |
1854 target.staticType = dynamicType; | |
1855 PrefixedIdentifier identifier = | |
1856 AstFactory.identifier(target, AstFactory.identifier3("b")); | |
1857 _resolveNode(identifier); | |
1858 expect(identifier.staticElement, isNull); | |
1859 expect(identifier.identifier.staticElement, isNull); | |
1860 _listener.assertNoErrors(); | |
1861 } | |
1862 | |
1863 void test_visitPrefixedIdentifier_nonDynamic() { | |
1864 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1865 String getterName = "b"; | |
1866 PropertyAccessorElement getter = | |
1867 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
1868 classA.accessors = <PropertyAccessorElement>[getter]; | |
1869 SimpleIdentifier target = AstFactory.identifier3("a"); | |
1870 VariableElementImpl variable = ElementFactory.localVariableElement(target); | |
1871 variable.type = classA.type; | |
1872 target.staticElement = variable; | |
1873 target.staticType = classA.type; | |
1874 PrefixedIdentifier identifier = | |
1875 AstFactory.identifier(target, AstFactory.identifier3(getterName)); | |
1876 _resolveNode(identifier); | |
1877 expect(identifier.staticElement, same(getter)); | |
1878 expect(identifier.identifier.staticElement, same(getter)); | |
1879 _listener.assertNoErrors(); | |
1880 } | |
1881 | |
1882 void test_visitPrefixedIdentifier_staticClassMember_getter() { | |
1883 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1884 // set accessors | |
1885 String propName = "b"; | |
1886 PropertyAccessorElement getter = | |
1887 ElementFactory.getterElement(propName, false, _typeProvider.intType); | |
1888 PropertyAccessorElement setter = | |
1889 ElementFactory.setterElement(propName, false, _typeProvider.intType); | |
1890 classA.accessors = <PropertyAccessorElement>[getter, setter]; | |
1891 // prepare "A.m" | |
1892 SimpleIdentifier target = AstFactory.identifier3("A"); | |
1893 target.staticElement = classA; | |
1894 target.staticType = classA.type; | |
1895 PrefixedIdentifier identifier = | |
1896 AstFactory.identifier(target, AstFactory.identifier3(propName)); | |
1897 // resolve | |
1898 _resolveNode(identifier); | |
1899 expect(identifier.staticElement, same(getter)); | |
1900 expect(identifier.identifier.staticElement, same(getter)); | |
1901 _listener.assertNoErrors(); | |
1902 } | |
1903 | |
1904 void test_visitPrefixedIdentifier_staticClassMember_method() { | |
1905 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1906 // set methods | |
1907 String propName = "m"; | |
1908 MethodElement method = | |
1909 ElementFactory.methodElement("m", _typeProvider.intType); | |
1910 classA.methods = <MethodElement>[method]; | |
1911 // prepare "A.m" | |
1912 SimpleIdentifier target = AstFactory.identifier3("A"); | |
1913 target.staticElement = classA; | |
1914 target.staticType = classA.type; | |
1915 PrefixedIdentifier identifier = | |
1916 AstFactory.identifier(target, AstFactory.identifier3(propName)); | |
1917 AstFactory.assignmentExpression( | |
1918 identifier, TokenType.EQ, AstFactory.nullLiteral()); | |
1919 // resolve | |
1920 _resolveNode(identifier); | |
1921 expect(identifier.staticElement, same(method)); | |
1922 expect(identifier.identifier.staticElement, same(method)); | |
1923 _listener.assertNoErrors(); | |
1924 } | |
1925 | |
1926 void test_visitPrefixedIdentifier_staticClassMember_setter() { | |
1927 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1928 // set accessors | |
1929 String propName = "b"; | |
1930 PropertyAccessorElement getter = | |
1931 ElementFactory.getterElement(propName, false, _typeProvider.intType); | |
1932 PropertyAccessorElement setter = | |
1933 ElementFactory.setterElement(propName, false, _typeProvider.intType); | |
1934 classA.accessors = <PropertyAccessorElement>[getter, setter]; | |
1935 // prepare "A.b = null" | |
1936 SimpleIdentifier target = AstFactory.identifier3("A"); | |
1937 target.staticElement = classA; | |
1938 target.staticType = classA.type; | |
1939 PrefixedIdentifier identifier = | |
1940 AstFactory.identifier(target, AstFactory.identifier3(propName)); | |
1941 AstFactory.assignmentExpression( | |
1942 identifier, TokenType.EQ, AstFactory.nullLiteral()); | |
1943 // resolve | |
1944 _resolveNode(identifier); | |
1945 expect(identifier.staticElement, same(setter)); | |
1946 expect(identifier.identifier.staticElement, same(setter)); | |
1947 _listener.assertNoErrors(); | |
1948 } | |
1949 | |
1950 void test_visitPrefixExpression() { | |
1951 InterfaceType numType = _typeProvider.numType; | |
1952 SimpleIdentifier operand = AstFactory.identifier3("i"); | |
1953 operand.staticType = numType; | |
1954 PrefixExpression expression = | |
1955 AstFactory.prefixExpression(TokenType.PLUS_PLUS, operand); | |
1956 _resolveNode(expression); | |
1957 expect(expression.staticElement, getMethod(numType, "+")); | |
1958 _listener.assertNoErrors(); | |
1959 } | |
1960 | |
1961 void test_visitPropertyAccess_getter_identifier() { | |
1962 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1963 String getterName = "b"; | |
1964 PropertyAccessorElement getter = | |
1965 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
1966 classA.accessors = <PropertyAccessorElement>[getter]; | |
1967 SimpleIdentifier target = AstFactory.identifier3("a"); | |
1968 target.staticType = classA.type; | |
1969 PropertyAccess access = AstFactory.propertyAccess2(target, getterName); | |
1970 _resolveNode(access); | |
1971 expect(access.propertyName.staticElement, same(getter)); | |
1972 _listener.assertNoErrors(); | |
1973 } | |
1974 | |
1975 void test_visitPropertyAccess_getter_super() { | |
1976 // | |
1977 // class A { | |
1978 // int get b; | |
1979 // } | |
1980 // class B { | |
1981 // ... super.m ... | |
1982 // } | |
1983 // | |
1984 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
1985 String getterName = "b"; | |
1986 PropertyAccessorElement getter = | |
1987 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
1988 classA.accessors = <PropertyAccessorElement>[getter]; | |
1989 SuperExpression target = AstFactory.superExpression(); | |
1990 target.staticType = ElementFactory.classElement("B", classA.type).type; | |
1991 PropertyAccess access = AstFactory.propertyAccess2(target, getterName); | |
1992 AstFactory.methodDeclaration2( | |
1993 null, | |
1994 null, | |
1995 null, | |
1996 null, | |
1997 AstFactory.identifier3("m"), | |
1998 AstFactory.formalParameterList(), | |
1999 AstFactory.expressionFunctionBody(access)); | |
2000 _resolveNode(access); | |
2001 expect(access.propertyName.staticElement, same(getter)); | |
2002 _listener.assertNoErrors(); | |
2003 } | |
2004 | |
2005 void test_visitPropertyAccess_setter_this() { | |
2006 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
2007 String setterName = "b"; | |
2008 PropertyAccessorElement setter = | |
2009 ElementFactory.setterElement(setterName, false, _typeProvider.intType); | |
2010 classA.accessors = <PropertyAccessorElement>[setter]; | |
2011 ThisExpression target = AstFactory.thisExpression(); | |
2012 target.staticType = classA.type; | |
2013 PropertyAccess access = AstFactory.propertyAccess2(target, setterName); | |
2014 AstFactory.assignmentExpression( | |
2015 access, TokenType.EQ, AstFactory.integer(0)); | |
2016 _resolveNode(access); | |
2017 expect(access.propertyName.staticElement, same(setter)); | |
2018 _listener.assertNoErrors(); | |
2019 } | |
2020 | |
2021 void test_visitSimpleIdentifier_classScope() { | |
2022 InterfaceType doubleType = _typeProvider.doubleType; | |
2023 String fieldName = "NAN"; | |
2024 SimpleIdentifier node = AstFactory.identifier3(fieldName); | |
2025 _resolveInClass(node, doubleType.element); | |
2026 expect(node.staticElement, getGetter(doubleType, fieldName)); | |
2027 _listener.assertNoErrors(); | |
2028 } | |
2029 | |
2030 void test_visitSimpleIdentifier_dynamic() { | |
2031 SimpleIdentifier node = AstFactory.identifier3("dynamic"); | |
2032 _resolveIdentifier(node); | |
2033 expect(node.staticElement, same(_typeProvider.dynamicType.element)); | |
2034 expect(node.staticType, same(_typeProvider.typeType)); | |
2035 _listener.assertNoErrors(); | |
2036 } | |
2037 | |
2038 void test_visitSimpleIdentifier_lexicalScope() { | |
2039 SimpleIdentifier node = AstFactory.identifier3("i"); | |
2040 VariableElementImpl element = ElementFactory.localVariableElement(node); | |
2041 expect(_resolveIdentifier(node, [element]), same(element)); | |
2042 _listener.assertNoErrors(); | |
2043 } | |
2044 | |
2045 void test_visitSimpleIdentifier_lexicalScope_field_setter() { | |
2046 InterfaceType intType = _typeProvider.intType; | |
2047 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
2048 String fieldName = "a"; | |
2049 FieldElement field = | |
2050 ElementFactory.fieldElement(fieldName, false, false, false, intType); | |
2051 classA.fields = <FieldElement>[field]; | |
2052 classA.accessors = <PropertyAccessorElement>[field.getter, field.setter]; | |
2053 SimpleIdentifier node = AstFactory.identifier3(fieldName); | |
2054 AstFactory.assignmentExpression(node, TokenType.EQ, AstFactory.integer(0)); | |
2055 _resolveInClass(node, classA); | |
2056 Element element = node.staticElement; | |
2057 EngineTestCase.assertInstanceOf((obj) => obj is PropertyAccessorElement, | |
2058 PropertyAccessorElement, element); | |
2059 expect((element as PropertyAccessorElement).isSetter, isTrue); | |
2060 _listener.assertNoErrors(); | |
2061 } | |
2062 | |
2063 void test_visitSuperConstructorInvocation() { | |
2064 ClassElementImpl superclass = ElementFactory.classElement2("A"); | |
2065 ConstructorElementImpl superConstructor = | |
2066 ElementFactory.constructorElement2(superclass, null); | |
2067 superclass.constructors = <ConstructorElement>[superConstructor]; | |
2068 ClassElementImpl subclass = | |
2069 ElementFactory.classElement("B", superclass.type); | |
2070 ConstructorElementImpl subConstructor = | |
2071 ElementFactory.constructorElement2(subclass, null); | |
2072 subclass.constructors = <ConstructorElement>[subConstructor]; | |
2073 SuperConstructorInvocation invocation = | |
2074 AstFactory.superConstructorInvocation(); | |
2075 _resolveInClass(invocation, subclass); | |
2076 expect(invocation.staticElement, superConstructor); | |
2077 _listener.assertNoErrors(); | |
2078 } | |
2079 | |
2080 void test_visitSuperConstructorInvocation_namedParameter() { | |
2081 ClassElementImpl superclass = ElementFactory.classElement2("A"); | |
2082 ConstructorElementImpl superConstructor = | |
2083 ElementFactory.constructorElement2(superclass, null); | |
2084 String parameterName = "p"; | |
2085 ParameterElement parameter = ElementFactory.namedParameter(parameterName); | |
2086 superConstructor.parameters = <ParameterElement>[parameter]; | |
2087 superclass.constructors = <ConstructorElement>[superConstructor]; | |
2088 ClassElementImpl subclass = | |
2089 ElementFactory.classElement("B", superclass.type); | |
2090 ConstructorElementImpl subConstructor = | |
2091 ElementFactory.constructorElement2(subclass, null); | |
2092 subclass.constructors = <ConstructorElement>[subConstructor]; | |
2093 SuperConstructorInvocation invocation = AstFactory | |
2094 .superConstructorInvocation([ | |
2095 AstFactory.namedExpression2(parameterName, AstFactory.integer(0)) | |
2096 ]); | |
2097 _resolveInClass(invocation, subclass); | |
2098 expect(invocation.staticElement, superConstructor); | |
2099 expect( | |
2100 (invocation.argumentList.arguments[0] as NamedExpression) | |
2101 .name | |
2102 .label | |
2103 .staticElement, | |
2104 same(parameter)); | |
2105 _listener.assertNoErrors(); | |
2106 } | |
2107 | |
2108 /** | |
2109 * Create the resolver used by the tests. | |
2110 * | |
2111 * @return the resolver that was created | |
2112 */ | |
2113 ElementResolver _createResolver() { | |
2114 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); | |
2115 FileBasedSource source = | |
2116 new FileBasedSource(FileUtilities2.createFile("/test.dart")); | |
2117 CompilationUnitElementImpl definingCompilationUnit = | |
2118 new CompilationUnitElementImpl("test.dart"); | |
2119 definingCompilationUnit.librarySource = | |
2120 definingCompilationUnit.source = source; | |
2121 _definingLibrary = ElementFactory.library(context, "test"); | |
2122 _definingLibrary.definingCompilationUnit = definingCompilationUnit; | |
2123 _visitor = new ResolverVisitor( | |
2124 _definingLibrary, source, _typeProvider, _listener, | |
2125 nameScope: new LibraryScope(_definingLibrary, _listener)); | |
2126 try { | |
2127 return _visitor.elementResolver; | |
2128 } catch (exception) { | |
2129 throw new IllegalArgumentException( | |
2130 "Could not create resolver", exception); | |
2131 } | |
2132 } | |
2133 | |
2134 /** | |
2135 * Return the element associated with the label of [statement] after the | |
2136 * resolver has resolved it. [labelElement] is the label element to be | |
2137 * defined in the statement's label scope, and [labelTarget] is the statement | |
2138 * the label resolves to. | |
2139 */ | |
2140 Element _resolveBreak(BreakStatement statement, LabelElementImpl labelElement, | |
2141 Statement labelTarget) { | |
2142 _resolveStatement(statement, labelElement, labelTarget); | |
2143 return statement.label.staticElement; | |
2144 } | |
2145 | |
2146 /** | |
2147 * Return the element associated with the label [statement] after the | |
2148 * resolver has resolved it. [labelElement] is the label element to be | |
2149 * defined in the statement's label scope, and [labelTarget] is the AST node | |
2150 * the label resolves to. | |
2151 * | |
2152 * @param statement the statement to be resolved | |
2153 * @param labelElement the label element to be defined in the statement's labe
l scope | |
2154 * @return the element to which the statement's label was resolved | |
2155 */ | |
2156 Element _resolveContinue(ContinueStatement statement, | |
2157 LabelElementImpl labelElement, AstNode labelTarget) { | |
2158 _resolveStatement(statement, labelElement, labelTarget); | |
2159 return statement.label.staticElement; | |
2160 } | |
2161 | |
2162 /** | |
2163 * Return the element associated with the given identifier after the resolver
has resolved the | |
2164 * identifier. | |
2165 * | |
2166 * @param node the expression to be resolved | |
2167 * @param definedElements the elements that are to be defined in the scope in
which the element is | |
2168 * being resolved | |
2169 * @return the element to which the expression was resolved | |
2170 */ | |
2171 Element _resolveIdentifier(Identifier node, [List<Element> definedElements]) { | |
2172 _resolveNode(node, definedElements); | |
2173 return node.staticElement; | |
2174 } | |
2175 | |
2176 /** | |
2177 * Return the element associated with the given identifier after the resolver
has resolved the | |
2178 * identifier. | |
2179 * | |
2180 * @param node the expression to be resolved | |
2181 * @param enclosingClass the element representing the class enclosing the iden
tifier | |
2182 * @return the element to which the expression was resolved | |
2183 */ | |
2184 void _resolveInClass(AstNode node, ClassElement enclosingClass) { | |
2185 try { | |
2186 Scope outerScope = _visitor.nameScope; | |
2187 try { | |
2188 _visitor.enclosingClass = enclosingClass; | |
2189 EnclosedScope innerScope = new ClassScope( | |
2190 new TypeParameterScope(outerScope, enclosingClass), enclosingClass); | |
2191 _visitor.nameScope = innerScope; | |
2192 node.accept(_resolver); | |
2193 } finally { | |
2194 _visitor.enclosingClass = null; | |
2195 _visitor.nameScope = outerScope; | |
2196 } | |
2197 } catch (exception) { | |
2198 throw new IllegalArgumentException("Could not resolve node", exception); | |
2199 } | |
2200 } | |
2201 | |
2202 /** | |
2203 * Return the element associated with the given expression after the resolver
has resolved the | |
2204 * expression. | |
2205 * | |
2206 * @param node the expression to be resolved | |
2207 * @param definedElements the elements that are to be defined in the scope in
which the element is | |
2208 * being resolved | |
2209 * @return the element to which the expression was resolved | |
2210 */ | |
2211 Element _resolveIndexExpression(IndexExpression node, | |
2212 [List<Element> definedElements]) { | |
2213 _resolveNode(node, definedElements); | |
2214 return node.staticElement; | |
2215 } | |
2216 | |
2217 /** | |
2218 * Return the element associated with the given identifier after the resolver
has resolved the | |
2219 * identifier. | |
2220 * | |
2221 * @param node the expression to be resolved | |
2222 * @param definedElements the elements that are to be defined in the scope in
which the element is | |
2223 * being resolved | |
2224 * @return the element to which the expression was resolved | |
2225 */ | |
2226 void _resolveNode(AstNode node, [List<Element> definedElements]) { | |
2227 try { | |
2228 Scope outerScope = _visitor.nameScope; | |
2229 try { | |
2230 EnclosedScope innerScope = new EnclosedScope(outerScope); | |
2231 if (definedElements != null) { | |
2232 for (Element element in definedElements) { | |
2233 innerScope.define(element); | |
2234 } | |
2235 } | |
2236 _visitor.nameScope = innerScope; | |
2237 node.accept(_resolver); | |
2238 } finally { | |
2239 _visitor.nameScope = outerScope; | |
2240 } | |
2241 } catch (exception) { | |
2242 throw new IllegalArgumentException("Could not resolve node", exception); | |
2243 } | |
2244 } | |
2245 | |
2246 /** | |
2247 * Return the element associated with the label of the given statement after t
he resolver has | |
2248 * resolved the statement. | |
2249 * | |
2250 * @param statement the statement to be resolved | |
2251 * @param labelElement the label element to be defined in the statement's labe
l scope | |
2252 * @return the element to which the statement's label was resolved | |
2253 */ | |
2254 void _resolveStatement( | |
2255 Statement statement, LabelElementImpl labelElement, AstNode labelTarget) { | |
2256 try { | |
2257 LabelScope outerScope = _visitor.labelScope; | |
2258 try { | |
2259 LabelScope innerScope; | |
2260 if (labelElement == null) { | |
2261 innerScope = outerScope; | |
2262 } else { | |
2263 innerScope = new LabelScope( | |
2264 outerScope, labelElement.name, labelTarget, labelElement); | |
2265 } | |
2266 _visitor.labelScope = innerScope; | |
2267 statement.accept(_resolver); | |
2268 } finally { | |
2269 _visitor.labelScope = outerScope; | |
2270 } | |
2271 } catch (exception) { | |
2272 throw new IllegalArgumentException("Could not resolve node", exception); | |
2273 } | |
2274 } | |
2275 } | |
2276 | |
2277 @reflectiveTest | |
2278 class EnclosedScopeTest extends ResolverTestCase { | 194 class EnclosedScopeTest extends ResolverTestCase { |
2279 void test_define_duplicate() { | 195 void test_define_duplicate() { |
2280 GatheringErrorListener listener = new GatheringErrorListener(); | 196 GatheringErrorListener listener = new GatheringErrorListener(); |
2281 Scope rootScope = | 197 Scope rootScope = |
2282 new Scope_EnclosedScopeTest_test_define_duplicate(listener); | 198 new Scope_EnclosedScopeTest_test_define_duplicate(listener); |
2283 EnclosedScope scope = new EnclosedScope(rootScope); | 199 EnclosedScope scope = new EnclosedScope(rootScope); |
2284 VariableElement element1 = | 200 VariableElement element1 = |
2285 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); | 201 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
2286 VariableElement element2 = | 202 VariableElement element2 = |
2287 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); | 203 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2365 expect(functions, hasLength(1)); | 281 expect(functions, hasLength(1)); |
2366 expect(functions[0].enclosingElement, constructor); | 282 expect(functions[0].enclosingElement, constructor); |
2367 assertErrors(source, [ParserErrorCode.GETTER_IN_FUNCTION]); | 283 assertErrors(source, [ParserErrorCode.GETTER_IN_FUNCTION]); |
2368 } | 284 } |
2369 } | 285 } |
2370 | 286 |
2371 /** | 287 /** |
2372 * Tests for generic method and function resolution that do not use strong mode. | 288 * Tests for generic method and function resolution that do not use strong mode. |
2373 */ | 289 */ |
2374 @reflectiveTest | 290 @reflectiveTest |
2375 class GenericMethodResolverTest extends _StaticTypeAnalyzer2TestShared { | 291 class GenericMethodResolverTest extends StaticTypeAnalyzer2TestShared { |
2376 void setUp() { | 292 void setUp() { |
2377 super.setUp(); | 293 super.setUp(); |
2378 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | 294 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
2379 options.enableGenericMethods = true; | 295 options.enableGenericMethods = true; |
2380 resetWithOptions(options); | 296 resetWithOptions(options); |
2381 } | 297 } |
2382 | 298 |
2383 void test_genericMethod_propagatedType_promotion() { | 299 void test_genericMethod_propagatedType_promotion() { |
2384 // Regression test for: | 300 // Regression test for: |
2385 // https://github.com/dart-lang/sdk/issues/25340 | 301 // https://github.com/dart-lang/sdk/issues/25340 |
2386 // | 302 // |
2387 // Note, after https://github.com/dart-lang/sdk/issues/25486 the original | 303 // Note, after https://github.com/dart-lang/sdk/issues/25486 the original |
2388 // strong mode example won't work, as we now compute a static type and | 304 // strong mode example won't work, as we now compute a static type and |
2389 // therefore discard the propagated type. | 305 // therefore discard the propagated type. |
2390 // | 306 // |
2391 // So this test does not use strong mode. | 307 // So this test does not use strong mode. |
2392 _resolveTestUnit(r''' | 308 resolveTestUnit(r''' |
2393 abstract class Iter { | 309 abstract class Iter { |
2394 List<S> map<S>(S f(x)); | 310 List<S> map<S>(S f(x)); |
2395 } | 311 } |
2396 class C {} | 312 class C {} |
2397 C toSpan(dynamic element) { | 313 C toSpan(dynamic element) { |
2398 if (element is Iter) { | 314 if (element is Iter) { |
2399 var y = element.map(toSpan); | 315 var y = element.map(toSpan); |
2400 } | 316 } |
2401 return null; | 317 return null; |
2402 }'''); | 318 }'''); |
2403 _expectIdentifierType('y = ', 'dynamic', 'List<dynamic>'); | 319 expectIdentifierType('y = ', 'dynamic', 'List<dynamic>'); |
2404 } | |
2405 } | |
2406 | |
2407 @reflectiveTest | |
2408 class HintCodeTest extends ResolverTestCase { | |
2409 void fail_deadCode_statementAfterRehrow() { | |
2410 Source source = addSource(r''' | |
2411 f() { | |
2412 try { | |
2413 var one = 1; | |
2414 } catch (e) { | |
2415 rethrow; | |
2416 var two = 2; | |
2417 } | |
2418 }'''); | |
2419 computeLibrarySourceErrors(source); | |
2420 assertErrors(source, [HintCode.DEAD_CODE]); | |
2421 verify([source]); | |
2422 } | |
2423 | |
2424 void fail_deadCode_statementAfterThrow() { | |
2425 Source source = addSource(r''' | |
2426 f() { | |
2427 var one = 1; | |
2428 throw 'Stop here'; | |
2429 var two = 2; | |
2430 }'''); | |
2431 computeLibrarySourceErrors(source); | |
2432 assertErrors(source, [HintCode.DEAD_CODE]); | |
2433 verify([source]); | |
2434 } | |
2435 | |
2436 void fail_isInt() { | |
2437 Source source = addSource("var v = 1 is int;"); | |
2438 computeLibrarySourceErrors(source); | |
2439 assertErrors(source, [HintCode.IS_INT]); | |
2440 verify([source]); | |
2441 } | |
2442 | |
2443 void fail_isNotInt() { | |
2444 Source source = addSource("var v = 1 is! int;"); | |
2445 computeLibrarySourceErrors(source); | |
2446 assertErrors(source, [HintCode.IS_NOT_INT]); | |
2447 verify([source]); | |
2448 } | |
2449 | |
2450 void fail_overrideEqualsButNotHashCode() { | |
2451 Source source = addSource(r''' | |
2452 class A { | |
2453 bool operator ==(x) {} | |
2454 }'''); | |
2455 computeLibrarySourceErrors(source); | |
2456 assertErrors(source, [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]); | |
2457 verify([source]); | |
2458 } | |
2459 | |
2460 void fail_unusedImport_as_equalPrefixes() { | |
2461 // See todo at ImportsVerifier.prefixElementMap. | |
2462 Source source = addSource(r''' | |
2463 library L; | |
2464 import 'lib1.dart' as one; | |
2465 import 'lib2.dart' as one; | |
2466 one.A a;'''); | |
2467 Source source2 = addNamedSource( | |
2468 "/lib1.dart", | |
2469 r''' | |
2470 library lib1; | |
2471 class A {}'''); | |
2472 Source source3 = addNamedSource( | |
2473 "/lib2.dart", | |
2474 r''' | |
2475 library lib2; | |
2476 class B {}'''); | |
2477 computeLibrarySourceErrors(source); | |
2478 assertErrors(source, [HintCode.UNUSED_IMPORT]); | |
2479 assertNoErrors(source2); | |
2480 assertNoErrors(source3); | |
2481 verify([source, source2, source3]); | |
2482 } | |
2483 | |
2484 @override | |
2485 void reset() { | |
2486 analysisContext2 = AnalysisContextFactory.contextWithCoreAndPackages({ | |
2487 'package:meta/meta.dart': r''' | |
2488 library meta; | |
2489 | |
2490 const _Factory factory = const _Factory(); | |
2491 const _Literal literal = const _Literal(); | |
2492 const _MustCallSuper mustCallSuper = const _MustCallSuper(); | |
2493 const _Override override = const _Override(); | |
2494 const _Protected protected = const _Protected(); | |
2495 const _Required required = const _Required(); | |
2496 | |
2497 class _Factory { | |
2498 const _Factory(); | |
2499 } | |
2500 class _Literal { | |
2501 const _Literal(); | |
2502 } | |
2503 class _MustCallSuper { | |
2504 const _MustCallSuper(); | |
2505 } | |
2506 class _Override { | |
2507 const _Override(); | |
2508 } | |
2509 class _Protected { | |
2510 const _Protected(); | |
2511 } | |
2512 class _Required { | |
2513 final String reason; | |
2514 const _Required([this.reason])); | |
2515 } | |
2516 ''' | |
2517 }); | |
2518 } | |
2519 | |
2520 void test_argumentTypeNotAssignable_functionType() { | |
2521 Source source = addSource(r''' | |
2522 m() { | |
2523 var a = new A(); | |
2524 a.n(() => 0); | |
2525 } | |
2526 class A { | |
2527 n(void f(int i)) {} | |
2528 }'''); | |
2529 computeLibrarySourceErrors(source); | |
2530 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); | |
2531 verify([source]); | |
2532 } | |
2533 | |
2534 void test_argumentTypeNotAssignable_message() { | |
2535 // The implementation of HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE assumes that | |
2536 // StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE has the same message. | |
2537 expect(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE.message, | |
2538 HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE.message); | |
2539 } | |
2540 | |
2541 void test_argumentTypeNotAssignable_type() { | |
2542 Source source = addSource(r''' | |
2543 m() { | |
2544 var i = ''; | |
2545 n(i); | |
2546 } | |
2547 n(int i) {}'''); | |
2548 computeLibrarySourceErrors(source); | |
2549 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); | |
2550 verify([source]); | |
2551 } | |
2552 | |
2553 void test_canBeNullAfterNullAware_false_methodInvocation() { | |
2554 Source source = addSource(r''' | |
2555 m(x) { | |
2556 x?.a()?.b(); | |
2557 } | |
2558 '''); | |
2559 computeLibrarySourceErrors(source); | |
2560 assertNoErrors(source); | |
2561 verify([source]); | |
2562 } | |
2563 | |
2564 void test_canBeNullAfterNullAware_false_propertyAccess() { | |
2565 Source source = addSource(r''' | |
2566 m(x) { | |
2567 x?.a?.b; | |
2568 } | |
2569 '''); | |
2570 computeLibrarySourceErrors(source); | |
2571 assertNoErrors(source); | |
2572 verify([source]); | |
2573 } | |
2574 | |
2575 void test_canBeNullAfterNullAware_methodInvocation() { | |
2576 Source source = addSource(r''' | |
2577 m(x) { | |
2578 x?.a.b(); | |
2579 } | |
2580 '''); | |
2581 computeLibrarySourceErrors(source); | |
2582 assertErrors(source, [HintCode.CAN_BE_NULL_AFTER_NULL_AWARE]); | |
2583 verify([source]); | |
2584 } | |
2585 | |
2586 void test_canBeNullAfterNullAware_parenthesized() { | |
2587 Source source = addSource(r''' | |
2588 m(x) { | |
2589 (x?.a).b; | |
2590 } | |
2591 '''); | |
2592 computeLibrarySourceErrors(source); | |
2593 assertErrors(source, [HintCode.CAN_BE_NULL_AFTER_NULL_AWARE]); | |
2594 verify([source]); | |
2595 } | |
2596 | |
2597 void test_canBeNullAfterNullAware_propertyAccess() { | |
2598 Source source = addSource(r''' | |
2599 m(x) { | |
2600 x?.a.b; | |
2601 } | |
2602 '''); | |
2603 computeLibrarySourceErrors(source); | |
2604 assertErrors(source, [HintCode.CAN_BE_NULL_AFTER_NULL_AWARE]); | |
2605 verify([source]); | |
2606 } | |
2607 | |
2608 void test_deadCode_deadBlock_conditionalElse() { | |
2609 Source source = addSource(r''' | |
2610 f() { | |
2611 true ? 1 : 2; | |
2612 }'''); | |
2613 computeLibrarySourceErrors(source); | |
2614 assertErrors(source, [HintCode.DEAD_CODE]); | |
2615 verify([source]); | |
2616 } | |
2617 | |
2618 void test_deadCode_deadBlock_conditionalElse_nested() { | |
2619 // test that a dead else-statement can't generate additional violations | |
2620 Source source = addSource(r''' | |
2621 f() { | |
2622 true ? true : false && false; | |
2623 }'''); | |
2624 computeLibrarySourceErrors(source); | |
2625 assertErrors(source, [HintCode.DEAD_CODE]); | |
2626 verify([source]); | |
2627 } | |
2628 | |
2629 void test_deadCode_deadBlock_conditionalIf() { | |
2630 Source source = addSource(r''' | |
2631 f() { | |
2632 false ? 1 : 2; | |
2633 }'''); | |
2634 computeLibrarySourceErrors(source); | |
2635 assertErrors(source, [HintCode.DEAD_CODE]); | |
2636 verify([source]); | |
2637 } | |
2638 | |
2639 void test_deadCode_deadBlock_conditionalIf_nested() { | |
2640 // test that a dead then-statement can't generate additional violations | |
2641 Source source = addSource(r''' | |
2642 f() { | |
2643 false ? false && false : true; | |
2644 }'''); | |
2645 computeLibrarySourceErrors(source); | |
2646 assertErrors(source, [HintCode.DEAD_CODE]); | |
2647 verify([source]); | |
2648 } | |
2649 | |
2650 void test_deadCode_deadBlock_else() { | |
2651 Source source = addSource(r''' | |
2652 f() { | |
2653 if(true) {} else {} | |
2654 }'''); | |
2655 computeLibrarySourceErrors(source); | |
2656 assertErrors(source, [HintCode.DEAD_CODE]); | |
2657 verify([source]); | |
2658 } | |
2659 | |
2660 void test_deadCode_deadBlock_else_nested() { | |
2661 // test that a dead else-statement can't generate additional violations | |
2662 Source source = addSource(r''' | |
2663 f() { | |
2664 if(true) {} else {if (false) {}} | |
2665 }'''); | |
2666 computeLibrarySourceErrors(source); | |
2667 assertErrors(source, [HintCode.DEAD_CODE]); | |
2668 verify([source]); | |
2669 } | |
2670 | |
2671 void test_deadCode_deadBlock_if() { | |
2672 Source source = addSource(r''' | |
2673 f() { | |
2674 if(false) {} | |
2675 }'''); | |
2676 computeLibrarySourceErrors(source); | |
2677 assertErrors(source, [HintCode.DEAD_CODE]); | |
2678 verify([source]); | |
2679 } | |
2680 | |
2681 void test_deadCode_deadBlock_if_nested() { | |
2682 // test that a dead then-statement can't generate additional violations | |
2683 Source source = addSource(r''' | |
2684 f() { | |
2685 if(false) {if(false) {}} | |
2686 }'''); | |
2687 computeLibrarySourceErrors(source); | |
2688 assertErrors(source, [HintCode.DEAD_CODE]); | |
2689 verify([source]); | |
2690 } | |
2691 | |
2692 void test_deadCode_deadBlock_while() { | |
2693 Source source = addSource(r''' | |
2694 f() { | |
2695 while(false) {} | |
2696 }'''); | |
2697 computeLibrarySourceErrors(source); | |
2698 assertErrors(source, [HintCode.DEAD_CODE]); | |
2699 verify([source]); | |
2700 } | |
2701 | |
2702 void test_deadCode_deadBlock_while_nested() { | |
2703 // test that a dead while body can't generate additional violations | |
2704 Source source = addSource(r''' | |
2705 f() { | |
2706 while(false) {if(false) {}} | |
2707 }'''); | |
2708 computeLibrarySourceErrors(source); | |
2709 assertErrors(source, [HintCode.DEAD_CODE]); | |
2710 verify([source]); | |
2711 } | |
2712 | |
2713 void test_deadCode_deadCatch_catchFollowingCatch() { | |
2714 Source source = addSource(r''' | |
2715 class A {} | |
2716 f() { | |
2717 try {} catch (e) {} catch (e) {} | |
2718 }'''); | |
2719 computeLibrarySourceErrors(source); | |
2720 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); | |
2721 verify([source]); | |
2722 } | |
2723 | |
2724 void test_deadCode_deadCatch_catchFollowingCatch_nested() { | |
2725 // test that a dead catch clause can't generate additional violations | |
2726 Source source = addSource(r''' | |
2727 class A {} | |
2728 f() { | |
2729 try {} catch (e) {} catch (e) {if(false) {}} | |
2730 }'''); | |
2731 computeLibrarySourceErrors(source); | |
2732 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); | |
2733 verify([source]); | |
2734 } | |
2735 | |
2736 void test_deadCode_deadCatch_catchFollowingCatch_object() { | |
2737 Source source = addSource(r''' | |
2738 f() { | |
2739 try {} on Object catch (e) {} catch (e) {} | |
2740 }'''); | |
2741 computeLibrarySourceErrors(source); | |
2742 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); | |
2743 verify([source]); | |
2744 } | |
2745 | |
2746 void test_deadCode_deadCatch_catchFollowingCatch_object_nested() { | |
2747 // test that a dead catch clause can't generate additional violations | |
2748 Source source = addSource(r''' | |
2749 f() { | |
2750 try {} on Object catch (e) {} catch (e) {if(false) {}} | |
2751 }'''); | |
2752 computeLibrarySourceErrors(source); | |
2753 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); | |
2754 verify([source]); | |
2755 } | |
2756 | |
2757 void test_deadCode_deadCatch_onCatchSubtype() { | |
2758 Source source = addSource(r''' | |
2759 class A {} | |
2760 class B extends A {} | |
2761 f() { | |
2762 try {} on A catch (e) {} on B catch (e) {} | |
2763 }'''); | |
2764 computeLibrarySourceErrors(source); | |
2765 assertErrors(source, [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]); | |
2766 verify([source]); | |
2767 } | |
2768 | |
2769 void test_deadCode_deadCatch_onCatchSubtype_nested() { | |
2770 // test that a dead catch clause can't generate additional violations | |
2771 Source source = addSource(r''' | |
2772 class A {} | |
2773 class B extends A {} | |
2774 f() { | |
2775 try {} on A catch (e) {} on B catch (e) {if(false) {}} | |
2776 }'''); | |
2777 computeLibrarySourceErrors(source); | |
2778 assertErrors(source, [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]); | |
2779 verify([source]); | |
2780 } | |
2781 | |
2782 void test_deadCode_deadOperandLHS_and() { | |
2783 Source source = addSource(r''' | |
2784 f() { | |
2785 bool b = false && false; | |
2786 }'''); | |
2787 computeLibrarySourceErrors(source); | |
2788 assertErrors(source, [HintCode.DEAD_CODE]); | |
2789 verify([source]); | |
2790 } | |
2791 | |
2792 void test_deadCode_deadOperandLHS_and_nested() { | |
2793 Source source = addSource(r''' | |
2794 f() { | |
2795 bool b = false && (false && false); | |
2796 }'''); | |
2797 computeLibrarySourceErrors(source); | |
2798 assertErrors(source, [HintCode.DEAD_CODE]); | |
2799 verify([source]); | |
2800 } | |
2801 | |
2802 void test_deadCode_deadOperandLHS_or() { | |
2803 Source source = addSource(r''' | |
2804 f() { | |
2805 bool b = true || true; | |
2806 }'''); | |
2807 computeLibrarySourceErrors(source); | |
2808 assertErrors(source, [HintCode.DEAD_CODE]); | |
2809 verify([source]); | |
2810 } | |
2811 | |
2812 void test_deadCode_deadOperandLHS_or_nested() { | |
2813 Source source = addSource(r''' | |
2814 f() { | |
2815 bool b = true || (false && false); | |
2816 }'''); | |
2817 computeLibrarySourceErrors(source); | |
2818 assertErrors(source, [HintCode.DEAD_CODE]); | |
2819 verify([source]); | |
2820 } | |
2821 | |
2822 void test_deadCode_statementAfterBreak_inDefaultCase() { | |
2823 Source source = addSource(r''' | |
2824 f(v) { | |
2825 switch(v) { | |
2826 case 1: | |
2827 default: | |
2828 break; | |
2829 var a; | |
2830 } | |
2831 }'''); | |
2832 computeLibrarySourceErrors(source); | |
2833 assertErrors(source, [HintCode.DEAD_CODE]); | |
2834 verify([source]); | |
2835 } | |
2836 | |
2837 void test_deadCode_statementAfterBreak_inForEachStatement() { | |
2838 Source source = addSource(r''' | |
2839 f() { | |
2840 var list; | |
2841 for(var l in list) { | |
2842 break; | |
2843 var a; | |
2844 } | |
2845 }'''); | |
2846 computeLibrarySourceErrors(source); | |
2847 assertErrors(source, [HintCode.DEAD_CODE]); | |
2848 verify([source]); | |
2849 } | |
2850 | |
2851 void test_deadCode_statementAfterBreak_inForStatement() { | |
2852 Source source = addSource(r''' | |
2853 f() { | |
2854 for(;;) { | |
2855 break; | |
2856 var a; | |
2857 } | |
2858 }'''); | |
2859 computeLibrarySourceErrors(source); | |
2860 assertErrors(source, [HintCode.DEAD_CODE]); | |
2861 verify([source]); | |
2862 } | |
2863 | |
2864 void test_deadCode_statementAfterBreak_inSwitchCase() { | |
2865 Source source = addSource(r''' | |
2866 f(v) { | |
2867 switch(v) { | |
2868 case 1: | |
2869 break; | |
2870 var a; | |
2871 } | |
2872 }'''); | |
2873 computeLibrarySourceErrors(source); | |
2874 assertErrors(source, [HintCode.DEAD_CODE]); | |
2875 verify([source]); | |
2876 } | |
2877 | |
2878 void test_deadCode_statementAfterBreak_inWhileStatement() { | |
2879 Source source = addSource(r''' | |
2880 f(v) { | |
2881 while(v) { | |
2882 break; | |
2883 var a; | |
2884 } | |
2885 }'''); | |
2886 computeLibrarySourceErrors(source); | |
2887 assertErrors(source, [HintCode.DEAD_CODE]); | |
2888 verify([source]); | |
2889 } | |
2890 | |
2891 void test_deadCode_statementAfterContinue_inForEachStatement() { | |
2892 Source source = addSource(r''' | |
2893 f() { | |
2894 var list; | |
2895 for(var l in list) { | |
2896 continue; | |
2897 var a; | |
2898 } | |
2899 }'''); | |
2900 computeLibrarySourceErrors(source); | |
2901 assertErrors(source, [HintCode.DEAD_CODE]); | |
2902 verify([source]); | |
2903 } | |
2904 | |
2905 void test_deadCode_statementAfterContinue_inForStatement() { | |
2906 Source source = addSource(r''' | |
2907 f() { | |
2908 for(;;) { | |
2909 continue; | |
2910 var a; | |
2911 } | |
2912 }'''); | |
2913 computeLibrarySourceErrors(source); | |
2914 assertErrors(source, [HintCode.DEAD_CODE]); | |
2915 verify([source]); | |
2916 } | |
2917 | |
2918 void test_deadCode_statementAfterContinue_inWhileStatement() { | |
2919 Source source = addSource(r''' | |
2920 f(v) { | |
2921 while(v) { | |
2922 continue; | |
2923 var a; | |
2924 } | |
2925 }'''); | |
2926 computeLibrarySourceErrors(source); | |
2927 assertErrors(source, [HintCode.DEAD_CODE]); | |
2928 verify([source]); | |
2929 } | |
2930 | |
2931 void test_deadCode_statementAfterReturn_function() { | |
2932 Source source = addSource(r''' | |
2933 f() { | |
2934 var one = 1; | |
2935 return; | |
2936 var two = 2; | |
2937 }'''); | |
2938 computeLibrarySourceErrors(source); | |
2939 assertErrors(source, [HintCode.DEAD_CODE]); | |
2940 verify([source]); | |
2941 } | |
2942 | |
2943 void test_deadCode_statementAfterReturn_ifStatement() { | |
2944 Source source = addSource(r''' | |
2945 f(bool b) { | |
2946 if(b) { | |
2947 var one = 1; | |
2948 return; | |
2949 var two = 2; | |
2950 } | |
2951 }'''); | |
2952 computeLibrarySourceErrors(source); | |
2953 assertErrors(source, [HintCode.DEAD_CODE]); | |
2954 verify([source]); | |
2955 } | |
2956 | |
2957 void test_deadCode_statementAfterReturn_method() { | |
2958 Source source = addSource(r''' | |
2959 class A { | |
2960 m() { | |
2961 var one = 1; | |
2962 return; | |
2963 var two = 2; | |
2964 } | |
2965 }'''); | |
2966 computeLibrarySourceErrors(source); | |
2967 assertErrors(source, [HintCode.DEAD_CODE]); | |
2968 verify([source]); | |
2969 } | |
2970 | |
2971 void test_deadCode_statementAfterReturn_nested() { | |
2972 Source source = addSource(r''' | |
2973 f() { | |
2974 var one = 1; | |
2975 return; | |
2976 if(false) {} | |
2977 }'''); | |
2978 computeLibrarySourceErrors(source); | |
2979 assertErrors(source, [HintCode.DEAD_CODE]); | |
2980 verify([source]); | |
2981 } | |
2982 | |
2983 void test_deadCode_statementAfterReturn_twoReturns() { | |
2984 Source source = addSource(r''' | |
2985 f() { | |
2986 var one = 1; | |
2987 return; | |
2988 var two = 2; | |
2989 return; | |
2990 var three = 3; | |
2991 }'''); | |
2992 computeLibrarySourceErrors(source); | |
2993 assertErrors(source, [HintCode.DEAD_CODE]); | |
2994 verify([source]); | |
2995 } | |
2996 | |
2997 void test_deprecatedAnnotationUse_assignment() { | |
2998 Source source = addSource(r''' | |
2999 class A { | |
3000 @deprecated | |
3001 A operator+(A a) { return a; } | |
3002 } | |
3003 f(A a) { | |
3004 A b; | |
3005 a += b; | |
3006 }'''); | |
3007 computeLibrarySourceErrors(source); | |
3008 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3009 verify([source]); | |
3010 } | |
3011 | |
3012 void test_deprecatedAnnotationUse_Deprecated() { | |
3013 Source source = addSource(r''' | |
3014 class A { | |
3015 @Deprecated('0.9') | |
3016 m() {} | |
3017 n() {m();} | |
3018 }'''); | |
3019 computeLibrarySourceErrors(source); | |
3020 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3021 verify([source]); | |
3022 } | |
3023 | |
3024 void test_deprecatedAnnotationUse_deprecated() { | |
3025 Source source = addSource(r''' | |
3026 class A { | |
3027 @deprecated | |
3028 m() {} | |
3029 n() {m();} | |
3030 }'''); | |
3031 computeLibrarySourceErrors(source); | |
3032 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3033 verify([source]); | |
3034 } | |
3035 | |
3036 void test_deprecatedAnnotationUse_export() { | |
3037 Source source = addSource("export 'deprecated_library.dart';"); | |
3038 addNamedSource( | |
3039 "/deprecated_library.dart", | |
3040 r''' | |
3041 @deprecated | |
3042 library deprecated_library; | |
3043 class A {}'''); | |
3044 computeLibrarySourceErrors(source); | |
3045 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3046 verify([source]); | |
3047 } | |
3048 | |
3049 void test_deprecatedAnnotationUse_getter() { | |
3050 Source source = addSource(r''' | |
3051 class A { | |
3052 @deprecated | |
3053 get m => 1; | |
3054 } | |
3055 f(A a) { | |
3056 return a.m; | |
3057 }'''); | |
3058 computeLibrarySourceErrors(source); | |
3059 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3060 verify([source]); | |
3061 } | |
3062 | |
3063 void test_deprecatedAnnotationUse_import() { | |
3064 Source source = addSource(r''' | |
3065 import 'deprecated_library.dart'; | |
3066 f(A a) {}'''); | |
3067 addNamedSource( | |
3068 "/deprecated_library.dart", | |
3069 r''' | |
3070 @deprecated | |
3071 library deprecated_library; | |
3072 class A {}'''); | |
3073 computeLibrarySourceErrors(source); | |
3074 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3075 verify([source]); | |
3076 } | |
3077 | |
3078 void test_deprecatedAnnotationUse_indexExpression() { | |
3079 Source source = addSource(r''' | |
3080 class A { | |
3081 @deprecated | |
3082 operator[](int i) {} | |
3083 } | |
3084 f(A a) { | |
3085 return a[1]; | |
3086 }'''); | |
3087 computeLibrarySourceErrors(source); | |
3088 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3089 verify([source]); | |
3090 } | |
3091 | |
3092 void test_deprecatedAnnotationUse_instanceCreation() { | |
3093 Source source = addSource(r''' | |
3094 class A { | |
3095 @deprecated | |
3096 A(int i) {} | |
3097 } | |
3098 f() { | |
3099 A a = new A(1); | |
3100 }'''); | |
3101 computeLibrarySourceErrors(source); | |
3102 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3103 verify([source]); | |
3104 } | |
3105 | |
3106 void test_deprecatedAnnotationUse_instanceCreation_namedConstructor() { | |
3107 Source source = addSource(r''' | |
3108 class A { | |
3109 @deprecated | |
3110 A.named(int i) {} | |
3111 } | |
3112 f() { | |
3113 A a = new A.named(1); | |
3114 }'''); | |
3115 computeLibrarySourceErrors(source); | |
3116 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3117 verify([source]); | |
3118 } | |
3119 | |
3120 void test_deprecatedAnnotationUse_operator() { | |
3121 Source source = addSource(r''' | |
3122 class A { | |
3123 @deprecated | |
3124 operator+(A a) {} | |
3125 } | |
3126 f(A a) { | |
3127 A b; | |
3128 return a + b; | |
3129 }'''); | |
3130 computeLibrarySourceErrors(source); | |
3131 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3132 verify([source]); | |
3133 } | |
3134 | |
3135 void test_deprecatedAnnotationUse_setter() { | |
3136 Source source = addSource(r''' | |
3137 class A { | |
3138 @deprecated | |
3139 set s(v) {} | |
3140 } | |
3141 f(A a) { | |
3142 return a.s = 1; | |
3143 }'''); | |
3144 computeLibrarySourceErrors(source); | |
3145 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3146 verify([source]); | |
3147 } | |
3148 | |
3149 void test_deprecatedAnnotationUse_superConstructor() { | |
3150 Source source = addSource(r''' | |
3151 class A { | |
3152 @deprecated | |
3153 A() {} | |
3154 } | |
3155 class B extends A { | |
3156 B() : super() {} | |
3157 }'''); | |
3158 computeLibrarySourceErrors(source); | |
3159 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3160 verify([source]); | |
3161 } | |
3162 | |
3163 void test_deprecatedAnnotationUse_superConstructor_namedConstructor() { | |
3164 Source source = addSource(r''' | |
3165 class A { | |
3166 @deprecated | |
3167 A.named() {} | |
3168 } | |
3169 class B extends A { | |
3170 B() : super.named() {} | |
3171 }'''); | |
3172 computeLibrarySourceErrors(source); | |
3173 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); | |
3174 verify([source]); | |
3175 } | |
3176 | |
3177 void test_divisionOptimization_double() { | |
3178 Source source = addSource(r''' | |
3179 f(double x, double y) { | |
3180 var v = (x / y).toInt(); | |
3181 }'''); | |
3182 computeLibrarySourceErrors(source); | |
3183 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); | |
3184 verify([source]); | |
3185 } | |
3186 | |
3187 void test_divisionOptimization_int() { | |
3188 Source source = addSource(r''' | |
3189 f(int x, int y) { | |
3190 var v = (x / y).toInt(); | |
3191 }'''); | |
3192 computeLibrarySourceErrors(source); | |
3193 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); | |
3194 verify([source]); | |
3195 } | |
3196 | |
3197 void test_divisionOptimization_propagatedType() { | |
3198 // Tests the propagated type information of the '/' method | |
3199 Source source = addSource(r''' | |
3200 f(x, y) { | |
3201 x = 1; | |
3202 y = 1; | |
3203 var v = (x / y).toInt(); | |
3204 }'''); | |
3205 computeLibrarySourceErrors(source); | |
3206 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); | |
3207 verify([source]); | |
3208 } | |
3209 | |
3210 void test_divisionOptimization_wrappedBinaryExpression() { | |
3211 Source source = addSource(r''' | |
3212 f(int x, int y) { | |
3213 var v = (((x / y))).toInt(); | |
3214 }'''); | |
3215 computeLibrarySourceErrors(source); | |
3216 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); | |
3217 verify([source]); | |
3218 } | |
3219 | |
3220 void test_duplicateImport() { | |
3221 Source source = addSource(r''' | |
3222 library L; | |
3223 import 'lib1.dart'; | |
3224 import 'lib1.dart'; | |
3225 A a;'''); | |
3226 addNamedSource( | |
3227 "/lib1.dart", | |
3228 r''' | |
3229 library lib1; | |
3230 class A {}'''); | |
3231 computeLibrarySourceErrors(source); | |
3232 assertErrors(source, [HintCode.DUPLICATE_IMPORT]); | |
3233 verify([source]); | |
3234 } | |
3235 | |
3236 void test_duplicateImport2() { | |
3237 Source source = addSource(r''' | |
3238 library L; | |
3239 import 'lib1.dart'; | |
3240 import 'lib1.dart'; | |
3241 import 'lib1.dart'; | |
3242 A a;'''); | |
3243 addNamedSource( | |
3244 "/lib1.dart", | |
3245 r''' | |
3246 library lib1; | |
3247 class A {}'''); | |
3248 computeLibrarySourceErrors(source); | |
3249 assertErrors( | |
3250 source, [HintCode.DUPLICATE_IMPORT, HintCode.DUPLICATE_IMPORT]); | |
3251 verify([source]); | |
3252 } | |
3253 | |
3254 void test_duplicateImport3() { | |
3255 Source source = addSource(r''' | |
3256 library L; | |
3257 import 'lib1.dart' as M show A hide B; | |
3258 import 'lib1.dart' as M show A hide B; | |
3259 M.A a;'''); | |
3260 addNamedSource( | |
3261 "/lib1.dart", | |
3262 r''' | |
3263 library lib1; | |
3264 class A {} | |
3265 class B {}'''); | |
3266 computeLibrarySourceErrors(source); | |
3267 assertErrors(source, [HintCode.DUPLICATE_IMPORT]); | |
3268 verify([source]); | |
3269 } | |
3270 | |
3271 void test_importDeferredLibraryWithLoadFunction() { | |
3272 resolveWithErrors(<String>[ | |
3273 r''' | |
3274 library lib1; | |
3275 loadLibrary() {} | |
3276 f() {}''', | |
3277 r''' | |
3278 library root; | |
3279 import 'lib1.dart' deferred as lib1; | |
3280 main() { lib1.f(); }''' | |
3281 ], <ErrorCode>[ | |
3282 HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION | |
3283 ]); | |
3284 } | |
3285 | |
3286 void test_invalidAssignment_instanceVariable() { | |
3287 Source source = addSource(r''' | |
3288 class A { | |
3289 int x; | |
3290 } | |
3291 f(var y) { | |
3292 A a; | |
3293 if(y is String) { | |
3294 a.x = y; | |
3295 } | |
3296 }'''); | |
3297 computeLibrarySourceErrors(source); | |
3298 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); | |
3299 verify([source]); | |
3300 } | |
3301 | |
3302 void test_invalidAssignment_localVariable() { | |
3303 Source source = addSource(r''' | |
3304 f(var y) { | |
3305 if(y is String) { | |
3306 int x = y; | |
3307 } | |
3308 }'''); | |
3309 computeLibrarySourceErrors(source); | |
3310 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); | |
3311 verify([source]); | |
3312 } | |
3313 | |
3314 void test_invalidAssignment_message() { | |
3315 // The implementation of HintCode.INVALID_ASSIGNMENT assumes that | |
3316 // StaticTypeWarningCode.INVALID_ASSIGNMENT has the same message. | |
3317 expect(StaticTypeWarningCode.INVALID_ASSIGNMENT.message, | |
3318 HintCode.INVALID_ASSIGNMENT.message); | |
3319 } | |
3320 | |
3321 void test_invalidAssignment_staticVariable() { | |
3322 Source source = addSource(r''' | |
3323 class A { | |
3324 static int x; | |
3325 } | |
3326 f(var y) { | |
3327 if(y is String) { | |
3328 A.x = y; | |
3329 } | |
3330 }'''); | |
3331 computeLibrarySourceErrors(source); | |
3332 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); | |
3333 verify([source]); | |
3334 } | |
3335 | |
3336 void test_invalidAssignment_variableDeclaration() { | |
3337 // 17971 | |
3338 Source source = addSource(r''' | |
3339 class Point { | |
3340 final num x, y; | |
3341 Point(this.x, this.y); | |
3342 Point operator +(Point other) { | |
3343 return new Point(x+other.x, y+other.y); | |
3344 } | |
3345 } | |
3346 main() { | |
3347 var p1 = new Point(0, 0); | |
3348 var p2 = new Point(10, 10); | |
3349 int n = p1 + p2; | |
3350 }'''); | |
3351 computeLibrarySourceErrors(source); | |
3352 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); | |
3353 verify([source]); | |
3354 } | |
3355 | |
3356 void test_invalidUseOfProtectedMember_field() { | |
3357 Source source = addSource(r''' | |
3358 import 'package:meta/meta.dart'; | |
3359 class A { | |
3360 @protected | |
3361 int a; | |
3362 } | |
3363 abstract class B implements A { | |
3364 int b() => a; | |
3365 }'''); | |
3366 computeLibrarySourceErrors(source); | |
3367 assertErrors(source, [HintCode.INVALID_USE_OF_PROTECTED_MEMBER]); | |
3368 verify([source]); | |
3369 } | |
3370 | |
3371 void test_invalidUseOfProtectedMember_function() { | |
3372 Source source = addSource(r''' | |
3373 import 'package:meta/meta.dart'; | |
3374 class A { | |
3375 @protected | |
3376 void a(){ } | |
3377 } | |
3378 main() { | |
3379 new A().a(); | |
3380 }'''); | |
3381 computeLibrarySourceErrors(source); | |
3382 assertErrors(source, [HintCode.INVALID_USE_OF_PROTECTED_MEMBER]); | |
3383 verify([source]); | |
3384 } | |
3385 | |
3386 void test_invalidUseOfProtectedMember_getter() { | |
3387 Source source = addSource(r''' | |
3388 import 'package:meta/meta.dart'; | |
3389 class A { | |
3390 @protected | |
3391 int get a => 42; | |
3392 } | |
3393 abstract class B implements A { | |
3394 int b() => a; | |
3395 }'''); | |
3396 computeLibrarySourceErrors(source); | |
3397 assertErrors(source, [HintCode.INVALID_USE_OF_PROTECTED_MEMBER]); | |
3398 verify([source]); | |
3399 } | |
3400 | |
3401 void test_invalidUseOfProtectedMember_message() { | |
3402 Source source = addSource(r''' | |
3403 import 'package:meta/meta.dart'; | |
3404 class A { | |
3405 @protected | |
3406 void a(){ } | |
3407 } | |
3408 class B { | |
3409 void b() => new A().a(); | |
3410 }'''); | |
3411 List<AnalysisError> errors = analysisContext2.computeErrors(source); | |
3412 expect(errors, hasLength(1)); | |
3413 expect(errors[0].message, | |
3414 "The member 'a' can only be used within instance members of subclasses o
f 'A'"); | |
3415 } | |
3416 | |
3417 void test_invalidUseOfProtectedMember_method_1() { | |
3418 Source source = addSource(r''' | |
3419 import 'package:meta/meta.dart'; | |
3420 class A { | |
3421 @protected | |
3422 void a(){ } | |
3423 } | |
3424 class B { | |
3425 void b() => new A().a(); | |
3426 }'''); | |
3427 computeLibrarySourceErrors(source); | |
3428 assertErrors(source, [HintCode.INVALID_USE_OF_PROTECTED_MEMBER]); | |
3429 verify([source]); | |
3430 } | |
3431 | |
3432 void test_invalidUseOfProtectedMember_method_2() { | |
3433 Source source = addSource(r''' | |
3434 import 'package:meta/meta.dart'; | |
3435 class A { | |
3436 @protected | |
3437 void a(){ } | |
3438 } | |
3439 abstract class B implements A { | |
3440 void b() => a(); | |
3441 }'''); | |
3442 computeLibrarySourceErrors(source); | |
3443 assertErrors(source, [HintCode.INVALID_USE_OF_PROTECTED_MEMBER]); | |
3444 verify([source]); | |
3445 } | |
3446 | |
3447 void test_invalidUseOfProtectedMember_OK_1() { | |
3448 Source source = addSource(r''' | |
3449 import 'package:meta/meta.dart'; | |
3450 class A { | |
3451 @protected | |
3452 void a(){ } | |
3453 } | |
3454 class B extends A { | |
3455 void b() => a(); | |
3456 }'''); | |
3457 computeLibrarySourceErrors(source); | |
3458 assertErrors(source, []); | |
3459 verify([source]); | |
3460 } | |
3461 | |
3462 void test_invalidUseOfProtectedMember_OK_2() { | |
3463 Source source = addSource(r''' | |
3464 import 'package:meta/meta.dart'; | |
3465 class A { | |
3466 @protected | |
3467 void a(){ } | |
3468 } | |
3469 class B extends Object with A { | |
3470 void b() => a(); | |
3471 }'''); | |
3472 computeLibrarySourceErrors(source); | |
3473 assertErrors(source, []); | |
3474 verify([source]); | |
3475 } | |
3476 | |
3477 void test_invalidUseOfProtectedMember_OK_3() { | |
3478 Source source = addSource(r''' | |
3479 import 'package:meta/meta.dart'; | |
3480 class A { | |
3481 @protected m1() {} | |
3482 } | |
3483 class B extends A { | |
3484 static m2(A a) => a.m1(); | |
3485 }'''); | |
3486 computeLibrarySourceErrors(source); | |
3487 assertErrors(source, []); | |
3488 verify([source]); | |
3489 } | |
3490 | |
3491 void test_invalidUseOfProtectedMember_OK_4() { | |
3492 Source source = addSource(r''' | |
3493 import 'package:meta/meta.dart'; | |
3494 class A { | |
3495 @protected | |
3496 void a(){ } | |
3497 } | |
3498 class B extends A { | |
3499 void a() => a(); | |
3500 } | |
3501 main() { | |
3502 new B().a(); | |
3503 }'''); | |
3504 computeLibrarySourceErrors(source); | |
3505 assertErrors(source, []); | |
3506 verify([source]); | |
3507 } | |
3508 | |
3509 void test_invalidUseOfProtectedMember_OK_field() { | |
3510 Source source = addSource(r''' | |
3511 import 'package:meta/meta.dart'; | |
3512 class A { | |
3513 @protected | |
3514 int a = 42; | |
3515 } | |
3516 class B extends A { | |
3517 int b() => a; | |
3518 } | |
3519 '''); | |
3520 computeLibrarySourceErrors(source); | |
3521 assertErrors(source, []); | |
3522 verify([source]); | |
3523 } | |
3524 | |
3525 void test_invalidUseOfProtectedMember_OK_getter() { | |
3526 Source source = addSource(r''' | |
3527 import 'package:meta/meta.dart'; | |
3528 class A { | |
3529 @protected | |
3530 int get a => 42; | |
3531 } | |
3532 class B extends A { | |
3533 int b() => a; | |
3534 } | |
3535 '''); | |
3536 computeLibrarySourceErrors(source); | |
3537 assertErrors(source, []); | |
3538 verify([source]); | |
3539 } | |
3540 | |
3541 void test_invalidUseOfProtectedMember_OK_setter() { | |
3542 Source source = addSource(r''' | |
3543 import 'package:meta/meta.dart'; | |
3544 class A { | |
3545 @protected | |
3546 void set a(int i) { } | |
3547 } | |
3548 class B extends A { | |
3549 void b(int i) { | |
3550 a = i; | |
3551 } | |
3552 } | |
3553 '''); | |
3554 computeLibrarySourceErrors(source); | |
3555 assertErrors(source, []); | |
3556 verify([source]); | |
3557 } | |
3558 | |
3559 void test_invalidUseOfProtectedMember_setter() { | |
3560 Source source = addSource(r''' | |
3561 import 'package:meta/meta.dart'; | |
3562 class A { | |
3563 @protected | |
3564 void set a(int i) { } | |
3565 } | |
3566 abstract class B implements A { | |
3567 b(int i) { | |
3568 a = i; | |
3569 } | |
3570 }'''); | |
3571 computeLibrarySourceErrors(source); | |
3572 assertErrors(source, [HintCode.INVALID_USE_OF_PROTECTED_MEMBER]); | |
3573 verify([source]); | |
3574 } | |
3575 | |
3576 void test_invalidUseOfProtectedMember_topLevelVariable() { | |
3577 Source source = addSource(r''' | |
3578 import 'package:meta/meta.dart'; | |
3579 @protected | |
3580 int x = 0; | |
3581 main() { | |
3582 print(x); | |
3583 }'''); | |
3584 computeLibrarySourceErrors(source); | |
3585 // TODO(brianwilkerson) This should produce a hint because the annotation is | |
3586 // being applied to the wrong kind of declaration. | |
3587 assertNoErrors(source); | |
3588 verify([source]); | |
3589 } | |
3590 | |
3591 void test_isDouble() { | |
3592 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | |
3593 options.dart2jsHint = true; | |
3594 resetWithOptions(options); | |
3595 Source source = addSource("var v = 1 is double;"); | |
3596 computeLibrarySourceErrors(source); | |
3597 assertErrors(source, [HintCode.IS_DOUBLE]); | |
3598 verify([source]); | |
3599 } | |
3600 | |
3601 void test_isNotDouble() { | |
3602 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | |
3603 options.dart2jsHint = true; | |
3604 resetWithOptions(options); | |
3605 Source source = addSource("var v = 1 is! double;"); | |
3606 computeLibrarySourceErrors(source); | |
3607 assertErrors(source, [HintCode.IS_NOT_DOUBLE]); | |
3608 verify([source]); | |
3609 } | |
3610 | |
3611 void test_missingReturn_async() { | |
3612 Source source = addSource(''' | |
3613 import 'dart:async'; | |
3614 Future<int> f() async {} | |
3615 '''); | |
3616 computeLibrarySourceErrors(source); | |
3617 assertErrors(source, [HintCode.MISSING_RETURN]); | |
3618 verify([source]); | |
3619 } | |
3620 | |
3621 void test_missingReturn_function() { | |
3622 Source source = addSource("int f() {}"); | |
3623 computeLibrarySourceErrors(source); | |
3624 assertErrors(source, [HintCode.MISSING_RETURN]); | |
3625 verify([source]); | |
3626 } | |
3627 | |
3628 void test_missingReturn_method() { | |
3629 Source source = addSource(r''' | |
3630 class A { | |
3631 int m() {} | |
3632 }'''); | |
3633 computeLibrarySourceErrors(source); | |
3634 assertErrors(source, [HintCode.MISSING_RETURN]); | |
3635 verify([source]); | |
3636 } | |
3637 | |
3638 void test_mustCallSuper() { | |
3639 Source source = addSource(r''' | |
3640 import 'package:meta/meta.dart'; | |
3641 class A { | |
3642 @mustCallSuper | |
3643 void a() {} | |
3644 } | |
3645 class B extends A { | |
3646 @override | |
3647 void a() | |
3648 {} | |
3649 } | |
3650 '''); | |
3651 computeLibrarySourceErrors(source); | |
3652 assertErrors(source, [HintCode.MUST_CALL_SUPER]); | |
3653 verify([source]); | |
3654 } | |
3655 | |
3656 void test_mustCallSuper_indirect() { | |
3657 Source source = addSource(r''' | |
3658 import 'package:meta/meta.dart'; | |
3659 class A { | |
3660 @mustCallSuper | |
3661 void a() {} | |
3662 } | |
3663 class C extends A { | |
3664 @override | |
3665 void a() { | |
3666 super.a(); | |
3667 } | |
3668 } | |
3669 class D extends C { | |
3670 @override | |
3671 void a() {} | |
3672 } | |
3673 '''); | |
3674 computeLibrarySourceErrors(source); | |
3675 assertErrors(source, [HintCode.MUST_CALL_SUPER]); | |
3676 verify([source]); | |
3677 } | |
3678 | |
3679 void test_mustCallSuper_OK() { | |
3680 Source source = addSource(r''' | |
3681 import 'package:meta/meta.dart'; | |
3682 class A { | |
3683 @mustCallSuper | |
3684 void a() {} | |
3685 } | |
3686 class C extends A { | |
3687 @override | |
3688 void a() { | |
3689 super.a(); //OK | |
3690 } | |
3691 } | |
3692 '''); | |
3693 computeLibrarySourceErrors(source); | |
3694 assertErrors(source, []); | |
3695 verify([source]); | |
3696 } | |
3697 | |
3698 @override | |
3699 void test_nullAwareInCondition_assert() { | |
3700 Source source = addSource(r''' | |
3701 m(x) { | |
3702 assert (x?.a); | |
3703 } | |
3704 '''); | |
3705 computeLibrarySourceErrors(source); | |
3706 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3707 verify([source]); | |
3708 } | |
3709 | |
3710 void test_nullAwareInCondition_conditionalExpression() { | |
3711 Source source = addSource(r''' | |
3712 m(x) { | |
3713 return x?.a ? 0 : 1; | |
3714 } | |
3715 '''); | |
3716 computeLibrarySourceErrors(source); | |
3717 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3718 verify([source]); | |
3719 } | |
3720 | |
3721 void test_nullAwareInCondition_do() { | |
3722 Source source = addSource(r''' | |
3723 m(x) { | |
3724 do {} while (x?.a); | |
3725 } | |
3726 '''); | |
3727 computeLibrarySourceErrors(source); | |
3728 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3729 verify([source]); | |
3730 } | |
3731 | |
3732 void test_nullAwareInCondition_for() { | |
3733 Source source = addSource(r''' | |
3734 m(x) { | |
3735 for (var v = x; v?.a; v = v.next) {} | |
3736 } | |
3737 '''); | |
3738 computeLibrarySourceErrors(source); | |
3739 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3740 verify([source]); | |
3741 } | |
3742 | |
3743 void test_nullAwareInCondition_if() { | |
3744 Source source = addSource(r''' | |
3745 m(x) { | |
3746 if (x?.a) {} | |
3747 } | |
3748 '''); | |
3749 computeLibrarySourceErrors(source); | |
3750 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3751 verify([source]); | |
3752 } | |
3753 | |
3754 void test_nullAwareInCondition_if_conditionalAnd_first() { | |
3755 Source source = addSource(r''' | |
3756 m(x) { | |
3757 if (x?.a && x.b) {} | |
3758 } | |
3759 '''); | |
3760 computeLibrarySourceErrors(source); | |
3761 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3762 verify([source]); | |
3763 } | |
3764 | |
3765 void test_nullAwareInCondition_if_conditionalAnd_second() { | |
3766 Source source = addSource(r''' | |
3767 m(x) { | |
3768 if (x.a && x?.b) {} | |
3769 } | |
3770 '''); | |
3771 computeLibrarySourceErrors(source); | |
3772 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3773 verify([source]); | |
3774 } | |
3775 | |
3776 void test_nullAwareInCondition_if_conditionalAnd_third() { | |
3777 Source source = addSource(r''' | |
3778 m(x) { | |
3779 if (x.a && x.b && x?.c) {} | |
3780 } | |
3781 '''); | |
3782 computeLibrarySourceErrors(source); | |
3783 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3784 verify([source]); | |
3785 } | |
3786 | |
3787 void test_nullAwareInCondition_if_conditionalOr_first() { | |
3788 Source source = addSource(r''' | |
3789 m(x) { | |
3790 if (x?.a || x.b) {} | |
3791 } | |
3792 '''); | |
3793 computeLibrarySourceErrors(source); | |
3794 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3795 verify([source]); | |
3796 } | |
3797 | |
3798 void test_nullAwareInCondition_if_conditionalOr_second() { | |
3799 Source source = addSource(r''' | |
3800 m(x) { | |
3801 if (x.a || x?.b) {} | |
3802 } | |
3803 '''); | |
3804 computeLibrarySourceErrors(source); | |
3805 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3806 verify([source]); | |
3807 } | |
3808 | |
3809 void test_nullAwareInCondition_if_conditionalOr_third() { | |
3810 Source source = addSource(r''' | |
3811 m(x) { | |
3812 if (x.a || x.b || x?.c) {} | |
3813 } | |
3814 '''); | |
3815 computeLibrarySourceErrors(source); | |
3816 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3817 verify([source]); | |
3818 } | |
3819 | |
3820 void test_nullAwareInCondition_if_not() { | |
3821 Source source = addSource(r''' | |
3822 m(x) { | |
3823 if (!x?.a) {} | |
3824 } | |
3825 '''); | |
3826 computeLibrarySourceErrors(source); | |
3827 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3828 verify([source]); | |
3829 } | |
3830 | |
3831 void test_nullAwareInCondition_if_parenthesized() { | |
3832 Source source = addSource(r''' | |
3833 m(x) { | |
3834 if ((x?.a)) {} | |
3835 } | |
3836 '''); | |
3837 computeLibrarySourceErrors(source); | |
3838 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3839 verify([source]); | |
3840 } | |
3841 | |
3842 void test_nullAwareInCondition_while() { | |
3843 Source source = addSource(r''' | |
3844 m(x) { | |
3845 while (x?.a) {} | |
3846 } | |
3847 '''); | |
3848 computeLibrarySourceErrors(source); | |
3849 assertErrors(source, [HintCode.NULL_AWARE_IN_CONDITION]); | |
3850 verify([source]); | |
3851 } | |
3852 | |
3853 void test_overrideOnNonOverridingGetter_invalid() { | |
3854 Source source = addSource(r''' | |
3855 library dart.core; | |
3856 const override = null; | |
3857 class A { | |
3858 } | |
3859 class B extends A { | |
3860 @override | |
3861 int get m => 1; | |
3862 }'''); | |
3863 computeLibrarySourceErrors(source); | |
3864 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER]); | |
3865 verify([source]); | |
3866 } | |
3867 | |
3868 void test_overrideOnNonOverridingMethod_invalid() { | |
3869 Source source = addSource(r''' | |
3870 library dart.core; | |
3871 const override = null; | |
3872 class A { | |
3873 } | |
3874 class B extends A { | |
3875 @override | |
3876 int m() => 1; | |
3877 }'''); | |
3878 computeLibrarySourceErrors(source); | |
3879 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD]); | |
3880 verify([source]); | |
3881 } | |
3882 | |
3883 void test_overrideOnNonOverridingSetter_invalid() { | |
3884 Source source = addSource(r''' | |
3885 library dart.core; | |
3886 const override = null; | |
3887 class A { | |
3888 } | |
3889 class B extends A { | |
3890 @override | |
3891 set m(int x) {} | |
3892 }'''); | |
3893 computeLibrarySourceErrors(source); | |
3894 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER]); | |
3895 verify([source]); | |
3896 } | |
3897 | |
3898 void test_typeCheck_type_is_Null() { | |
3899 Source source = addSource(r''' | |
3900 m(i) { | |
3901 bool b = i is Null; | |
3902 }'''); | |
3903 computeLibrarySourceErrors(source); | |
3904 assertErrors(source, [HintCode.TYPE_CHECK_IS_NULL]); | |
3905 verify([source]); | |
3906 } | |
3907 | |
3908 void test_typeCheck_type_not_Null() { | |
3909 Source source = addSource(r''' | |
3910 m(i) { | |
3911 bool b = i is! Null; | |
3912 }'''); | |
3913 computeLibrarySourceErrors(source); | |
3914 assertErrors(source, [HintCode.TYPE_CHECK_IS_NOT_NULL]); | |
3915 verify([source]); | |
3916 } | |
3917 | |
3918 void test_undefinedGetter() { | |
3919 Source source = addSource(r''' | |
3920 class A {} | |
3921 f(var a) { | |
3922 if(a is A) { | |
3923 return a.m; | |
3924 } | |
3925 }'''); | |
3926 computeLibrarySourceErrors(source); | |
3927 assertErrors(source, [HintCode.UNDEFINED_GETTER]); | |
3928 } | |
3929 | |
3930 void test_undefinedGetter_message() { | |
3931 // The implementation of HintCode.UNDEFINED_SETTER assumes that | |
3932 // UNDEFINED_SETTER in StaticTypeWarningCode and StaticWarningCode are the | |
3933 // same, this verifies that assumption. | |
3934 expect(StaticWarningCode.UNDEFINED_GETTER.message, | |
3935 StaticTypeWarningCode.UNDEFINED_GETTER.message); | |
3936 } | |
3937 | |
3938 void test_undefinedMethod() { | |
3939 Source source = addSource(r''' | |
3940 f() { | |
3941 var a = 'str'; | |
3942 a.notAMethodOnString(); | |
3943 }'''); | |
3944 computeLibrarySourceErrors(source); | |
3945 assertErrors(source, [HintCode.UNDEFINED_METHOD]); | |
3946 } | |
3947 | |
3948 void test_undefinedMethod_assignmentExpression() { | |
3949 Source source = addSource(r''' | |
3950 class A {} | |
3951 class B { | |
3952 f(var a, var a2) { | |
3953 a = new A(); | |
3954 a2 = new A(); | |
3955 a += a2; | |
3956 } | |
3957 }'''); | |
3958 computeLibrarySourceErrors(source); | |
3959 assertErrors(source, [HintCode.UNDEFINED_METHOD]); | |
3960 } | |
3961 | |
3962 void test_undefinedOperator_binaryExpression() { | |
3963 Source source = addSource(r''' | |
3964 class A {} | |
3965 f(var a) { | |
3966 if(a is A) { | |
3967 a + 1; | |
3968 } | |
3969 }'''); | |
3970 computeLibrarySourceErrors(source); | |
3971 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); | |
3972 } | |
3973 | |
3974 void test_undefinedOperator_indexBoth() { | |
3975 Source source = addSource(r''' | |
3976 class A {} | |
3977 f(var a) { | |
3978 if(a is A) { | |
3979 a[0]++; | |
3980 } | |
3981 }'''); | |
3982 computeLibrarySourceErrors(source); | |
3983 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); | |
3984 } | |
3985 | |
3986 void test_undefinedOperator_indexGetter() { | |
3987 Source source = addSource(r''' | |
3988 class A {} | |
3989 f(var a) { | |
3990 if(a is A) { | |
3991 a[0]; | |
3992 } | |
3993 }'''); | |
3994 computeLibrarySourceErrors(source); | |
3995 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); | |
3996 } | |
3997 | |
3998 void test_undefinedOperator_indexSetter() { | |
3999 Source source = addSource(r''' | |
4000 class A {} | |
4001 f(var a) { | |
4002 if(a is A) { | |
4003 a[0] = 1; | |
4004 } | |
4005 }'''); | |
4006 computeLibrarySourceErrors(source); | |
4007 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); | |
4008 } | |
4009 | |
4010 void test_undefinedOperator_postfixExpression() { | |
4011 Source source = addSource(r''' | |
4012 class A {} | |
4013 f(var a) { | |
4014 if(a is A) { | |
4015 a++; | |
4016 } | |
4017 }'''); | |
4018 computeLibrarySourceErrors(source); | |
4019 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); | |
4020 } | |
4021 | |
4022 void test_undefinedOperator_prefixExpression() { | |
4023 Source source = addSource(r''' | |
4024 class A {} | |
4025 f(var a) { | |
4026 if(a is A) { | |
4027 ++a; | |
4028 } | |
4029 }'''); | |
4030 computeLibrarySourceErrors(source); | |
4031 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); | |
4032 } | |
4033 | |
4034 void test_undefinedSetter() { | |
4035 Source source = addSource(r''' | |
4036 class A {} | |
4037 f(var a) { | |
4038 if(a is A) { | |
4039 a.m = 0; | |
4040 } | |
4041 }'''); | |
4042 computeLibrarySourceErrors(source); | |
4043 assertErrors(source, [HintCode.UNDEFINED_SETTER]); | |
4044 } | |
4045 | |
4046 void test_undefinedSetter_message() { | |
4047 // The implementation of HintCode.UNDEFINED_SETTER assumes that | |
4048 // UNDEFINED_SETTER in StaticTypeWarningCode and StaticWarningCode are the | |
4049 // same, this verifies that assumption. | |
4050 expect(StaticWarningCode.UNDEFINED_SETTER.message, | |
4051 StaticTypeWarningCode.UNDEFINED_SETTER.message); | |
4052 } | |
4053 | |
4054 void test_unnecessaryCast_type_supertype() { | |
4055 Source source = addSource(r''' | |
4056 m(int i) { | |
4057 var b = i as Object; | |
4058 }'''); | |
4059 computeLibrarySourceErrors(source); | |
4060 assertErrors(source, [HintCode.UNNECESSARY_CAST]); | |
4061 verify([source]); | |
4062 } | |
4063 | |
4064 void test_unnecessaryCast_type_type() { | |
4065 Source source = addSource(r''' | |
4066 m(num i) { | |
4067 var b = i as num; | |
4068 }'''); | |
4069 computeLibrarySourceErrors(source); | |
4070 assertErrors(source, [HintCode.UNNECESSARY_CAST]); | |
4071 verify([source]); | |
4072 } | |
4073 | |
4074 void test_unnecessaryNoSuchMethod_blockBody() { | |
4075 Source source = addSource(r''' | |
4076 class A { | |
4077 noSuchMethod(x) => super.noSuchMethod(x); | |
4078 } | |
4079 class B extends A { | |
4080 mmm(); | |
4081 noSuchMethod(y) { | |
4082 return super.noSuchMethod(y); | |
4083 } | |
4084 }'''); | |
4085 computeLibrarySourceErrors(source); | |
4086 assertErrors(source, [HintCode.UNNECESSARY_NO_SUCH_METHOD]); | |
4087 verify([source]); | |
4088 } | |
4089 | |
4090 void test_unnecessaryNoSuchMethod_expressionBody() { | |
4091 Source source = addSource(r''' | |
4092 class A { | |
4093 noSuchMethod(x) => super.noSuchMethod(x); | |
4094 } | |
4095 class B extends A { | |
4096 mmm(); | |
4097 noSuchMethod(y) => super.noSuchMethod(y); | |
4098 }'''); | |
4099 computeLibrarySourceErrors(source); | |
4100 assertErrors(source, [HintCode.UNNECESSARY_NO_SUCH_METHOD]); | |
4101 verify([source]); | |
4102 } | |
4103 | |
4104 void test_unnecessaryTypeCheck_null_is_Null() { | |
4105 Source source = addSource("bool b = null is Null;"); | |
4106 computeLibrarySourceErrors(source); | |
4107 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); | |
4108 verify([source]); | |
4109 } | |
4110 | |
4111 void test_unnecessaryTypeCheck_null_not_Null() { | |
4112 Source source = addSource("bool b = null is! Null;"); | |
4113 computeLibrarySourceErrors(source); | |
4114 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); | |
4115 verify([source]); | |
4116 } | |
4117 | |
4118 void test_unnecessaryTypeCheck_type_is_dynamic() { | |
4119 Source source = addSource(r''' | |
4120 m(i) { | |
4121 bool b = i is dynamic; | |
4122 }'''); | |
4123 computeLibrarySourceErrors(source); | |
4124 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); | |
4125 verify([source]); | |
4126 } | |
4127 | |
4128 void test_unnecessaryTypeCheck_type_is_object() { | |
4129 Source source = addSource(r''' | |
4130 m(i) { | |
4131 bool b = i is Object; | |
4132 }'''); | |
4133 computeLibrarySourceErrors(source); | |
4134 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); | |
4135 verify([source]); | |
4136 } | |
4137 | |
4138 void test_unnecessaryTypeCheck_type_not_dynamic() { | |
4139 Source source = addSource(r''' | |
4140 m(i) { | |
4141 bool b = i is! dynamic; | |
4142 }'''); | |
4143 computeLibrarySourceErrors(source); | |
4144 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); | |
4145 verify([source]); | |
4146 } | |
4147 | |
4148 void test_unnecessaryTypeCheck_type_not_object() { | |
4149 Source source = addSource(r''' | |
4150 m(i) { | |
4151 bool b = i is! Object; | |
4152 }'''); | |
4153 computeLibrarySourceErrors(source); | |
4154 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); | |
4155 verify([source]); | |
4156 } | |
4157 | |
4158 void test_unusedElement_class_isUsed_extends() { | |
4159 enableUnusedElement = true; | |
4160 Source source = addSource(r''' | |
4161 class _A {} | |
4162 class B extends _A {} | |
4163 '''); | |
4164 computeLibrarySourceErrors(source); | |
4165 assertNoErrors(source); | |
4166 verify([source]); | |
4167 } | |
4168 | |
4169 void test_unusedElement_class_isUsed_fieldDeclaration() { | |
4170 enableUnusedElement = true; | |
4171 var src = r''' | |
4172 class Foo { | |
4173 _Bar x; | |
4174 } | |
4175 | |
4176 class _Bar { | |
4177 } | |
4178 '''; | |
4179 Source source = addSource(src); | |
4180 computeLibrarySourceErrors(source); | |
4181 assertNoErrors(source); | |
4182 verify([source]); | |
4183 } | |
4184 | |
4185 void test_unusedElement_class_isUsed_implements() { | |
4186 enableUnusedElement = true; | |
4187 Source source = addSource(r''' | |
4188 class _A {} | |
4189 class B implements _A {} | |
4190 '''); | |
4191 computeLibrarySourceErrors(source); | |
4192 assertNoErrors(source); | |
4193 verify([source]); | |
4194 } | |
4195 | |
4196 void test_unusedElement_class_isUsed_instanceCreation() { | |
4197 enableUnusedElement = true; | |
4198 Source source = addSource(r''' | |
4199 class _A {} | |
4200 main() { | |
4201 new _A(); | |
4202 }'''); | |
4203 computeLibrarySourceErrors(source); | |
4204 assertNoErrors(source); | |
4205 verify([source]); | |
4206 } | |
4207 | |
4208 void test_unusedElement_class_isUsed_staticFieldAccess() { | |
4209 enableUnusedElement = true; | |
4210 Source source = addSource(r''' | |
4211 class _A { | |
4212 static const F = 42; | |
4213 } | |
4214 main() { | |
4215 _A.F; | |
4216 }'''); | |
4217 computeLibrarySourceErrors(source); | |
4218 assertNoErrors(source); | |
4219 verify([source]); | |
4220 } | |
4221 | |
4222 void test_unusedElement_class_isUsed_staticMethodInvocation() { | |
4223 enableUnusedElement = true; | |
4224 Source source = addSource(r''' | |
4225 class _A { | |
4226 static m() {} | |
4227 } | |
4228 main() { | |
4229 _A.m(); | |
4230 }'''); | |
4231 computeLibrarySourceErrors(source); | |
4232 assertNoErrors(source); | |
4233 verify([source]); | |
4234 } | |
4235 | |
4236 void test_unusedElement_class_isUsed_typeArgument() { | |
4237 enableUnusedElement = true; | |
4238 Source source = addSource(r''' | |
4239 class _A {} | |
4240 main() { | |
4241 var v = new List<_A>(); | |
4242 print(v); | |
4243 }'''); | |
4244 computeLibrarySourceErrors(source); | |
4245 assertNoErrors(source); | |
4246 verify([source]); | |
4247 } | |
4248 | |
4249 void test_unusedElement_class_notUsed_inClassMember() { | |
4250 enableUnusedElement = true; | |
4251 Source source = addSource(r''' | |
4252 class _A { | |
4253 static staticMethod() { | |
4254 new _A(); | |
4255 } | |
4256 instanceMethod() { | |
4257 new _A(); | |
4258 } | |
4259 } | |
4260 '''); | |
4261 computeLibrarySourceErrors(source); | |
4262 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4263 verify([source]); | |
4264 } | |
4265 | |
4266 void test_unusedElement_class_notUsed_inConstructorName() { | |
4267 enableUnusedElement = true; | |
4268 Source source = addSource(r''' | |
4269 class _A { | |
4270 _A() {} | |
4271 _A.named() {} | |
4272 } | |
4273 '''); | |
4274 computeLibrarySourceErrors(source); | |
4275 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4276 verify([source]); | |
4277 } | |
4278 | |
4279 void test_unusedElement_class_notUsed_isExpression() { | |
4280 enableUnusedElement = true; | |
4281 Source source = addSource(r''' | |
4282 class _A {} | |
4283 main(p) { | |
4284 if (p is _A) { | |
4285 } | |
4286 } | |
4287 '''); | |
4288 computeLibrarySourceErrors(source); | |
4289 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4290 verify([source]); | |
4291 } | |
4292 | |
4293 void test_unusedElement_class_notUsed_noReference() { | |
4294 enableUnusedElement = true; | |
4295 Source source = addSource(r''' | |
4296 class _A {} | |
4297 main() { | |
4298 }'''); | |
4299 computeLibrarySourceErrors(source); | |
4300 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4301 verify([source]); | |
4302 } | |
4303 | |
4304 void test_unusedElement_class_notUsed_variableDeclaration() { | |
4305 enableUnusedElement = true; | |
4306 Source source = addSource(r''' | |
4307 class _A {} | |
4308 main() { | |
4309 _A v; | |
4310 print(v); | |
4311 } | |
4312 print(x) {} | |
4313 '''); | |
4314 computeLibrarySourceErrors(source); | |
4315 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4316 verify([source]); | |
4317 } | |
4318 | |
4319 void test_unusedElement_enum_isUsed_fieldReference() { | |
4320 enableUnusedElement = true; | |
4321 Source source = addSource(r''' | |
4322 enum _MyEnum {A, B, C} | |
4323 main() { | |
4324 print(_MyEnum.B); | |
4325 }'''); | |
4326 computeLibrarySourceErrors(source); | |
4327 assertNoErrors(source); | |
4328 verify([source]); | |
4329 } | |
4330 | |
4331 void test_unusedElement_enum_notUsed_noReference() { | |
4332 enableUnusedElement = true; | |
4333 Source source = addSource(r''' | |
4334 enum _MyEnum {A, B, C} | |
4335 main() { | |
4336 }'''); | |
4337 computeLibrarySourceErrors(source); | |
4338 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4339 verify([source]); | |
4340 } | |
4341 | |
4342 void test_unusedElement_functionLocal_isUsed_closure() { | |
4343 enableUnusedElement = true; | |
4344 Source source = addSource(r''' | |
4345 main() { | |
4346 print(() {}); | |
4347 } | |
4348 print(x) {} | |
4349 '''); | |
4350 computeLibrarySourceErrors(source); | |
4351 assertNoErrors(source); | |
4352 verify([source]); | |
4353 } | |
4354 | |
4355 void test_unusedElement_functionLocal_isUsed_invocation() { | |
4356 enableUnusedElement = true; | |
4357 Source source = addSource(r''' | |
4358 main() { | |
4359 f() {} | |
4360 f(); | |
4361 }'''); | |
4362 computeLibrarySourceErrors(source); | |
4363 assertNoErrors(source); | |
4364 verify([source]); | |
4365 } | |
4366 | |
4367 void test_unusedElement_functionLocal_isUsed_reference() { | |
4368 enableUnusedElement = true; | |
4369 Source source = addSource(r''' | |
4370 main() { | |
4371 f() {} | |
4372 print(f); | |
4373 } | |
4374 print(x) {} | |
4375 '''); | |
4376 computeLibrarySourceErrors(source); | |
4377 assertNoErrors(source); | |
4378 verify([source]); | |
4379 } | |
4380 | |
4381 void test_unusedElement_functionLocal_notUsed_noReference() { | |
4382 enableUnusedElement = true; | |
4383 Source source = addSource(r''' | |
4384 main() { | |
4385 f() {} | |
4386 }'''); | |
4387 computeLibrarySourceErrors(source); | |
4388 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4389 verify([source]); | |
4390 } | |
4391 | |
4392 void test_unusedElement_functionLocal_notUsed_referenceFromItself() { | |
4393 enableUnusedElement = true; | |
4394 Source source = addSource(r''' | |
4395 main() { | |
4396 _f(int p) { | |
4397 _f(p - 1); | |
4398 } | |
4399 }'''); | |
4400 computeLibrarySourceErrors(source); | |
4401 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4402 verify([source]); | |
4403 } | |
4404 | |
4405 void test_unusedElement_functionTop_isUsed_invocation() { | |
4406 enableUnusedElement = true; | |
4407 Source source = addSource(r''' | |
4408 _f() {} | |
4409 main() { | |
4410 _f(); | |
4411 }'''); | |
4412 computeLibrarySourceErrors(source); | |
4413 assertNoErrors(source); | |
4414 verify([source]); | |
4415 } | |
4416 | |
4417 void test_unusedElement_functionTop_isUsed_reference() { | |
4418 enableUnusedElement = true; | |
4419 Source source = addSource(r''' | |
4420 _f() {} | |
4421 main() { | |
4422 print(_f); | |
4423 } | |
4424 print(x) {} | |
4425 '''); | |
4426 computeLibrarySourceErrors(source); | |
4427 assertNoErrors(source); | |
4428 verify([source]); | |
4429 } | |
4430 | |
4431 void test_unusedElement_functionTop_notUsed_noReference() { | |
4432 enableUnusedElement = true; | |
4433 Source source = addSource(r''' | |
4434 _f() {} | |
4435 main() { | |
4436 }'''); | |
4437 computeLibrarySourceErrors(source); | |
4438 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4439 verify([source]); | |
4440 } | |
4441 | |
4442 void test_unusedElement_functionTop_notUsed_referenceFromItself() { | |
4443 enableUnusedElement = true; | |
4444 Source source = addSource(r''' | |
4445 _f(int p) { | |
4446 _f(p - 1); | |
4447 } | |
4448 main() { | |
4449 }'''); | |
4450 computeLibrarySourceErrors(source); | |
4451 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4452 verify([source]); | |
4453 } | |
4454 | |
4455 void test_unusedElement_functionTypeAlias_isUsed_isExpression() { | |
4456 enableUnusedElement = true; | |
4457 Source source = addSource(r''' | |
4458 typedef _F(a, b); | |
4459 main(f) { | |
4460 if (f is _F) { | |
4461 print('F'); | |
4462 } | |
4463 }'''); | |
4464 computeLibrarySourceErrors(source); | |
4465 assertNoErrors(source); | |
4466 verify([source]); | |
4467 } | |
4468 | |
4469 void test_unusedElement_functionTypeAlias_isUsed_reference() { | |
4470 enableUnusedElement = true; | |
4471 Source source = addSource(r''' | |
4472 typedef _F(a, b); | |
4473 main(_F f) { | |
4474 }'''); | |
4475 computeLibrarySourceErrors(source); | |
4476 assertNoErrors(source); | |
4477 verify([source]); | |
4478 } | |
4479 | |
4480 void test_unusedElement_functionTypeAlias_isUsed_typeArgument() { | |
4481 enableUnusedElement = true; | |
4482 Source source = addSource(r''' | |
4483 typedef _F(a, b); | |
4484 main() { | |
4485 var v = new List<_F>(); | |
4486 print(v); | |
4487 }'''); | |
4488 computeLibrarySourceErrors(source); | |
4489 assertNoErrors(source); | |
4490 verify([source]); | |
4491 } | |
4492 | |
4493 void test_unusedElement_functionTypeAlias_isUsed_variableDeclaration() { | |
4494 enableUnusedElement = true; | |
4495 Source source = addSource(r''' | |
4496 typedef _F(a, b); | |
4497 class A { | |
4498 _F f; | |
4499 }'''); | |
4500 computeLibrarySourceErrors(source); | |
4501 assertNoErrors(source); | |
4502 verify([source]); | |
4503 } | |
4504 | |
4505 void test_unusedElement_functionTypeAlias_notUsed_noReference() { | |
4506 enableUnusedElement = true; | |
4507 Source source = addSource(r''' | |
4508 typedef _F(a, b); | |
4509 main() { | |
4510 }'''); | |
4511 computeLibrarySourceErrors(source); | |
4512 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4513 verify([source]); | |
4514 } | |
4515 | |
4516 void test_unusedElement_getter_isUsed_invocation_implicitThis() { | |
4517 enableUnusedElement = true; | |
4518 Source source = addSource(r''' | |
4519 class A { | |
4520 get _g => null; | |
4521 useGetter() { | |
4522 var v = _g; | |
4523 } | |
4524 }'''); | |
4525 computeLibrarySourceErrors(source); | |
4526 assertNoErrors(source); | |
4527 verify([source]); | |
4528 } | |
4529 | |
4530 void test_unusedElement_getter_isUsed_invocation_PrefixedIdentifier() { | |
4531 enableUnusedElement = true; | |
4532 Source source = addSource(r''' | |
4533 class A { | |
4534 get _g => null; | |
4535 } | |
4536 main(A a) { | |
4537 var v = a._g; | |
4538 } | |
4539 '''); | |
4540 computeLibrarySourceErrors(source); | |
4541 assertNoErrors(source); | |
4542 verify([source]); | |
4543 } | |
4544 | |
4545 void test_unusedElement_getter_isUsed_invocation_PropertyAccess() { | |
4546 enableUnusedElement = true; | |
4547 Source source = addSource(r''' | |
4548 class A { | |
4549 get _g => null; | |
4550 } | |
4551 main() { | |
4552 var v = new A()._g; | |
4553 } | |
4554 '''); | |
4555 computeLibrarySourceErrors(source); | |
4556 assertNoErrors(source); | |
4557 verify([source]); | |
4558 } | |
4559 | |
4560 void test_unusedElement_getter_notUsed_noReference() { | |
4561 enableUnusedElement = true; | |
4562 Source source = addSource(r''' | |
4563 class A { | |
4564 get _g => null; | |
4565 }'''); | |
4566 computeLibrarySourceErrors(source); | |
4567 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4568 verify([source]); | |
4569 } | |
4570 | |
4571 void test_unusedElement_getter_notUsed_referenceFromItself() { | |
4572 enableUnusedElement = true; | |
4573 Source source = addSource(r''' | |
4574 class A { | |
4575 get _g { | |
4576 return _g; | |
4577 } | |
4578 }'''); | |
4579 computeLibrarySourceErrors(source); | |
4580 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4581 verify([source]); | |
4582 } | |
4583 | |
4584 void test_unusedElement_method_isUsed_hasReference_implicitThis() { | |
4585 enableUnusedElement = true; | |
4586 Source source = addSource(r''' | |
4587 class A { | |
4588 _m() {} | |
4589 useMethod() { | |
4590 print(_m); | |
4591 } | |
4592 } | |
4593 print(x) {} | |
4594 '''); | |
4595 computeLibrarySourceErrors(source); | |
4596 assertNoErrors(source); | |
4597 verify([source]); | |
4598 } | |
4599 | |
4600 void test_unusedElement_method_isUsed_hasReference_implicitThis_subclass() { | |
4601 enableUnusedElement = true; | |
4602 Source source = addSource(r''' | |
4603 class A { | |
4604 _m() {} | |
4605 useMethod() { | |
4606 print(_m); | |
4607 } | |
4608 } | |
4609 class B extends A { | |
4610 _m() {} | |
4611 } | |
4612 print(x) {} | |
4613 '''); | |
4614 computeLibrarySourceErrors(source); | |
4615 assertNoErrors(source); | |
4616 verify([source]); | |
4617 } | |
4618 | |
4619 void test_unusedElement_method_isUsed_hasReference_PrefixedIdentifier() { | |
4620 enableUnusedElement = true; | |
4621 Source source = addSource(r''' | |
4622 class A { | |
4623 _m() {} | |
4624 } | |
4625 main(A a) { | |
4626 a._m; | |
4627 }'''); | |
4628 computeLibrarySourceErrors(source); | |
4629 assertNoErrors(source); | |
4630 verify([source]); | |
4631 } | |
4632 | |
4633 void test_unusedElement_method_isUsed_hasReference_PropertyAccess() { | |
4634 enableUnusedElement = true; | |
4635 Source source = addSource(r''' | |
4636 class A { | |
4637 _m() {} | |
4638 } | |
4639 main() { | |
4640 new A()._m; | |
4641 }'''); | |
4642 computeLibrarySourceErrors(source); | |
4643 assertNoErrors(source); | |
4644 verify([source]); | |
4645 } | |
4646 | |
4647 void test_unusedElement_method_isUsed_invocation_implicitThis() { | |
4648 enableUnusedElement = true; | |
4649 Source source = addSource(r''' | |
4650 class A { | |
4651 _m() {} | |
4652 useMethod() { | |
4653 _m(); | |
4654 } | |
4655 }'''); | |
4656 computeLibrarySourceErrors(source); | |
4657 assertNoErrors(source); | |
4658 verify([source]); | |
4659 } | |
4660 | |
4661 void test_unusedElement_method_isUsed_invocation_implicitThis_subclass() { | |
4662 enableUnusedElement = true; | |
4663 Source source = addSource(r''' | |
4664 class A { | |
4665 _m() {} | |
4666 useMethod() { | |
4667 _m(); | |
4668 } | |
4669 } | |
4670 class B extends A { | |
4671 _m() {} | |
4672 }'''); | |
4673 computeLibrarySourceErrors(source); | |
4674 assertNoErrors(source); | |
4675 verify([source]); | |
4676 } | |
4677 | |
4678 void test_unusedElement_method_isUsed_invocation_MemberElement() { | |
4679 enableUnusedElement = true; | |
4680 Source source = addSource(r''' | |
4681 class A<T> { | |
4682 _m(T t) {} | |
4683 } | |
4684 main(A<int> a) { | |
4685 a._m(0); | |
4686 }'''); | |
4687 computeLibrarySourceErrors(source); | |
4688 assertNoErrors(source); | |
4689 verify([source]); | |
4690 } | |
4691 | |
4692 void test_unusedElement_method_isUsed_invocation_propagated() { | |
4693 enableUnusedElement = true; | |
4694 Source source = addSource(r''' | |
4695 class A { | |
4696 _m() {} | |
4697 } | |
4698 main() { | |
4699 var a = new A(); | |
4700 a._m(); | |
4701 }'''); | |
4702 computeLibrarySourceErrors(source); | |
4703 assertNoErrors(source); | |
4704 verify([source]); | |
4705 } | |
4706 | |
4707 void test_unusedElement_method_isUsed_invocation_static() { | |
4708 enableUnusedElement = true; | |
4709 Source source = addSource(r''' | |
4710 class A { | |
4711 _m() {} | |
4712 } | |
4713 main() { | |
4714 A a = new A(); | |
4715 a._m(); | |
4716 }'''); | |
4717 computeLibrarySourceErrors(source); | |
4718 assertNoErrors(source); | |
4719 verify([source]); | |
4720 } | |
4721 | |
4722 void test_unusedElement_method_isUsed_invocation_subclass() { | |
4723 enableUnusedElement = true; | |
4724 Source source = addSource(r''' | |
4725 class A { | |
4726 _m() {} | |
4727 } | |
4728 class B extends A { | |
4729 _m() {} | |
4730 } | |
4731 main(A a) { | |
4732 a._m(); | |
4733 }'''); | |
4734 computeLibrarySourceErrors(source); | |
4735 assertNoErrors(source); | |
4736 verify([source]); | |
4737 } | |
4738 | |
4739 void test_unusedElement_method_isUsed_notPrivate() { | |
4740 enableUnusedElement = true; | |
4741 Source source = addSource(r''' | |
4742 class A { | |
4743 m() {} | |
4744 } | |
4745 main() { | |
4746 }'''); | |
4747 computeLibrarySourceErrors(source); | |
4748 assertNoErrors(source); | |
4749 verify([source]); | |
4750 } | |
4751 | |
4752 void test_unusedElement_method_isUsed_staticInvocation() { | |
4753 enableUnusedElement = true; | |
4754 Source source = addSource(r''' | |
4755 class A { | |
4756 static _m() {} | |
4757 } | |
4758 main() { | |
4759 A._m(); | |
4760 }'''); | |
4761 computeLibrarySourceErrors(source); | |
4762 assertNoErrors(source); | |
4763 verify([source]); | |
4764 } | |
4765 | |
4766 void test_unusedElement_method_notUsed_noReference() { | |
4767 enableUnusedElement = true; | |
4768 Source source = addSource(r''' | |
4769 class A { | |
4770 static _m() {} | |
4771 }'''); | |
4772 computeLibrarySourceErrors(source); | |
4773 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4774 verify([source]); | |
4775 } | |
4776 | |
4777 void test_unusedElement_method_notUsed_referenceFromItself() { | |
4778 enableUnusedElement = true; | |
4779 Source source = addSource(r''' | |
4780 class A { | |
4781 static _m(int p) { | |
4782 _m(p - 1); | |
4783 } | |
4784 }'''); | |
4785 computeLibrarySourceErrors(source); | |
4786 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4787 verify([source]); | |
4788 } | |
4789 | |
4790 void test_unusedElement_setter_isUsed_invocation_implicitThis() { | |
4791 enableUnusedElement = true; | |
4792 Source source = addSource(r''' | |
4793 class A { | |
4794 set _s(x) {} | |
4795 useSetter() { | |
4796 _s = 42; | |
4797 } | |
4798 }'''); | |
4799 computeLibrarySourceErrors(source); | |
4800 assertNoErrors(source); | |
4801 verify([source]); | |
4802 } | |
4803 | |
4804 void test_unusedElement_setter_isUsed_invocation_PrefixedIdentifier() { | |
4805 enableUnusedElement = true; | |
4806 Source source = addSource(r''' | |
4807 class A { | |
4808 set _s(x) {} | |
4809 } | |
4810 main(A a) { | |
4811 a._s = 42; | |
4812 } | |
4813 '''); | |
4814 computeLibrarySourceErrors(source); | |
4815 assertNoErrors(source); | |
4816 verify([source]); | |
4817 } | |
4818 | |
4819 void test_unusedElement_setter_isUsed_invocation_PropertyAccess() { | |
4820 enableUnusedElement = true; | |
4821 Source source = addSource(r''' | |
4822 class A { | |
4823 set _s(x) {} | |
4824 } | |
4825 main() { | |
4826 new A()._s = 42; | |
4827 } | |
4828 '''); | |
4829 computeLibrarySourceErrors(source); | |
4830 assertNoErrors(source); | |
4831 verify([source]); | |
4832 } | |
4833 | |
4834 void test_unusedElement_setter_notUsed_noReference() { | |
4835 enableUnusedElement = true; | |
4836 Source source = addSource(r''' | |
4837 class A { | |
4838 set _s(x) {} | |
4839 }'''); | |
4840 computeLibrarySourceErrors(source); | |
4841 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4842 verify([source]); | |
4843 } | |
4844 | |
4845 void test_unusedElement_setter_notUsed_referenceFromItself() { | |
4846 enableUnusedElement = true; | |
4847 Source source = addSource(r''' | |
4848 class A { | |
4849 set _s(int x) { | |
4850 if (x > 5) { | |
4851 _s = x - 1; | |
4852 } | |
4853 } | |
4854 }'''); | |
4855 computeLibrarySourceErrors(source); | |
4856 assertErrors(source, [HintCode.UNUSED_ELEMENT]); | |
4857 verify([source]); | |
4858 } | |
4859 | |
4860 void test_unusedField_isUsed_argument() { | |
4861 enableUnusedElement = true; | |
4862 Source source = addSource(r''' | |
4863 class A { | |
4864 int _f = 0; | |
4865 main() { | |
4866 print(++_f); | |
4867 } | |
4868 } | |
4869 print(x) {}'''); | |
4870 computeLibrarySourceErrors(source); | |
4871 assertErrors(source); | |
4872 verify([source]); | |
4873 } | |
4874 | |
4875 void test_unusedField_isUsed_reference_implicitThis() { | |
4876 enableUnusedElement = true; | |
4877 Source source = addSource(r''' | |
4878 class A { | |
4879 int _f; | |
4880 main() { | |
4881 print(_f); | |
4882 } | |
4883 } | |
4884 print(x) {}'''); | |
4885 computeLibrarySourceErrors(source); | |
4886 assertErrors(source); | |
4887 verify([source]); | |
4888 } | |
4889 | |
4890 void test_unusedField_isUsed_reference_implicitThis_expressionFunctionBody() { | |
4891 enableUnusedElement = true; | |
4892 Source source = addSource(r''' | |
4893 class A { | |
4894 int _f; | |
4895 m() => _f; | |
4896 }'''); | |
4897 computeLibrarySourceErrors(source); | |
4898 assertErrors(source); | |
4899 verify([source]); | |
4900 } | |
4901 | |
4902 void test_unusedField_isUsed_reference_implicitThis_subclass() { | |
4903 enableUnusedElement = true; | |
4904 Source source = addSource(r''' | |
4905 class A { | |
4906 int _f; | |
4907 main() { | |
4908 print(_f); | |
4909 } | |
4910 } | |
4911 class B extends A { | |
4912 int _f; | |
4913 } | |
4914 print(x) {}'''); | |
4915 computeLibrarySourceErrors(source); | |
4916 assertErrors(source); | |
4917 verify([source]); | |
4918 } | |
4919 | |
4920 void test_unusedField_isUsed_reference_qualified_propagatedElement() { | |
4921 enableUnusedElement = true; | |
4922 Source source = addSource(r''' | |
4923 class A { | |
4924 int _f; | |
4925 } | |
4926 main() { | |
4927 var a = new A(); | |
4928 print(a._f); | |
4929 } | |
4930 print(x) {}'''); | |
4931 computeLibrarySourceErrors(source); | |
4932 assertErrors(source); | |
4933 verify([source]); | |
4934 } | |
4935 | |
4936 void test_unusedField_isUsed_reference_qualified_staticElement() { | |
4937 enableUnusedElement = true; | |
4938 Source source = addSource(r''' | |
4939 class A { | |
4940 int _f; | |
4941 } | |
4942 main() { | |
4943 A a = new A(); | |
4944 print(a._f); | |
4945 } | |
4946 print(x) {}'''); | |
4947 computeLibrarySourceErrors(source); | |
4948 assertErrors(source); | |
4949 verify([source]); | |
4950 } | |
4951 | |
4952 void test_unusedField_isUsed_reference_qualified_unresolved() { | |
4953 enableUnusedElement = true; | |
4954 Source source = addSource(r''' | |
4955 class A { | |
4956 int _f; | |
4957 } | |
4958 main(a) { | |
4959 print(a._f); | |
4960 } | |
4961 print(x) {}'''); | |
4962 computeLibrarySourceErrors(source); | |
4963 assertErrors(source); | |
4964 verify([source]); | |
4965 } | |
4966 | |
4967 void test_unusedField_notUsed_compoundAssign() { | |
4968 enableUnusedElement = true; | |
4969 Source source = addSource(r''' | |
4970 class A { | |
4971 int _f; | |
4972 main() { | |
4973 _f += 2; | |
4974 } | |
4975 }'''); | |
4976 computeLibrarySourceErrors(source); | |
4977 assertErrors(source, [HintCode.UNUSED_FIELD]); | |
4978 verify([source]); | |
4979 } | |
4980 | |
4981 void test_unusedField_notUsed_noReference() { | |
4982 enableUnusedElement = true; | |
4983 Source source = addSource(r''' | |
4984 class A { | |
4985 int _f; | |
4986 } | |
4987 '''); | |
4988 computeLibrarySourceErrors(source); | |
4989 assertErrors(source, [HintCode.UNUSED_FIELD]); | |
4990 verify([source]); | |
4991 } | |
4992 | |
4993 void test_unusedField_notUsed_postfixExpr() { | |
4994 enableUnusedElement = true; | |
4995 Source source = addSource(r''' | |
4996 class A { | |
4997 int _f = 0; | |
4998 main() { | |
4999 _f++; | |
5000 } | |
5001 }'''); | |
5002 computeLibrarySourceErrors(source); | |
5003 assertErrors(source, [HintCode.UNUSED_FIELD]); | |
5004 verify([source]); | |
5005 } | |
5006 | |
5007 void test_unusedField_notUsed_prefixExpr() { | |
5008 enableUnusedElement = true; | |
5009 Source source = addSource(r''' | |
5010 class A { | |
5011 int _f = 0; | |
5012 main() { | |
5013 ++_f; | |
5014 } | |
5015 }'''); | |
5016 computeLibrarySourceErrors(source); | |
5017 assertErrors(source, [HintCode.UNUSED_FIELD]); | |
5018 verify([source]); | |
5019 } | |
5020 | |
5021 void test_unusedField_notUsed_simpleAssignment() { | |
5022 enableUnusedElement = true; | |
5023 Source source = addSource(r''' | |
5024 class A { | |
5025 int _f; | |
5026 m() { | |
5027 _f = 1; | |
5028 } | |
5029 } | |
5030 main(A a) { | |
5031 a._f = 2; | |
5032 } | |
5033 '''); | |
5034 computeLibrarySourceErrors(source); | |
5035 assertErrors(source, [HintCode.UNUSED_FIELD]); | |
5036 verify([source]); | |
5037 } | |
5038 | |
5039 void test_unusedImport() { | |
5040 Source source = addSource(r''' | |
5041 library L; | |
5042 import 'lib1.dart';'''); | |
5043 Source source2 = addNamedSource("/lib1.dart", "library lib1;"); | |
5044 computeLibrarySourceErrors(source); | |
5045 assertErrors(source, [HintCode.UNUSED_IMPORT]); | |
5046 assertNoErrors(source2); | |
5047 verify([source, source2]); | |
5048 } | |
5049 | |
5050 void test_unusedImport_as() { | |
5051 Source source = addSource(r''' | |
5052 library L; | |
5053 import 'lib1.dart'; | |
5054 import 'lib1.dart' as one; | |
5055 one.A a;'''); | |
5056 Source source2 = addNamedSource( | |
5057 "/lib1.dart", | |
5058 r''' | |
5059 library lib1; | |
5060 class A {}'''); | |
5061 computeLibrarySourceErrors(source); | |
5062 assertErrors(source, [HintCode.UNUSED_IMPORT]); | |
5063 assertNoErrors(source2); | |
5064 verify([source, source2]); | |
5065 } | |
5066 | |
5067 void test_unusedImport_hide() { | |
5068 Source source = addSource(r''' | |
5069 library L; | |
5070 import 'lib1.dart'; | |
5071 import 'lib1.dart' hide A; | |
5072 A a;'''); | |
5073 Source source2 = addNamedSource( | |
5074 "/lib1.dart", | |
5075 r''' | |
5076 library lib1; | |
5077 class A {}'''); | |
5078 computeLibrarySourceErrors(source); | |
5079 assertErrors(source, [HintCode.UNUSED_IMPORT]); | |
5080 assertNoErrors(source2); | |
5081 verify([source, source2]); | |
5082 } | |
5083 | |
5084 void test_unusedImport_show() { | |
5085 Source source = addSource(r''' | |
5086 library L; | |
5087 import 'lib1.dart' show A; | |
5088 import 'lib1.dart' show B; | |
5089 A a;'''); | |
5090 Source source2 = addNamedSource( | |
5091 "/lib1.dart", | |
5092 r''' | |
5093 library lib1; | |
5094 class A {} | |
5095 class B {}'''); | |
5096 computeLibrarySourceErrors(source); | |
5097 assertErrors(source, [HintCode.UNUSED_IMPORT]); | |
5098 assertNoErrors(source2); | |
5099 verify([source, source2]); | |
5100 } | |
5101 | |
5102 void test_unusedLocalVariable_inCatch_exception() { | |
5103 enableUnusedLocalVariable = true; | |
5104 Source source = addSource(r''' | |
5105 main() { | |
5106 try { | |
5107 } on String catch (exception) { | |
5108 } | |
5109 }'''); | |
5110 computeLibrarySourceErrors(source); | |
5111 assertErrors(source, [HintCode.UNUSED_CATCH_CLAUSE]); | |
5112 verify([source]); | |
5113 } | |
5114 | |
5115 void test_unusedLocalVariable_inCatch_exception_hasStack() { | |
5116 enableUnusedLocalVariable = true; | |
5117 Source source = addSource(r''' | |
5118 main() { | |
5119 try { | |
5120 } catch (exception, stack) { | |
5121 print(stack); | |
5122 } | |
5123 }'''); | |
5124 computeLibrarySourceErrors(source); | |
5125 assertNoErrors(source); | |
5126 verify([source]); | |
5127 } | |
5128 | |
5129 void test_unusedLocalVariable_inCatch_exception_noOnClause() { | |
5130 enableUnusedLocalVariable = true; | |
5131 Source source = addSource(r''' | |
5132 main() { | |
5133 try { | |
5134 } catch (exception) { | |
5135 } | |
5136 }'''); | |
5137 computeLibrarySourceErrors(source); | |
5138 assertNoErrors(source); | |
5139 verify([source]); | |
5140 } | |
5141 | |
5142 void test_unusedLocalVariable_inCatch_stackTrace() { | |
5143 enableUnusedLocalVariable = true; | |
5144 Source source = addSource(r''' | |
5145 main() { | |
5146 try { | |
5147 } catch (exception, stackTrace) { | |
5148 } | |
5149 }'''); | |
5150 computeLibrarySourceErrors(source); | |
5151 assertErrors(source, [HintCode.UNUSED_CATCH_STACK]); | |
5152 verify([source]); | |
5153 } | |
5154 | |
5155 void test_unusedLocalVariable_inCatch_stackTrace_used() { | |
5156 enableUnusedLocalVariable = true; | |
5157 Source source = addSource(r''' | |
5158 main() { | |
5159 try { | |
5160 } catch (exception, stackTrace) { | |
5161 print('exception at $stackTrace'); | |
5162 } | |
5163 } | |
5164 print(x) {}'''); | |
5165 computeLibrarySourceErrors(source); | |
5166 assertErrors(source); | |
5167 verify([source]); | |
5168 } | |
5169 | |
5170 void test_unusedLocalVariable_inFor_underscore_ignored() { | |
5171 enableUnusedLocalVariable = true; | |
5172 Source source = addSource(r''' | |
5173 main() { | |
5174 for (var _ in [1,2,3]) { | |
5175 for (var __ in [4,5,6]) { | |
5176 // do something | |
5177 } | |
5178 } | |
5179 }'''); | |
5180 computeLibrarySourceErrors(source); | |
5181 assertErrors(source); | |
5182 verify([source]); | |
5183 } | |
5184 | |
5185 void test_unusedLocalVariable_inFunction() { | |
5186 enableUnusedLocalVariable = true; | |
5187 Source source = addSource(r''' | |
5188 main() { | |
5189 var v = 1; | |
5190 v = 2; | |
5191 }'''); | |
5192 computeLibrarySourceErrors(source); | |
5193 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); | |
5194 verify([source]); | |
5195 } | |
5196 | |
5197 void test_unusedLocalVariable_inMethod() { | |
5198 enableUnusedLocalVariable = true; | |
5199 Source source = addSource(r''' | |
5200 class A { | |
5201 foo() { | |
5202 var v = 1; | |
5203 v = 2; | |
5204 } | |
5205 }'''); | |
5206 computeLibrarySourceErrors(source); | |
5207 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); | |
5208 verify([source]); | |
5209 } | |
5210 | |
5211 void test_unusedLocalVariable_isInvoked() { | |
5212 enableUnusedLocalVariable = true; | |
5213 Source source = addSource(r''' | |
5214 typedef Foo(); | |
5215 main() { | |
5216 Foo foo; | |
5217 foo(); | |
5218 }'''); | |
5219 computeLibrarySourceErrors(source); | |
5220 assertErrors(source); | |
5221 verify([source]); | |
5222 } | |
5223 | |
5224 void test_unusedLocalVariable_isRead_notUsed_compoundAssign() { | |
5225 enableUnusedLocalVariable = true; | |
5226 Source source = addSource(r''' | |
5227 main() { | |
5228 var v = 1; | |
5229 v += 2; | |
5230 }'''); | |
5231 computeLibrarySourceErrors(source); | |
5232 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); | |
5233 verify([source]); | |
5234 } | |
5235 | |
5236 void test_unusedLocalVariable_isRead_notUsed_postfixExpr() { | |
5237 enableUnusedLocalVariable = true; | |
5238 Source source = addSource(r''' | |
5239 main() { | |
5240 var v = 1; | |
5241 v++; | |
5242 }'''); | |
5243 computeLibrarySourceErrors(source); | |
5244 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); | |
5245 verify([source]); | |
5246 } | |
5247 | |
5248 void test_unusedLocalVariable_isRead_notUsed_prefixExpr() { | |
5249 enableUnusedLocalVariable = true; | |
5250 Source source = addSource(r''' | |
5251 main() { | |
5252 var v = 1; | |
5253 ++v; | |
5254 }'''); | |
5255 computeLibrarySourceErrors(source); | |
5256 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); | |
5257 verify([source]); | |
5258 } | |
5259 | |
5260 void test_unusedLocalVariable_isRead_usedArgument() { | |
5261 enableUnusedLocalVariable = true; | |
5262 Source source = addSource(r''' | |
5263 main() { | |
5264 var v = 1; | |
5265 print(++v); | |
5266 } | |
5267 print(x) {}'''); | |
5268 computeLibrarySourceErrors(source); | |
5269 assertErrors(source); | |
5270 verify([source]); | |
5271 } | |
5272 | |
5273 void test_unusedLocalVariable_isRead_usedInvocationTarget() { | |
5274 enableUnusedLocalVariable = true; | |
5275 Source source = addSource(r''' | |
5276 class A { | |
5277 foo() {} | |
5278 } | |
5279 main() { | |
5280 var a = new A(); | |
5281 a.foo(); | |
5282 } | |
5283 '''); | |
5284 computeLibrarySourceErrors(source); | |
5285 assertErrors(source); | |
5286 verify([source]); | |
5287 } | |
5288 | |
5289 void test_useOfVoidResult_assignmentExpression_function() { | |
5290 Source source = addSource(r''' | |
5291 void f() {} | |
5292 class A { | |
5293 n() { | |
5294 var a; | |
5295 a = f(); | |
5296 } | |
5297 }'''); | |
5298 computeLibrarySourceErrors(source); | |
5299 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); | |
5300 verify([source]); | |
5301 } | |
5302 | |
5303 void test_useOfVoidResult_assignmentExpression_method() { | |
5304 Source source = addSource(r''' | |
5305 class A { | |
5306 void m() {} | |
5307 n() { | |
5308 var a; | |
5309 a = m(); | |
5310 } | |
5311 }'''); | |
5312 computeLibrarySourceErrors(source); | |
5313 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); | |
5314 verify([source]); | |
5315 } | |
5316 | |
5317 void test_useOfVoidResult_inForLoop() { | |
5318 Source source = addSource(r''' | |
5319 class A { | |
5320 void m() {} | |
5321 n() { | |
5322 for(var a = m();;) {} | |
5323 } | |
5324 }'''); | |
5325 computeLibrarySourceErrors(source); | |
5326 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); | |
5327 verify([source]); | |
5328 } | |
5329 | |
5330 void test_useOfVoidResult_variableDeclaration_function() { | |
5331 Source source = addSource(r''' | |
5332 void f() {} | |
5333 class A { | |
5334 n() { | |
5335 var a = f(); | |
5336 } | |
5337 }'''); | |
5338 computeLibrarySourceErrors(source); | |
5339 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); | |
5340 verify([source]); | |
5341 } | |
5342 | |
5343 void test_useOfVoidResult_variableDeclaration_method() { | |
5344 Source source = addSource(r''' | |
5345 class A { | |
5346 void m() {} | |
5347 n() { | |
5348 var a = m(); | |
5349 } | |
5350 }'''); | |
5351 computeLibrarySourceErrors(source); | |
5352 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); | |
5353 verify([source]); | |
5354 } | |
5355 | |
5356 void test_useOfVoidResult_variableDeclaration_method2() { | |
5357 Source source = addSource(r''' | |
5358 class A { | |
5359 void m() {} | |
5360 n() { | |
5361 var a = m(), b = m(); | |
5362 } | |
5363 }'''); | |
5364 computeLibrarySourceErrors(source); | |
5365 assertErrors( | |
5366 source, [HintCode.USE_OF_VOID_RESULT, HintCode.USE_OF_VOID_RESULT]); | |
5367 verify([source]); | |
5368 } | |
5369 } | |
5370 | |
5371 @reflectiveTest | |
5372 class InheritanceManagerTest { | |
5373 /** | |
5374 * The type provider used to access the types. | |
5375 */ | |
5376 TestTypeProvider _typeProvider; | |
5377 | |
5378 /** | |
5379 * The library containing the code being resolved. | |
5380 */ | |
5381 LibraryElementImpl _definingLibrary; | |
5382 | |
5383 /** | |
5384 * The inheritance manager being tested. | |
5385 */ | |
5386 InheritanceManager _inheritanceManager; | |
5387 | |
5388 /** | |
5389 * The number of members that Object implements (as determined by [TestTypePro
vider]). | |
5390 */ | |
5391 int _numOfMembersInObject = 0; | |
5392 | |
5393 void setUp() { | |
5394 _typeProvider = new TestTypeProvider(); | |
5395 _inheritanceManager = _createInheritanceManager(); | |
5396 InterfaceType objectType = _typeProvider.objectType; | |
5397 _numOfMembersInObject = | |
5398 objectType.methods.length + objectType.accessors.length; | |
5399 } | |
5400 | |
5401 void test_getMapOfMembersInheritedFromClasses_accessor_extends() { | |
5402 // class A { int get g; } | |
5403 // class B extends A {} | |
5404 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5405 String getterName = "g"; | |
5406 PropertyAccessorElement getterG = | |
5407 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
5408 classA.accessors = <PropertyAccessorElement>[getterG]; | |
5409 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
5410 MemberMap mapB = | |
5411 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); | |
5412 MemberMap mapA = | |
5413 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); | |
5414 expect(mapA.size, _numOfMembersInObject); | |
5415 expect(mapB.size, _numOfMembersInObject + 1); | |
5416 expect(mapB.get(getterName), same(getterG)); | |
5417 _assertNoErrors(classA); | |
5418 _assertNoErrors(classB); | |
5419 } | |
5420 | |
5421 void test_getMapOfMembersInheritedFromClasses_accessor_implements() { | |
5422 // class A { int get g; } | |
5423 // class B implements A {} | |
5424 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5425 String getterName = "g"; | |
5426 PropertyAccessorElement getterG = | |
5427 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
5428 classA.accessors = <PropertyAccessorElement>[getterG]; | |
5429 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5430 classB.interfaces = <InterfaceType>[classA.type]; | |
5431 MemberMap mapB = | |
5432 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); | |
5433 MemberMap mapA = | |
5434 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); | |
5435 expect(mapA.size, _numOfMembersInObject); | |
5436 expect(mapB.size, _numOfMembersInObject); | |
5437 expect(mapB.get(getterName), isNull); | |
5438 _assertNoErrors(classA); | |
5439 _assertNoErrors(classB); | |
5440 } | |
5441 | |
5442 void test_getMapOfMembersInheritedFromClasses_accessor_with() { | |
5443 // class A { int get g; } | |
5444 // class B extends Object with A {} | |
5445 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5446 String getterName = "g"; | |
5447 PropertyAccessorElement getterG = | |
5448 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
5449 classA.accessors = <PropertyAccessorElement>[getterG]; | |
5450 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5451 classB.mixins = <InterfaceType>[classA.type]; | |
5452 MemberMap mapB = | |
5453 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); | |
5454 MemberMap mapA = | |
5455 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); | |
5456 expect(mapA.size, _numOfMembersInObject); | |
5457 expect(mapB.size, _numOfMembersInObject + 1); | |
5458 expect(mapB.get(getterName), same(getterG)); | |
5459 _assertNoErrors(classA); | |
5460 _assertNoErrors(classB); | |
5461 } | |
5462 | |
5463 void test_getMapOfMembersInheritedFromClasses_implicitExtends() { | |
5464 // class A {} | |
5465 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5466 MemberMap mapA = | |
5467 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); | |
5468 expect(mapA.size, _numOfMembersInObject); | |
5469 _assertNoErrors(classA); | |
5470 } | |
5471 | |
5472 void test_getMapOfMembersInheritedFromClasses_method_extends() { | |
5473 // class A { int g(); } | |
5474 // class B extends A {} | |
5475 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5476 String methodName = "m"; | |
5477 MethodElement methodM = | |
5478 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5479 classA.methods = <MethodElement>[methodM]; | |
5480 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5481 classB.supertype = classA.type; | |
5482 MemberMap mapB = | |
5483 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); | |
5484 MemberMap mapA = | |
5485 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); | |
5486 expect(mapA.size, _numOfMembersInObject); | |
5487 expect(mapB.size, _numOfMembersInObject + 1); | |
5488 expect(mapB.get(methodName), same(methodM)); | |
5489 _assertNoErrors(classA); | |
5490 _assertNoErrors(classB); | |
5491 } | |
5492 | |
5493 void test_getMapOfMembersInheritedFromClasses_method_implements() { | |
5494 // class A { int g(); } | |
5495 // class B implements A {} | |
5496 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5497 String methodName = "m"; | |
5498 MethodElement methodM = | |
5499 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5500 classA.methods = <MethodElement>[methodM]; | |
5501 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5502 classB.interfaces = <InterfaceType>[classA.type]; | |
5503 MemberMap mapB = | |
5504 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); | |
5505 MemberMap mapA = | |
5506 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); | |
5507 expect(mapA.size, _numOfMembersInObject); | |
5508 expect(mapB.size, _numOfMembersInObject); | |
5509 expect(mapB.get(methodName), isNull); | |
5510 _assertNoErrors(classA); | |
5511 _assertNoErrors(classB); | |
5512 } | |
5513 | |
5514 void test_getMapOfMembersInheritedFromClasses_method_with() { | |
5515 // class A { int g(); } | |
5516 // class B extends Object with A {} | |
5517 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5518 String methodName = "m"; | |
5519 MethodElement methodM = | |
5520 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5521 classA.methods = <MethodElement>[methodM]; | |
5522 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5523 classB.mixins = <InterfaceType>[classA.type]; | |
5524 MemberMap mapB = | |
5525 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); | |
5526 MemberMap mapA = | |
5527 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); | |
5528 expect(mapA.size, _numOfMembersInObject); | |
5529 expect(mapB.size, _numOfMembersInObject + 1); | |
5530 expect(mapB.get(methodName), same(methodM)); | |
5531 _assertNoErrors(classA); | |
5532 _assertNoErrors(classB); | |
5533 } | |
5534 | |
5535 void test_getMapOfMembersInheritedFromClasses_method_with_two_mixins() { | |
5536 // class A1 { int m(); } | |
5537 // class A2 { int m(); } | |
5538 // class B extends Object with A1, A2 {} | |
5539 ClassElementImpl classA1 = ElementFactory.classElement2("A1"); | |
5540 String methodName = "m"; | |
5541 MethodElement methodA1M = | |
5542 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5543 classA1.methods = <MethodElement>[methodA1M]; | |
5544 ClassElementImpl classA2 = ElementFactory.classElement2("A2"); | |
5545 MethodElement methodA2M = | |
5546 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5547 classA2.methods = <MethodElement>[methodA2M]; | |
5548 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5549 classB.mixins = <InterfaceType>[classA1.type, classA2.type]; | |
5550 MemberMap mapB = | |
5551 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); | |
5552 expect(mapB.get(methodName), same(methodA2M)); | |
5553 _assertNoErrors(classA1); | |
5554 _assertNoErrors(classA2); | |
5555 _assertNoErrors(classB); | |
5556 } | |
5557 | |
5558 void test_getMapOfMembersInheritedFromInterfaces_accessor_extends() { | |
5559 // class A { int get g; } | |
5560 // class B extends A {} | |
5561 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5562 String getterName = "g"; | |
5563 PropertyAccessorElement getterG = | |
5564 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
5565 classA.accessors = <PropertyAccessorElement>[getterG]; | |
5566 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
5567 MemberMap mapB = | |
5568 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); | |
5569 MemberMap mapA = | |
5570 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5571 expect(mapA.size, _numOfMembersInObject); | |
5572 expect(mapB.size, _numOfMembersInObject + 1); | |
5573 expect(mapB.get(getterName), same(getterG)); | |
5574 _assertNoErrors(classA); | |
5575 _assertNoErrors(classB); | |
5576 } | |
5577 | |
5578 void test_getMapOfMembersInheritedFromInterfaces_accessor_implements() { | |
5579 // class A { int get g; } | |
5580 // class B implements A {} | |
5581 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5582 String getterName = "g"; | |
5583 PropertyAccessorElement getterG = | |
5584 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
5585 classA.accessors = <PropertyAccessorElement>[getterG]; | |
5586 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5587 classB.interfaces = <InterfaceType>[classA.type]; | |
5588 MemberMap mapB = | |
5589 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); | |
5590 MemberMap mapA = | |
5591 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5592 expect(mapA.size, _numOfMembersInObject); | |
5593 expect(mapB.size, _numOfMembersInObject + 1); | |
5594 expect(mapB.get(getterName), same(getterG)); | |
5595 _assertNoErrors(classA); | |
5596 _assertNoErrors(classB); | |
5597 } | |
5598 | |
5599 void test_getMapOfMembersInheritedFromInterfaces_accessor_with() { | |
5600 // class A { int get g; } | |
5601 // class B extends Object with A {} | |
5602 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5603 String getterName = "g"; | |
5604 PropertyAccessorElement getterG = | |
5605 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
5606 classA.accessors = <PropertyAccessorElement>[getterG]; | |
5607 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5608 classB.mixins = <InterfaceType>[classA.type]; | |
5609 MemberMap mapB = | |
5610 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); | |
5611 MemberMap mapA = | |
5612 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5613 expect(mapA.size, _numOfMembersInObject); | |
5614 expect(mapB.size, _numOfMembersInObject + 1); | |
5615 expect(mapB.get(getterName), same(getterG)); | |
5616 _assertNoErrors(classA); | |
5617 _assertNoErrors(classB); | |
5618 } | |
5619 | |
5620 void test_getMapOfMembersInheritedFromInterfaces_implicitExtends() { | |
5621 // class A {} | |
5622 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5623 MemberMap mapA = | |
5624 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5625 expect(mapA.size, _numOfMembersInObject); | |
5626 _assertNoErrors(classA); | |
5627 } | |
5628 | |
5629 void | |
5630 test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_
getter_method() { | |
5631 // class I1 { int m(); } | |
5632 // class I2 { int get m; } | |
5633 // class A implements I2, I1 {} | |
5634 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5635 String methodName = "m"; | |
5636 MethodElement methodM = | |
5637 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5638 classI1.methods = <MethodElement>[methodM]; | |
5639 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5640 PropertyAccessorElement getter = | |
5641 ElementFactory.getterElement(methodName, false, _typeProvider.intType); | |
5642 classI2.accessors = <PropertyAccessorElement>[getter]; | |
5643 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5644 classA.interfaces = <InterfaceType>[classI2.type, classI1.type]; | |
5645 MemberMap mapA = | |
5646 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5647 expect(mapA.size, _numOfMembersInObject); | |
5648 expect(mapA.get(methodName), isNull); | |
5649 _assertErrors(classA, | |
5650 [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]); | |
5651 } | |
5652 | |
5653 void | |
5654 test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_
int_str() { | |
5655 // class I1 { int m(); } | |
5656 // class I2 { String m(); } | |
5657 // class A implements I1, I2 {} | |
5658 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5659 String methodName = "m"; | |
5660 MethodElement methodM1 = | |
5661 ElementFactory.methodElement(methodName, null, [_typeProvider.intType]); | |
5662 classI1.methods = <MethodElement>[methodM1]; | |
5663 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5664 MethodElement methodM2 = ElementFactory | |
5665 .methodElement(methodName, null, [_typeProvider.stringType]); | |
5666 classI2.methods = <MethodElement>[methodM2]; | |
5667 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5668 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; | |
5669 MemberMap mapA = | |
5670 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5671 expect(mapA.size, _numOfMembersInObject); | |
5672 expect(mapA.get(methodName), isNull); | |
5673 _assertErrors( | |
5674 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); | |
5675 } | |
5676 | |
5677 void | |
5678 test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_
method_getter() { | |
5679 // class I1 { int m(); } | |
5680 // class I2 { int get m; } | |
5681 // class A implements I1, I2 {} | |
5682 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5683 String methodName = "m"; | |
5684 MethodElement methodM = | |
5685 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5686 classI1.methods = <MethodElement>[methodM]; | |
5687 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5688 PropertyAccessorElement getter = | |
5689 ElementFactory.getterElement(methodName, false, _typeProvider.intType); | |
5690 classI2.accessors = <PropertyAccessorElement>[getter]; | |
5691 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5692 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; | |
5693 MemberMap mapA = | |
5694 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5695 expect(mapA.size, _numOfMembersInObject); | |
5696 expect(mapA.get(methodName), isNull); | |
5697 _assertErrors(classA, | |
5698 [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]); | |
5699 } | |
5700 | |
5701 void | |
5702 test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_
numOfRequiredParams() { | |
5703 // class I1 { dynamic m(int, [int]); } | |
5704 // class I2 { dynamic m(int, int, int); } | |
5705 // class A implements I1, I2 {} | |
5706 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5707 String methodName = "m"; | |
5708 MethodElementImpl methodM1 = | |
5709 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); | |
5710 ParameterElementImpl parameter1 = | |
5711 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); | |
5712 parameter1.type = _typeProvider.intType; | |
5713 parameter1.parameterKind = ParameterKind.REQUIRED; | |
5714 ParameterElementImpl parameter2 = | |
5715 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); | |
5716 parameter2.type = _typeProvider.intType; | |
5717 parameter2.parameterKind = ParameterKind.POSITIONAL; | |
5718 methodM1.parameters = <ParameterElement>[parameter1, parameter2]; | |
5719 classI1.methods = <MethodElement>[methodM1]; | |
5720 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5721 MethodElementImpl methodM2 = | |
5722 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); | |
5723 ParameterElementImpl parameter3 = | |
5724 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); | |
5725 parameter3.type = _typeProvider.intType; | |
5726 parameter3.parameterKind = ParameterKind.REQUIRED; | |
5727 ParameterElementImpl parameter4 = | |
5728 new ParameterElementImpl.forNode(AstFactory.identifier3("a4")); | |
5729 parameter4.type = _typeProvider.intType; | |
5730 parameter4.parameterKind = ParameterKind.REQUIRED; | |
5731 ParameterElementImpl parameter5 = | |
5732 new ParameterElementImpl.forNode(AstFactory.identifier3("a5")); | |
5733 parameter5.type = _typeProvider.intType; | |
5734 parameter5.parameterKind = ParameterKind.REQUIRED; | |
5735 methodM2.parameters = <ParameterElement>[ | |
5736 parameter3, | |
5737 parameter4, | |
5738 parameter5 | |
5739 ]; | |
5740 classI2.methods = <MethodElement>[methodM2]; | |
5741 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5742 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; | |
5743 MemberMap mapA = | |
5744 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5745 expect(mapA.size, _numOfMembersInObject); | |
5746 expect(mapA.get(methodName), isNull); | |
5747 _assertErrors( | |
5748 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); | |
5749 } | |
5750 | |
5751 void | |
5752 test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance_
str_int() { | |
5753 // class I1 { int m(); } | |
5754 // class I2 { String m(); } | |
5755 // class A implements I2, I1 {} | |
5756 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5757 String methodName = "m"; | |
5758 MethodElement methodM1 = ElementFactory | |
5759 .methodElement(methodName, null, [_typeProvider.stringType]); | |
5760 classI1.methods = <MethodElement>[methodM1]; | |
5761 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5762 MethodElement methodM2 = | |
5763 ElementFactory.methodElement(methodName, null, [_typeProvider.intType]); | |
5764 classI2.methods = <MethodElement>[methodM2]; | |
5765 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5766 classA.interfaces = <InterfaceType>[classI2.type, classI1.type]; | |
5767 MemberMap mapA = | |
5768 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5769 expect(mapA.size, _numOfMembersInObject); | |
5770 expect(mapA.get(methodName), isNull); | |
5771 _assertErrors( | |
5772 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); | |
5773 } | |
5774 | |
5775 void test_getMapOfMembersInheritedFromInterfaces_method_extends() { | |
5776 // class A { int g(); } | |
5777 // class B extends A {} | |
5778 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5779 String methodName = "m"; | |
5780 MethodElement methodM = | |
5781 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5782 classA.methods = <MethodElement>[methodM]; | |
5783 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
5784 MemberMap mapB = | |
5785 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); | |
5786 MemberMap mapA = | |
5787 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5788 expect(mapA.size, _numOfMembersInObject); | |
5789 expect(mapB.size, _numOfMembersInObject + 1); | |
5790 expect(mapB.get(methodName), same(methodM)); | |
5791 _assertNoErrors(classA); | |
5792 _assertNoErrors(classB); | |
5793 } | |
5794 | |
5795 void test_getMapOfMembersInheritedFromInterfaces_method_implements() { | |
5796 // class A { int g(); } | |
5797 // class B implements A {} | |
5798 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5799 String methodName = "m"; | |
5800 MethodElement methodM = | |
5801 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5802 classA.methods = <MethodElement>[methodM]; | |
5803 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5804 classB.interfaces = <InterfaceType>[classA.type]; | |
5805 MemberMap mapB = | |
5806 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); | |
5807 MemberMap mapA = | |
5808 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5809 expect(mapA.size, _numOfMembersInObject); | |
5810 expect(mapB.size, _numOfMembersInObject + 1); | |
5811 expect(mapB.get(methodName), same(methodM)); | |
5812 _assertNoErrors(classA); | |
5813 _assertNoErrors(classB); | |
5814 } | |
5815 | |
5816 void test_getMapOfMembersInheritedFromInterfaces_method_with() { | |
5817 // class A { int g(); } | |
5818 // class B extends Object with A {} | |
5819 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5820 String methodName = "m"; | |
5821 MethodElement methodM = | |
5822 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
5823 classA.methods = <MethodElement>[methodM]; | |
5824 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
5825 classB.mixins = <InterfaceType>[classA.type]; | |
5826 MemberMap mapB = | |
5827 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); | |
5828 MemberMap mapA = | |
5829 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5830 expect(mapA.size, _numOfMembersInObject); | |
5831 expect(mapB.size, _numOfMembersInObject + 1); | |
5832 expect(mapB.get(methodName), same(methodM)); | |
5833 _assertNoErrors(classA); | |
5834 _assertNoErrors(classB); | |
5835 } | |
5836 | |
5837 void test_getMapOfMembersInheritedFromInterfaces_union_differentNames() { | |
5838 // class I1 { int m1(); } | |
5839 // class I2 { int m2(); } | |
5840 // class A implements I1, I2 {} | |
5841 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5842 String methodName1 = "m1"; | |
5843 MethodElement methodM1 = | |
5844 ElementFactory.methodElement(methodName1, _typeProvider.intType); | |
5845 classI1.methods = <MethodElement>[methodM1]; | |
5846 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5847 String methodName2 = "m2"; | |
5848 MethodElement methodM2 = | |
5849 ElementFactory.methodElement(methodName2, _typeProvider.intType); | |
5850 classI2.methods = <MethodElement>[methodM2]; | |
5851 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5852 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; | |
5853 MemberMap mapA = | |
5854 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5855 expect(mapA.size, _numOfMembersInObject + 2); | |
5856 expect(mapA.get(methodName1), same(methodM1)); | |
5857 expect(mapA.get(methodName2), same(methodM2)); | |
5858 _assertNoErrors(classA); | |
5859 } | |
5860 | |
5861 void | |
5862 test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_gette
rs() { | |
5863 // class I1 { int get g; } | |
5864 // class I2 { num get g; } | |
5865 // class A implements I1, I2 {} | |
5866 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5867 String accessorName = "g"; | |
5868 PropertyAccessorElement getter1 = ElementFactory.getterElement( | |
5869 accessorName, false, _typeProvider.intType); | |
5870 classI1.accessors = <PropertyAccessorElement>[getter1]; | |
5871 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5872 PropertyAccessorElement getter2 = ElementFactory.getterElement( | |
5873 accessorName, false, _typeProvider.numType); | |
5874 classI2.accessors = <PropertyAccessorElement>[getter2]; | |
5875 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5876 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; | |
5877 MemberMap mapA = | |
5878 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5879 expect(mapA.size, _numOfMembersInObject + 1); | |
5880 PropertyAccessorElement syntheticAccessor = ElementFactory.getterElement( | |
5881 accessorName, false, _typeProvider.dynamicType); | |
5882 expect(mapA.get(accessorName).type, syntheticAccessor.type); | |
5883 _assertNoErrors(classA); | |
5884 } | |
5885 | |
5886 void | |
5887 test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_metho
ds() { | |
5888 // class I1 { dynamic m(int); } | |
5889 // class I2 { dynamic m(num); } | |
5890 // class A implements I1, I2 {} | |
5891 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5892 String methodName = "m"; | |
5893 MethodElementImpl methodM1 = | |
5894 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); | |
5895 ParameterElementImpl parameter1 = | |
5896 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); | |
5897 parameter1.type = _typeProvider.intType; | |
5898 parameter1.parameterKind = ParameterKind.REQUIRED; | |
5899 methodM1.parameters = <ParameterElement>[parameter1]; | |
5900 classI1.methods = <MethodElement>[methodM1]; | |
5901 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5902 MethodElementImpl methodM2 = | |
5903 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); | |
5904 ParameterElementImpl parameter2 = | |
5905 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); | |
5906 parameter2.type = _typeProvider.numType; | |
5907 parameter2.parameterKind = ParameterKind.REQUIRED; | |
5908 methodM2.parameters = <ParameterElement>[parameter2]; | |
5909 classI2.methods = <MethodElement>[methodM2]; | |
5910 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5911 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; | |
5912 MemberMap mapA = | |
5913 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5914 expect(mapA.size, _numOfMembersInObject + 1); | |
5915 MethodElement syntheticMethod = ElementFactory.methodElement( | |
5916 methodName, _typeProvider.dynamicType, [_typeProvider.dynamicType]); | |
5917 expect(mapA.get(methodName).type, syntheticMethod.type); | |
5918 _assertNoErrors(classA); | |
5919 } | |
5920 | |
5921 void | |
5922 test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_sette
rs() { | |
5923 // class I1 { set s(int); } | |
5924 // class I2 { set s(num); } | |
5925 // class A implements I1, I2 {} | |
5926 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5927 String accessorName = "s"; | |
5928 PropertyAccessorElement setter1 = ElementFactory.setterElement( | |
5929 accessorName, false, _typeProvider.intType); | |
5930 classI1.accessors = <PropertyAccessorElement>[setter1]; | |
5931 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5932 PropertyAccessorElement setter2 = ElementFactory.setterElement( | |
5933 accessorName, false, _typeProvider.numType); | |
5934 classI2.accessors = <PropertyAccessorElement>[setter2]; | |
5935 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5936 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; | |
5937 MemberMap mapA = | |
5938 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
5939 expect(mapA.size, _numOfMembersInObject + 1); | |
5940 PropertyAccessorElementImpl syntheticAccessor = ElementFactory | |
5941 .setterElement(accessorName, false, _typeProvider.dynamicType); | |
5942 syntheticAccessor.returnType = _typeProvider.dynamicType; | |
5943 expect(mapA.get("$accessorName=").type, syntheticAccessor.type); | |
5944 _assertNoErrors(classA); | |
5945 } | |
5946 | |
5947 void | |
5948 test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_gette
rs() { | |
5949 // class A {} | |
5950 // class B extends A {} | |
5951 // class C extends B {} | |
5952 // class I1 { A get g; } | |
5953 // class I2 { B get g; } | |
5954 // class I3 { C get g; } | |
5955 // class D implements I1, I2, I3 {} | |
5956 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5957 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
5958 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); | |
5959 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
5960 String accessorName = "g"; | |
5961 PropertyAccessorElement getter1 = | |
5962 ElementFactory.getterElement(accessorName, false, classA.type); | |
5963 classI1.accessors = <PropertyAccessorElement>[getter1]; | |
5964 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
5965 PropertyAccessorElement getter2 = | |
5966 ElementFactory.getterElement(accessorName, false, classB.type); | |
5967 classI2.accessors = <PropertyAccessorElement>[getter2]; | |
5968 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); | |
5969 PropertyAccessorElement getter3 = | |
5970 ElementFactory.getterElement(accessorName, false, classC.type); | |
5971 classI3.accessors = <PropertyAccessorElement>[getter3]; | |
5972 ClassElementImpl classD = ElementFactory.classElement2("D"); | |
5973 classD.interfaces = <InterfaceType>[ | |
5974 classI1.type, | |
5975 classI2.type, | |
5976 classI3.type | |
5977 ]; | |
5978 MemberMap mapD = | |
5979 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); | |
5980 expect(mapD.size, _numOfMembersInObject + 1); | |
5981 PropertyAccessorElement syntheticAccessor = ElementFactory.getterElement( | |
5982 accessorName, false, _typeProvider.dynamicType); | |
5983 expect(mapD.get(accessorName).type, syntheticAccessor.type); | |
5984 _assertNoErrors(classD); | |
5985 } | |
5986 | |
5987 void | |
5988 test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_metho
ds() { | |
5989 // class A {} | |
5990 // class B extends A {} | |
5991 // class C extends B {} | |
5992 // class I1 { dynamic m(A a); } | |
5993 // class I2 { dynamic m(B b); } | |
5994 // class I3 { dynamic m(C c); } | |
5995 // class D implements I1, I2, I3 {} | |
5996 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
5997 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
5998 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); | |
5999 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
6000 String methodName = "m"; | |
6001 MethodElementImpl methodM1 = | |
6002 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); | |
6003 ParameterElementImpl parameter1 = | |
6004 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); | |
6005 parameter1.type = classA.type; | |
6006 parameter1.parameterKind = ParameterKind.REQUIRED; | |
6007 methodM1.parameters = <ParameterElement>[parameter1]; | |
6008 classI1.methods = <MethodElement>[methodM1]; | |
6009 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
6010 MethodElementImpl methodM2 = | |
6011 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); | |
6012 ParameterElementImpl parameter2 = | |
6013 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); | |
6014 parameter2.type = classB.type; | |
6015 parameter2.parameterKind = ParameterKind.REQUIRED; | |
6016 methodM2.parameters = <ParameterElement>[parameter2]; | |
6017 classI2.methods = <MethodElement>[methodM2]; | |
6018 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); | |
6019 MethodElementImpl methodM3 = | |
6020 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); | |
6021 ParameterElementImpl parameter3 = | |
6022 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); | |
6023 parameter3.type = classC.type; | |
6024 parameter3.parameterKind = ParameterKind.REQUIRED; | |
6025 methodM3.parameters = <ParameterElement>[parameter3]; | |
6026 classI3.methods = <MethodElement>[methodM3]; | |
6027 ClassElementImpl classD = ElementFactory.classElement2("D"); | |
6028 classD.interfaces = <InterfaceType>[ | |
6029 classI1.type, | |
6030 classI2.type, | |
6031 classI3.type | |
6032 ]; | |
6033 MemberMap mapD = | |
6034 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); | |
6035 expect(mapD.size, _numOfMembersInObject + 1); | |
6036 MethodElement syntheticMethod = ElementFactory.methodElement( | |
6037 methodName, _typeProvider.dynamicType, [_typeProvider.dynamicType]); | |
6038 expect(mapD.get(methodName).type, syntheticMethod.type); | |
6039 _assertNoErrors(classD); | |
6040 } | |
6041 | |
6042 void | |
6043 test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_sette
rs() { | |
6044 // class A {} | |
6045 // class B extends A {} | |
6046 // class C extends B {} | |
6047 // class I1 { set s(A); } | |
6048 // class I2 { set s(B); } | |
6049 // class I3 { set s(C); } | |
6050 // class D implements I1, I2, I3 {} | |
6051 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6052 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
6053 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); | |
6054 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
6055 String accessorName = "s"; | |
6056 PropertyAccessorElement setter1 = | |
6057 ElementFactory.setterElement(accessorName, false, classA.type); | |
6058 classI1.accessors = <PropertyAccessorElement>[setter1]; | |
6059 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
6060 PropertyAccessorElement setter2 = | |
6061 ElementFactory.setterElement(accessorName, false, classB.type); | |
6062 classI2.accessors = <PropertyAccessorElement>[setter2]; | |
6063 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); | |
6064 PropertyAccessorElement setter3 = | |
6065 ElementFactory.setterElement(accessorName, false, classC.type); | |
6066 classI3.accessors = <PropertyAccessorElement>[setter3]; | |
6067 ClassElementImpl classD = ElementFactory.classElement2("D"); | |
6068 classD.interfaces = <InterfaceType>[ | |
6069 classI1.type, | |
6070 classI2.type, | |
6071 classI3.type | |
6072 ]; | |
6073 MemberMap mapD = | |
6074 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); | |
6075 expect(mapD.size, _numOfMembersInObject + 1); | |
6076 PropertyAccessorElementImpl syntheticAccessor = ElementFactory | |
6077 .setterElement(accessorName, false, _typeProvider.dynamicType); | |
6078 syntheticAccessor.returnType = _typeProvider.dynamicType; | |
6079 expect(mapD.get("$accessorName=").type, syntheticAccessor.type); | |
6080 _assertNoErrors(classD); | |
6081 } | |
6082 | |
6083 void | |
6084 test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_2_methods() { | |
6085 // class I1 { int m(); } | |
6086 // class I2 { int m([int]); } | |
6087 // class A implements I1, I2 {} | |
6088 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
6089 String methodName = "m"; | |
6090 MethodElement methodM1 = | |
6091 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6092 classI1.methods = <MethodElement>[methodM1]; | |
6093 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
6094 MethodElementImpl methodM2 = | |
6095 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6096 ParameterElementImpl parameter1 = | |
6097 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); | |
6098 parameter1.type = _typeProvider.intType; | |
6099 parameter1.parameterKind = ParameterKind.POSITIONAL; | |
6100 methodM2.parameters = <ParameterElement>[parameter1]; | |
6101 classI2.methods = <MethodElement>[methodM2]; | |
6102 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6103 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; | |
6104 MemberMap mapA = | |
6105 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
6106 expect(mapA.size, _numOfMembersInObject + 1); | |
6107 expect(mapA.get(methodName), same(methodM2)); | |
6108 _assertNoErrors(classA); | |
6109 } | |
6110 | |
6111 void | |
6112 test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_3_methods() { | |
6113 // class I1 { int m(); } | |
6114 // class I2 { int m([int]); } | |
6115 // class I3 { int m([int, int]); } | |
6116 // class A implements I1, I2, I3 {} | |
6117 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
6118 String methodName = "m"; | |
6119 MethodElementImpl methodM1 = | |
6120 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6121 classI1.methods = <MethodElement>[methodM1]; | |
6122 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
6123 MethodElementImpl methodM2 = | |
6124 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6125 ParameterElementImpl parameter1 = | |
6126 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); | |
6127 parameter1.type = _typeProvider.intType; | |
6128 parameter1.parameterKind = ParameterKind.POSITIONAL; | |
6129 methodM1.parameters = <ParameterElement>[parameter1]; | |
6130 classI2.methods = <MethodElement>[methodM2]; | |
6131 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); | |
6132 MethodElementImpl methodM3 = | |
6133 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6134 ParameterElementImpl parameter2 = | |
6135 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); | |
6136 parameter2.type = _typeProvider.intType; | |
6137 parameter2.parameterKind = ParameterKind.POSITIONAL; | |
6138 ParameterElementImpl parameter3 = | |
6139 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); | |
6140 parameter3.type = _typeProvider.intType; | |
6141 parameter3.parameterKind = ParameterKind.POSITIONAL; | |
6142 methodM3.parameters = <ParameterElement>[parameter2, parameter3]; | |
6143 classI3.methods = <MethodElement>[methodM3]; | |
6144 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6145 classA.interfaces = <InterfaceType>[ | |
6146 classI1.type, | |
6147 classI2.type, | |
6148 classI3.type | |
6149 ]; | |
6150 MemberMap mapA = | |
6151 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
6152 expect(mapA.size, _numOfMembersInObject + 1); | |
6153 expect(mapA.get(methodName), same(methodM3)); | |
6154 _assertNoErrors(classA); | |
6155 } | |
6156 | |
6157 void | |
6158 test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_4_methods() { | |
6159 // class I1 { int m(); } | |
6160 // class I2 { int m(); } | |
6161 // class I3 { int m([int]); } | |
6162 // class I4 { int m([int, int]); } | |
6163 // class A implements I1, I2, I3, I4 {} | |
6164 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
6165 String methodName = "m"; | |
6166 MethodElement methodM1 = | |
6167 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6168 classI1.methods = <MethodElement>[methodM1]; | |
6169 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
6170 MethodElement methodM2 = | |
6171 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6172 classI2.methods = <MethodElement>[methodM2]; | |
6173 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); | |
6174 MethodElementImpl methodM3 = | |
6175 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6176 ParameterElementImpl parameter1 = | |
6177 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); | |
6178 parameter1.type = _typeProvider.intType; | |
6179 parameter1.parameterKind = ParameterKind.POSITIONAL; | |
6180 methodM3.parameters = <ParameterElement>[parameter1]; | |
6181 classI3.methods = <MethodElement>[methodM3]; | |
6182 ClassElementImpl classI4 = ElementFactory.classElement2("I4"); | |
6183 MethodElementImpl methodM4 = | |
6184 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6185 ParameterElementImpl parameter2 = | |
6186 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); | |
6187 parameter2.type = _typeProvider.intType; | |
6188 parameter2.parameterKind = ParameterKind.POSITIONAL; | |
6189 ParameterElementImpl parameter3 = | |
6190 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); | |
6191 parameter3.type = _typeProvider.intType; | |
6192 parameter3.parameterKind = ParameterKind.POSITIONAL; | |
6193 methodM4.parameters = <ParameterElement>[parameter2, parameter3]; | |
6194 classI4.methods = <MethodElement>[methodM4]; | |
6195 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6196 classA.interfaces = <InterfaceType>[ | |
6197 classI1.type, | |
6198 classI2.type, | |
6199 classI3.type, | |
6200 classI4.type | |
6201 ]; | |
6202 MemberMap mapA = | |
6203 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); | |
6204 expect(mapA.size, _numOfMembersInObject + 1); | |
6205 expect(mapA.get(methodName), same(methodM4)); | |
6206 _assertNoErrors(classA); | |
6207 } | |
6208 | |
6209 void test_lookupInheritance_interface_getter() { | |
6210 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6211 String getterName = "g"; | |
6212 PropertyAccessorElement getterG = | |
6213 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
6214 classA.accessors = <PropertyAccessorElement>[getterG]; | |
6215 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6216 classB.interfaces = <InterfaceType>[classA.type]; | |
6217 expect(_inheritanceManager.lookupInheritance(classB, getterName), | |
6218 same(getterG)); | |
6219 _assertNoErrors(classA); | |
6220 _assertNoErrors(classB); | |
6221 } | |
6222 | |
6223 void test_lookupInheritance_interface_method() { | |
6224 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6225 String methodName = "m"; | |
6226 MethodElement methodM = | |
6227 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6228 classA.methods = <MethodElement>[methodM]; | |
6229 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6230 classB.interfaces = <InterfaceType>[classA.type]; | |
6231 expect(_inheritanceManager.lookupInheritance(classB, methodName), | |
6232 same(methodM)); | |
6233 _assertNoErrors(classA); | |
6234 _assertNoErrors(classB); | |
6235 } | |
6236 | |
6237 void test_lookupInheritance_interface_setter() { | |
6238 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6239 String setterName = "s"; | |
6240 PropertyAccessorElement setterS = | |
6241 ElementFactory.setterElement(setterName, false, _typeProvider.intType); | |
6242 classA.accessors = <PropertyAccessorElement>[setterS]; | |
6243 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6244 classB.interfaces = <InterfaceType>[classA.type]; | |
6245 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), | |
6246 same(setterS)); | |
6247 _assertNoErrors(classA); | |
6248 _assertNoErrors(classB); | |
6249 } | |
6250 | |
6251 void test_lookupInheritance_interface_staticMember() { | |
6252 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6253 String methodName = "m"; | |
6254 MethodElement methodM = | |
6255 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6256 (methodM as MethodElementImpl).static = true; | |
6257 classA.methods = <MethodElement>[methodM]; | |
6258 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6259 classB.interfaces = <InterfaceType>[classA.type]; | |
6260 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); | |
6261 _assertNoErrors(classA); | |
6262 _assertNoErrors(classB); | |
6263 } | |
6264 | |
6265 void test_lookupInheritance_interfaces_infiniteLoop() { | |
6266 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6267 classA.interfaces = <InterfaceType>[classA.type]; | |
6268 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); | |
6269 _assertNoErrors(classA); | |
6270 } | |
6271 | |
6272 void test_lookupInheritance_interfaces_infiniteLoop2() { | |
6273 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6274 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6275 classA.interfaces = <InterfaceType>[classB.type]; | |
6276 classB.interfaces = <InterfaceType>[classA.type]; | |
6277 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); | |
6278 _assertNoErrors(classA); | |
6279 _assertNoErrors(classB); | |
6280 } | |
6281 | |
6282 void test_lookupInheritance_interfaces_union2() { | |
6283 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); | |
6284 String methodName1 = "m1"; | |
6285 MethodElement methodM1 = | |
6286 ElementFactory.methodElement(methodName1, _typeProvider.intType); | |
6287 classI1.methods = <MethodElement>[methodM1]; | |
6288 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); | |
6289 String methodName2 = "m2"; | |
6290 MethodElement methodM2 = | |
6291 ElementFactory.methodElement(methodName2, _typeProvider.intType); | |
6292 classI2.methods = <MethodElement>[methodM2]; | |
6293 classI2.interfaces = <InterfaceType>[classI1.type]; | |
6294 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6295 classA.interfaces = <InterfaceType>[classI2.type]; | |
6296 expect(_inheritanceManager.lookupInheritance(classA, methodName1), | |
6297 same(methodM1)); | |
6298 expect(_inheritanceManager.lookupInheritance(classA, methodName2), | |
6299 same(methodM2)); | |
6300 _assertNoErrors(classI1); | |
6301 _assertNoErrors(classI2); | |
6302 _assertNoErrors(classA); | |
6303 } | |
6304 | |
6305 void test_lookupInheritance_mixin_getter() { | |
6306 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6307 String getterName = "g"; | |
6308 PropertyAccessorElement getterG = | |
6309 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
6310 classA.accessors = <PropertyAccessorElement>[getterG]; | |
6311 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6312 classB.mixins = <InterfaceType>[classA.type]; | |
6313 expect(_inheritanceManager.lookupInheritance(classB, getterName), | |
6314 same(getterG)); | |
6315 _assertNoErrors(classA); | |
6316 _assertNoErrors(classB); | |
6317 } | |
6318 | |
6319 void test_lookupInheritance_mixin_method() { | |
6320 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6321 String methodName = "m"; | |
6322 MethodElement methodM = | |
6323 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6324 classA.methods = <MethodElement>[methodM]; | |
6325 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6326 classB.mixins = <InterfaceType>[classA.type]; | |
6327 expect(_inheritanceManager.lookupInheritance(classB, methodName), | |
6328 same(methodM)); | |
6329 _assertNoErrors(classA); | |
6330 _assertNoErrors(classB); | |
6331 } | |
6332 | |
6333 void test_lookupInheritance_mixin_setter() { | |
6334 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6335 String setterName = "s"; | |
6336 PropertyAccessorElement setterS = | |
6337 ElementFactory.setterElement(setterName, false, _typeProvider.intType); | |
6338 classA.accessors = <PropertyAccessorElement>[setterS]; | |
6339 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6340 classB.mixins = <InterfaceType>[classA.type]; | |
6341 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), | |
6342 same(setterS)); | |
6343 _assertNoErrors(classA); | |
6344 _assertNoErrors(classB); | |
6345 } | |
6346 | |
6347 void test_lookupInheritance_mixin_staticMember() { | |
6348 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6349 String methodName = "m"; | |
6350 MethodElement methodM = | |
6351 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6352 (methodM as MethodElementImpl).static = true; | |
6353 classA.methods = <MethodElement>[methodM]; | |
6354 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6355 classB.mixins = <InterfaceType>[classA.type]; | |
6356 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); | |
6357 _assertNoErrors(classA); | |
6358 _assertNoErrors(classB); | |
6359 } | |
6360 | |
6361 void test_lookupInheritance_noMember() { | |
6362 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6363 expect(_inheritanceManager.lookupInheritance(classA, "a"), isNull); | |
6364 _assertNoErrors(classA); | |
6365 } | |
6366 | |
6367 void test_lookupInheritance_superclass_getter() { | |
6368 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6369 String getterName = "g"; | |
6370 PropertyAccessorElement getterG = | |
6371 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
6372 classA.accessors = <PropertyAccessorElement>[getterG]; | |
6373 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
6374 expect(_inheritanceManager.lookupInheritance(classB, getterName), | |
6375 same(getterG)); | |
6376 _assertNoErrors(classA); | |
6377 _assertNoErrors(classB); | |
6378 } | |
6379 | |
6380 void test_lookupInheritance_superclass_infiniteLoop() { | |
6381 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6382 classA.supertype = classA.type; | |
6383 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); | |
6384 _assertNoErrors(classA); | |
6385 } | |
6386 | |
6387 void test_lookupInheritance_superclass_infiniteLoop2() { | |
6388 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6389 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6390 classA.supertype = classB.type; | |
6391 classB.supertype = classA.type; | |
6392 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); | |
6393 _assertNoErrors(classA); | |
6394 _assertNoErrors(classB); | |
6395 } | |
6396 | |
6397 void test_lookupInheritance_superclass_method() { | |
6398 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6399 String methodName = "m"; | |
6400 MethodElement methodM = | |
6401 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6402 classA.methods = <MethodElement>[methodM]; | |
6403 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
6404 expect(_inheritanceManager.lookupInheritance(classB, methodName), | |
6405 same(methodM)); | |
6406 _assertNoErrors(classA); | |
6407 _assertNoErrors(classB); | |
6408 } | |
6409 | |
6410 void test_lookupInheritance_superclass_setter() { | |
6411 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6412 String setterName = "s"; | |
6413 PropertyAccessorElement setterS = | |
6414 ElementFactory.setterElement(setterName, false, _typeProvider.intType); | |
6415 classA.accessors = <PropertyAccessorElement>[setterS]; | |
6416 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
6417 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), | |
6418 same(setterS)); | |
6419 _assertNoErrors(classA); | |
6420 _assertNoErrors(classB); | |
6421 } | |
6422 | |
6423 void test_lookupInheritance_superclass_staticMember() { | |
6424 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6425 String methodName = "m"; | |
6426 MethodElement methodM = | |
6427 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6428 (methodM as MethodElementImpl).static = true; | |
6429 classA.methods = <MethodElement>[methodM]; | |
6430 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
6431 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); | |
6432 _assertNoErrors(classA); | |
6433 _assertNoErrors(classB); | |
6434 } | |
6435 | |
6436 void test_lookupMember_getter() { | |
6437 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6438 String getterName = "g"; | |
6439 PropertyAccessorElement getterG = | |
6440 ElementFactory.getterElement(getterName, false, _typeProvider.intType); | |
6441 classA.accessors = <PropertyAccessorElement>[getterG]; | |
6442 expect(_inheritanceManager.lookupMember(classA, getterName), same(getterG)); | |
6443 _assertNoErrors(classA); | |
6444 } | |
6445 | |
6446 void test_lookupMember_getter_static() { | |
6447 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6448 String getterName = "g"; | |
6449 PropertyAccessorElement getterG = | |
6450 ElementFactory.getterElement(getterName, true, _typeProvider.intType); | |
6451 classA.accessors = <PropertyAccessorElement>[getterG]; | |
6452 expect(_inheritanceManager.lookupMember(classA, getterName), isNull); | |
6453 _assertNoErrors(classA); | |
6454 } | |
6455 | |
6456 void test_lookupMember_method() { | |
6457 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6458 String methodName = "m"; | |
6459 MethodElement methodM = | |
6460 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6461 classA.methods = <MethodElement>[methodM]; | |
6462 expect(_inheritanceManager.lookupMember(classA, methodName), same(methodM)); | |
6463 _assertNoErrors(classA); | |
6464 } | |
6465 | |
6466 void test_lookupMember_method_static() { | |
6467 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6468 String methodName = "m"; | |
6469 MethodElement methodM = | |
6470 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6471 (methodM as MethodElementImpl).static = true; | |
6472 classA.methods = <MethodElement>[methodM]; | |
6473 expect(_inheritanceManager.lookupMember(classA, methodName), isNull); | |
6474 _assertNoErrors(classA); | |
6475 } | |
6476 | |
6477 void test_lookupMember_noMember() { | |
6478 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6479 expect(_inheritanceManager.lookupMember(classA, "a"), isNull); | |
6480 _assertNoErrors(classA); | |
6481 } | |
6482 | |
6483 void test_lookupMember_setter() { | |
6484 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6485 String setterName = "s"; | |
6486 PropertyAccessorElement setterS = | |
6487 ElementFactory.setterElement(setterName, false, _typeProvider.intType); | |
6488 classA.accessors = <PropertyAccessorElement>[setterS]; | |
6489 expect(_inheritanceManager.lookupMember(classA, "$setterName="), | |
6490 same(setterS)); | |
6491 _assertNoErrors(classA); | |
6492 } | |
6493 | |
6494 void test_lookupMember_setter_static() { | |
6495 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6496 String setterName = "s"; | |
6497 PropertyAccessorElement setterS = | |
6498 ElementFactory.setterElement(setterName, true, _typeProvider.intType); | |
6499 classA.accessors = <PropertyAccessorElement>[setterS]; | |
6500 expect(_inheritanceManager.lookupMember(classA, setterName), isNull); | |
6501 _assertNoErrors(classA); | |
6502 } | |
6503 | |
6504 void test_lookupOverrides_noParentClasses() { | |
6505 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6506 String methodName = "m"; | |
6507 MethodElementImpl methodM = | |
6508 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6509 classA.methods = <MethodElement>[methodM]; | |
6510 expect( | |
6511 _inheritanceManager.lookupOverrides(classA, methodName), hasLength(0)); | |
6512 _assertNoErrors(classA); | |
6513 } | |
6514 | |
6515 void test_lookupOverrides_overrideBaseClass() { | |
6516 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6517 String methodName = "m"; | |
6518 MethodElementImpl methodMinA = | |
6519 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6520 classA.methods = <MethodElement>[methodMinA]; | |
6521 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | |
6522 MethodElementImpl methodMinB = | |
6523 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6524 classB.methods = <MethodElement>[methodMinB]; | |
6525 List<ExecutableElement> overrides = | |
6526 _inheritanceManager.lookupOverrides(classB, methodName); | |
6527 expect(overrides, unorderedEquals([methodMinA])); | |
6528 _assertNoErrors(classA); | |
6529 _assertNoErrors(classB); | |
6530 } | |
6531 | |
6532 void test_lookupOverrides_overrideInterface() { | |
6533 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6534 String methodName = "m"; | |
6535 MethodElementImpl methodMinA = | |
6536 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6537 classA.methods = <MethodElement>[methodMinA]; | |
6538 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6539 classB.interfaces = <InterfaceType>[classA.type]; | |
6540 MethodElementImpl methodMinB = | |
6541 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6542 classB.methods = <MethodElement>[methodMinB]; | |
6543 List<ExecutableElement> overrides = | |
6544 _inheritanceManager.lookupOverrides(classB, methodName); | |
6545 expect(overrides, unorderedEquals([methodMinA])); | |
6546 _assertNoErrors(classA); | |
6547 _assertNoErrors(classB); | |
6548 } | |
6549 | |
6550 void test_lookupOverrides_overrideTwoInterfaces() { | |
6551 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
6552 String methodName = "m"; | |
6553 MethodElementImpl methodMinA = | |
6554 ElementFactory.methodElement(methodName, _typeProvider.intType); | |
6555 classA.methods = <MethodElement>[methodMinA]; | |
6556 ClassElementImpl classB = ElementFactory.classElement2("B"); | |
6557 MethodElementImpl methodMinB = | |
6558 ElementFactory.methodElement(methodName, _typeProvider.doubleType); | |
6559 classB.methods = <MethodElement>[methodMinB]; | |
6560 ClassElementImpl classC = ElementFactory.classElement2("C"); | |
6561 classC.interfaces = <InterfaceType>[classA.type, classB.type]; | |
6562 MethodElementImpl methodMinC = | |
6563 ElementFactory.methodElement(methodName, _typeProvider.numType); | |
6564 classC.methods = <MethodElement>[methodMinC]; | |
6565 List<ExecutableElement> overrides = | |
6566 _inheritanceManager.lookupOverrides(classC, methodName); | |
6567 expect(overrides, unorderedEquals([methodMinA, methodMinB])); | |
6568 _assertNoErrors(classA); | |
6569 _assertNoErrors(classB); | |
6570 _assertNoErrors(classC); | |
6571 } | |
6572 | |
6573 void _assertErrors(ClassElement classElt, | |
6574 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { | |
6575 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
6576 HashSet<AnalysisError> actualErrors = | |
6577 _inheritanceManager.getErrors(classElt); | |
6578 if (actualErrors != null) { | |
6579 for (AnalysisError error in actualErrors) { | |
6580 errorListener.onError(error); | |
6581 } | |
6582 } | |
6583 errorListener.assertErrorsWithCodes(expectedErrorCodes); | |
6584 } | |
6585 | |
6586 void _assertNoErrors(ClassElement classElt) { | |
6587 _assertErrors(classElt); | |
6588 } | |
6589 | |
6590 /** | |
6591 * Create the inheritance manager used by the tests. | |
6592 * | |
6593 * @return the inheritance manager that was created | |
6594 */ | |
6595 InheritanceManager _createInheritanceManager() { | |
6596 AnalysisContext context = AnalysisContextFactory.contextWithCore(); | |
6597 FileBasedSource source = | |
6598 new FileBasedSource(FileUtilities2.createFile("/test.dart")); | |
6599 CompilationUnitElementImpl definingCompilationUnit = | |
6600 new CompilationUnitElementImpl("test.dart"); | |
6601 definingCompilationUnit.librarySource = | |
6602 definingCompilationUnit.source = source; | |
6603 _definingLibrary = ElementFactory.library(context, "test"); | |
6604 _definingLibrary.definingCompilationUnit = definingCompilationUnit; | |
6605 return new InheritanceManager(_definingLibrary); | |
6606 } | 320 } |
6607 } | 321 } |
6608 | 322 |
6609 @reflectiveTest | 323 @reflectiveTest |
6610 class LibraryImportScopeTest extends ResolverTestCase { | 324 class LibraryImportScopeTest extends ResolverTestCase { |
6611 void test_conflictingImports() { | 325 void test_conflictingImports() { |
6612 AnalysisContext context = AnalysisContextFactory.contextWithCore(); | 326 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
6613 String typeNameA = "A"; | 327 String typeNameA = "A"; |
6614 String typeNameB = "B"; | 328 String typeNameB = "B"; |
6615 String typeNameC = "C"; | 329 String typeNameC = "C"; |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6861 void test_MemberMap_put() { | 575 void test_MemberMap_put() { |
6862 MethodElement m1 = ElementFactory.methodElement("m1", _nullType); | 576 MethodElement m1 = ElementFactory.methodElement("m1", _nullType); |
6863 MemberMap map = new MemberMap(); | 577 MemberMap map = new MemberMap(); |
6864 expect(map.size, 0); | 578 expect(map.size, 0); |
6865 map.put(m1.name, m1); | 579 map.put(m1.name, m1); |
6866 expect(map.size, 1); | 580 expect(map.size, 1); |
6867 expect(map.get("m1"), m1); | 581 expect(map.get("m1"), m1); |
6868 } | 582 } |
6869 } | 583 } |
6870 | 584 |
6871 @reflectiveTest | |
6872 class NonHintCodeTest extends ResolverTestCase { | |
6873 void test_deadCode_deadBlock_conditionalElse_debugConst() { | |
6874 Source source = addSource(r''' | |
6875 const bool DEBUG = true; | |
6876 f() { | |
6877 DEBUG ? 1 : 2; | |
6878 }'''); | |
6879 computeLibrarySourceErrors(source); | |
6880 assertNoErrors(source); | |
6881 verify([source]); | |
6882 } | |
6883 | |
6884 void test_deadCode_deadBlock_conditionalIf_debugConst() { | |
6885 Source source = addSource(r''' | |
6886 const bool DEBUG = false; | |
6887 f() { | |
6888 DEBUG ? 1 : 2; | |
6889 }'''); | |
6890 computeLibrarySourceErrors(source); | |
6891 assertNoErrors(source); | |
6892 verify([source]); | |
6893 } | |
6894 | |
6895 void test_deadCode_deadBlock_else() { | |
6896 Source source = addSource(r''' | |
6897 const bool DEBUG = true; | |
6898 f() { | |
6899 if(DEBUG) {} else {} | |
6900 }'''); | |
6901 computeLibrarySourceErrors(source); | |
6902 assertNoErrors(source); | |
6903 verify([source]); | |
6904 } | |
6905 | |
6906 void test_deadCode_deadBlock_if_debugConst_prefixedIdentifier() { | |
6907 Source source = addSource(r''' | |
6908 class A { | |
6909 static const bool DEBUG = false; | |
6910 } | |
6911 f() { | |
6912 if(A.DEBUG) {} | |
6913 }'''); | |
6914 computeLibrarySourceErrors(source); | |
6915 assertNoErrors(source); | |
6916 verify([source]); | |
6917 } | |
6918 | |
6919 void test_deadCode_deadBlock_if_debugConst_prefixedIdentifier2() { | |
6920 Source source = addSource(r''' | |
6921 library L; | |
6922 import 'lib2.dart'; | |
6923 f() { | |
6924 if(A.DEBUG) {} | |
6925 }'''); | |
6926 addNamedSource( | |
6927 "/lib2.dart", | |
6928 r''' | |
6929 library lib2; | |
6930 class A { | |
6931 static const bool DEBUG = false; | |
6932 }'''); | |
6933 computeLibrarySourceErrors(source); | |
6934 assertNoErrors(source); | |
6935 verify([source]); | |
6936 } | |
6937 | |
6938 void test_deadCode_deadBlock_if_debugConst_propertyAccessor() { | |
6939 Source source = addSource(r''' | |
6940 library L; | |
6941 import 'lib2.dart' as LIB; | |
6942 f() { | |
6943 if(LIB.A.DEBUG) {} | |
6944 }'''); | |
6945 addNamedSource( | |
6946 "/lib2.dart", | |
6947 r''' | |
6948 library lib2; | |
6949 class A { | |
6950 static const bool DEBUG = false; | |
6951 }'''); | |
6952 computeLibrarySourceErrors(source); | |
6953 assertNoErrors(source); | |
6954 verify([source]); | |
6955 } | |
6956 | |
6957 void test_deadCode_deadBlock_if_debugConst_simpleIdentifier() { | |
6958 Source source = addSource(r''' | |
6959 const bool DEBUG = false; | |
6960 f() { | |
6961 if(DEBUG) {} | |
6962 }'''); | |
6963 computeLibrarySourceErrors(source); | |
6964 assertNoErrors(source); | |
6965 verify([source]); | |
6966 } | |
6967 | |
6968 void test_deadCode_deadBlock_while_debugConst() { | |
6969 Source source = addSource(r''' | |
6970 const bool DEBUG = false; | |
6971 f() { | |
6972 while(DEBUG) {} | |
6973 }'''); | |
6974 computeLibrarySourceErrors(source); | |
6975 assertNoErrors(source); | |
6976 verify([source]); | |
6977 } | |
6978 | |
6979 void test_deadCode_deadCatch_onCatchSubtype() { | |
6980 Source source = addSource(r''' | |
6981 class A {} | |
6982 class B extends A {} | |
6983 f() { | |
6984 try {} on B catch (e) {} on A catch (e) {} catch (e) {} | |
6985 }'''); | |
6986 computeLibrarySourceErrors(source); | |
6987 assertNoErrors(source); | |
6988 verify([source]); | |
6989 } | |
6990 | |
6991 void test_deadCode_deadOperandLHS_and_debugConst() { | |
6992 Source source = addSource(r''' | |
6993 const bool DEBUG = false; | |
6994 f() { | |
6995 bool b = DEBUG && false; | |
6996 }'''); | |
6997 computeLibrarySourceErrors(source); | |
6998 assertNoErrors(source); | |
6999 verify([source]); | |
7000 } | |
7001 | |
7002 void test_deadCode_deadOperandLHS_or_debugConst() { | |
7003 Source source = addSource(r''' | |
7004 const bool DEBUG = true; | |
7005 f() { | |
7006 bool b = DEBUG || true; | |
7007 }'''); | |
7008 computeLibrarySourceErrors(source); | |
7009 assertNoErrors(source); | |
7010 verify([source]); | |
7011 } | |
7012 | |
7013 void test_deprecatedAnnotationUse_classWithConstructor() { | |
7014 Source source = addSource(r''' | |
7015 @deprecated | |
7016 class C { | |
7017 C(); | |
7018 } | |
7019 '''); | |
7020 computeLibrarySourceErrors(source); | |
7021 assertNoErrors(source); | |
7022 verify([source]); | |
7023 } | |
7024 | |
7025 void test_divisionOptimization() { | |
7026 Source source = addSource(r''' | |
7027 f(int x, int y) { | |
7028 var v = x / y.toInt(); | |
7029 }'''); | |
7030 computeLibrarySourceErrors(source); | |
7031 assertNoErrors(source); | |
7032 verify([source]); | |
7033 } | |
7034 | |
7035 void test_divisionOptimization_supressIfDivisionNotDefinedInCore() { | |
7036 Source source = addSource(r''' | |
7037 f(x, y) { | |
7038 var v = (x / y).toInt(); | |
7039 }'''); | |
7040 computeLibrarySourceErrors(source); | |
7041 assertNoErrors(source); | |
7042 verify([source]); | |
7043 } | |
7044 | |
7045 void test_divisionOptimization_supressIfDivisionOverridden() { | |
7046 Source source = addSource(r''' | |
7047 class A { | |
7048 num operator /(x) { return x; } | |
7049 } | |
7050 f(A x, A y) { | |
7051 var v = (x / y).toInt(); | |
7052 }'''); | |
7053 computeLibrarySourceErrors(source); | |
7054 assertNoErrors(source); | |
7055 verify([source]); | |
7056 } | |
7057 | |
7058 void test_duplicateImport_as() { | |
7059 Source source = addSource(r''' | |
7060 library L; | |
7061 import 'lib1.dart'; | |
7062 import 'lib1.dart' as one; | |
7063 A a; | |
7064 one.A a2;'''); | |
7065 addNamedSource( | |
7066 "/lib1.dart", | |
7067 r''' | |
7068 library lib1; | |
7069 class A {}'''); | |
7070 computeLibrarySourceErrors(source); | |
7071 assertNoErrors(source); | |
7072 verify([source]); | |
7073 } | |
7074 | |
7075 void test_duplicateImport_hide() { | |
7076 Source source = addSource(r''' | |
7077 library L; | |
7078 import 'lib1.dart'; | |
7079 import 'lib1.dart' hide A; | |
7080 A a; | |
7081 B b;'''); | |
7082 addNamedSource( | |
7083 "/lib1.dart", | |
7084 r''' | |
7085 library lib1; | |
7086 class A {} | |
7087 class B {}'''); | |
7088 computeLibrarySourceErrors(source); | |
7089 assertNoErrors(source); | |
7090 verify([source]); | |
7091 } | |
7092 | |
7093 void test_duplicateImport_show() { | |
7094 Source source = addSource(r''' | |
7095 library L; | |
7096 import 'lib1.dart'; | |
7097 import 'lib1.dart' show A; | |
7098 A a; | |
7099 B b;'''); | |
7100 addNamedSource( | |
7101 "/lib1.dart", | |
7102 r''' | |
7103 library lib1; | |
7104 class A {} | |
7105 class B {}'''); | |
7106 computeLibrarySourceErrors(source); | |
7107 assertNoErrors(source); | |
7108 verify([source]); | |
7109 } | |
7110 | |
7111 void test_importDeferredLibraryWithLoadFunction() { | |
7112 resolveWithErrors(<String>[ | |
7113 r''' | |
7114 library lib1; | |
7115 f() {}''', | |
7116 r''' | |
7117 library root; | |
7118 import 'lib1.dart' deferred as lib1; | |
7119 main() { lib1.f(); }''' | |
7120 ], ErrorCode.EMPTY_LIST); | |
7121 } | |
7122 | |
7123 void test_issue20904BuggyTypePromotionAtIfJoin_1() { | |
7124 // https://code.google.com/p/dart/issues/detail?id=20904 | |
7125 Source source = addSource(r''' | |
7126 f(var message, var dynamic_) { | |
7127 if (message is Function) { | |
7128 message = dynamic_; | |
7129 } | |
7130 int s = message; | |
7131 }'''); | |
7132 computeLibrarySourceErrors(source); | |
7133 assertNoErrors(source); | |
7134 verify([source]); | |
7135 } | |
7136 | |
7137 void test_issue20904BuggyTypePromotionAtIfJoin_3() { | |
7138 // https://code.google.com/p/dart/issues/detail?id=20904 | |
7139 Source source = addSource(r''' | |
7140 f(var message) { | |
7141 var dynamic_; | |
7142 if (message is Function) { | |
7143 message = dynamic_; | |
7144 } else { | |
7145 return; | |
7146 } | |
7147 int s = message; | |
7148 }'''); | |
7149 computeLibrarySourceErrors(source); | |
7150 assertNoErrors(source); | |
7151 verify([source]); | |
7152 } | |
7153 | |
7154 void test_issue20904BuggyTypePromotionAtIfJoin_4() { | |
7155 // https://code.google.com/p/dart/issues/detail?id=20904 | |
7156 Source source = addSource(r''' | |
7157 f(var message) { | |
7158 if (message is Function) { | |
7159 message = ''; | |
7160 } else { | |
7161 return; | |
7162 } | |
7163 String s = message; | |
7164 }'''); | |
7165 computeLibrarySourceErrors(source); | |
7166 assertNoErrors(source); | |
7167 verify([source]); | |
7168 } | |
7169 | |
7170 void test_missingReturn_emptyFunctionBody() { | |
7171 Source source = addSource(r''' | |
7172 abstract class A { | |
7173 int m(); | |
7174 }'''); | |
7175 computeLibrarySourceErrors(source); | |
7176 assertNoErrors(source); | |
7177 verify([source]); | |
7178 } | |
7179 | |
7180 void test_missingReturn_expressionFunctionBody() { | |
7181 Source source = addSource("int f() => 0;"); | |
7182 computeLibrarySourceErrors(source); | |
7183 assertNoErrors(source); | |
7184 verify([source]); | |
7185 } | |
7186 | |
7187 void test_missingReturn_noReturnType() { | |
7188 Source source = addSource("f() {}"); | |
7189 computeLibrarySourceErrors(source); | |
7190 assertNoErrors(source); | |
7191 verify([source]); | |
7192 } | |
7193 | |
7194 void test_missingReturn_voidReturnType() { | |
7195 Source source = addSource("void f() {}"); | |
7196 computeLibrarySourceErrors(source); | |
7197 assertNoErrors(source); | |
7198 verify([source]); | |
7199 } | |
7200 | |
7201 void test_nullAwareInCondition_for_noCondition() { | |
7202 Source source = addSource(r''' | |
7203 m(x) { | |
7204 for (var v = x; ; v++) {} | |
7205 } | |
7206 '''); | |
7207 computeLibrarySourceErrors(source); | |
7208 assertNoErrors(source); | |
7209 verify([source]); | |
7210 } | |
7211 | |
7212 void test_nullAwareInCondition_if_notTopLevel() { | |
7213 Source source = addSource(r''' | |
7214 m(x) { | |
7215 if (x?.y == null) {} | |
7216 } | |
7217 '''); | |
7218 computeLibrarySourceErrors(source); | |
7219 assertNoErrors(source); | |
7220 verify([source]); | |
7221 } | |
7222 | |
7223 void test_overrideEqualsButNotHashCode() { | |
7224 Source source = addSource(r''' | |
7225 class A { | |
7226 bool operator ==(x) { return x; } | |
7227 get hashCode => 0; | |
7228 }'''); | |
7229 computeLibrarySourceErrors(source); | |
7230 assertNoErrors(source); | |
7231 verify([source]); | |
7232 } | |
7233 | |
7234 void test_overrideOnNonOverridingGetter_inInterface() { | |
7235 Source source = addSource(r''' | |
7236 library dart.core; | |
7237 const override = null; | |
7238 class A { | |
7239 int get m => 0; | |
7240 } | |
7241 class B implements A { | |
7242 @override | |
7243 int get m => 1; | |
7244 }'''); | |
7245 computeLibrarySourceErrors(source); | |
7246 assertNoErrors(source); | |
7247 verify([source]); | |
7248 } | |
7249 | |
7250 void test_overrideOnNonOverridingGetter_inSuperclass() { | |
7251 Source source = addSource(r''' | |
7252 library dart.core; | |
7253 const override = null; | |
7254 class A { | |
7255 int get m => 0; | |
7256 } | |
7257 class B extends A { | |
7258 @override | |
7259 int get m => 1; | |
7260 }'''); | |
7261 computeLibrarySourceErrors(source); | |
7262 assertNoErrors(source); | |
7263 verify([source]); | |
7264 } | |
7265 | |
7266 void test_overrideOnNonOverridingMethod_inInterface() { | |
7267 Source source = addSource(r''' | |
7268 library dart.core; | |
7269 const override = null; | |
7270 class A { | |
7271 int m() => 0; | |
7272 } | |
7273 class B implements A { | |
7274 @override | |
7275 int m() => 1; | |
7276 }'''); | |
7277 computeLibrarySourceErrors(source); | |
7278 assertNoErrors(source); | |
7279 verify([source]); | |
7280 } | |
7281 | |
7282 void test_overrideOnNonOverridingMethod_inSuperclass() { | |
7283 Source source = addSource(r''' | |
7284 library dart.core; | |
7285 const override = null; | |
7286 class A { | |
7287 int m() => 0; | |
7288 } | |
7289 class B extends A { | |
7290 @override | |
7291 int m() => 1; | |
7292 }'''); | |
7293 computeLibrarySourceErrors(source); | |
7294 assertNoErrors(source); | |
7295 verify([source]); | |
7296 } | |
7297 | |
7298 void test_overrideOnNonOverridingSetter_inInterface() { | |
7299 Source source = addSource(r''' | |
7300 library dart.core; | |
7301 const override = null; | |
7302 class A { | |
7303 set m(int x) {} | |
7304 } | |
7305 class B implements A { | |
7306 @override | |
7307 set m(int x) {} | |
7308 }'''); | |
7309 computeLibrarySourceErrors(source); | |
7310 assertNoErrors(source); | |
7311 verify([source]); | |
7312 } | |
7313 | |
7314 void test_overrideOnNonOverridingSetter_inSuperclass() { | |
7315 Source source = addSource(r''' | |
7316 library dart.core; | |
7317 const override = null; | |
7318 class A { | |
7319 set m(int x) {} | |
7320 } | |
7321 class B extends A { | |
7322 @override | |
7323 set m(int x) {} | |
7324 }'''); | |
7325 computeLibrarySourceErrors(source); | |
7326 assertNoErrors(source); | |
7327 verify([source]); | |
7328 } | |
7329 | |
7330 void test_propagatedFieldType() { | |
7331 Source source = addSource(r''' | |
7332 class A { } | |
7333 class X<T> { | |
7334 final x = new List<T>(); | |
7335 } | |
7336 class Z { | |
7337 final X<A> y = new X<A>(); | |
7338 foo() { | |
7339 y.x.add(new A()); | |
7340 } | |
7341 }'''); | |
7342 computeLibrarySourceErrors(source); | |
7343 assertNoErrors(source); | |
7344 verify([source]); | |
7345 } | |
7346 | |
7347 void test_proxy_annotation_prefixed() { | |
7348 Source source = addSource(r''' | |
7349 library L; | |
7350 @proxy | |
7351 class A {} | |
7352 f(var a) { | |
7353 a = new A(); | |
7354 a.m(); | |
7355 var x = a.g; | |
7356 a.s = 1; | |
7357 var y = a + a; | |
7358 a++; | |
7359 ++a; | |
7360 }'''); | |
7361 computeLibrarySourceErrors(source); | |
7362 assertNoErrors(source); | |
7363 } | |
7364 | |
7365 void test_proxy_annotation_prefixed2() { | |
7366 Source source = addSource(r''' | |
7367 library L; | |
7368 @proxy | |
7369 class A {} | |
7370 class B { | |
7371 f(var a) { | |
7372 a = new A(); | |
7373 a.m(); | |
7374 var x = a.g; | |
7375 a.s = 1; | |
7376 var y = a + a; | |
7377 a++; | |
7378 ++a; | |
7379 } | |
7380 }'''); | |
7381 computeLibrarySourceErrors(source); | |
7382 assertNoErrors(source); | |
7383 } | |
7384 | |
7385 void test_proxy_annotation_prefixed3() { | |
7386 Source source = addSource(r''' | |
7387 library L; | |
7388 class B { | |
7389 f(var a) { | |
7390 a = new A(); | |
7391 a.m(); | |
7392 var x = a.g; | |
7393 a.s = 1; | |
7394 var y = a + a; | |
7395 a++; | |
7396 ++a; | |
7397 } | |
7398 } | |
7399 @proxy | |
7400 class A {}'''); | |
7401 computeLibrarySourceErrors(source); | |
7402 assertNoErrors(source); | |
7403 } | |
7404 | |
7405 void test_undefinedGetter_inSubtype() { | |
7406 Source source = addSource(r''' | |
7407 class A {} | |
7408 class B extends A { | |
7409 get b => 0; | |
7410 } | |
7411 f(var a) { | |
7412 if(a is A) { | |
7413 return a.b; | |
7414 } | |
7415 }'''); | |
7416 computeLibrarySourceErrors(source); | |
7417 assertNoErrors(source); | |
7418 } | |
7419 | |
7420 void test_undefinedMethod_assignmentExpression_inSubtype() { | |
7421 Source source = addSource(r''' | |
7422 class A {} | |
7423 class B extends A { | |
7424 operator +(B b) {return new B();} | |
7425 } | |
7426 f(var a, var a2) { | |
7427 a = new A(); | |
7428 a2 = new A(); | |
7429 a += a2; | |
7430 }'''); | |
7431 computeLibrarySourceErrors(source); | |
7432 assertNoErrors(source); | |
7433 } | |
7434 | |
7435 void test_undefinedMethod_dynamic() { | |
7436 Source source = addSource(r''' | |
7437 class D<T extends dynamic> { | |
7438 fieldAccess(T t) => t.abc; | |
7439 methodAccess(T t) => t.xyz(1, 2, 'three'); | |
7440 }'''); | |
7441 computeLibrarySourceErrors(source); | |
7442 assertNoErrors(source); | |
7443 } | |
7444 | |
7445 void test_undefinedMethod_inSubtype() { | |
7446 Source source = addSource(r''' | |
7447 class A {} | |
7448 class B extends A { | |
7449 b() {} | |
7450 } | |
7451 f() { | |
7452 var a = new A(); | |
7453 a.b(); | |
7454 }'''); | |
7455 computeLibrarySourceErrors(source); | |
7456 assertNoErrors(source); | |
7457 } | |
7458 | |
7459 void test_undefinedMethod_unionType_all() { | |
7460 Source source = addSource(r''' | |
7461 class A { | |
7462 int m(int x) => 0; | |
7463 } | |
7464 class B { | |
7465 String m() => '0'; | |
7466 } | |
7467 f(A a, B b) { | |
7468 var ab; | |
7469 if (0 < 1) { | |
7470 ab = a; | |
7471 } else { | |
7472 ab = b; | |
7473 } | |
7474 ab.m(); | |
7475 }'''); | |
7476 computeLibrarySourceErrors(source); | |
7477 assertNoErrors(source); | |
7478 } | |
7479 | |
7480 void test_undefinedMethod_unionType_some() { | |
7481 Source source = addSource(r''' | |
7482 class A { | |
7483 int m(int x) => 0; | |
7484 } | |
7485 class B {} | |
7486 f(A a, B b) { | |
7487 var ab; | |
7488 if (0 < 1) { | |
7489 ab = a; | |
7490 } else { | |
7491 ab = b; | |
7492 } | |
7493 ab.m(0); | |
7494 }'''); | |
7495 computeLibrarySourceErrors(source); | |
7496 assertNoErrors(source); | |
7497 } | |
7498 | |
7499 void test_undefinedOperator_binaryExpression_inSubtype() { | |
7500 Source source = addSource(r''' | |
7501 class A {} | |
7502 class B extends A { | |
7503 operator +(B b) {} | |
7504 } | |
7505 f(var a) { | |
7506 if(a is A) { | |
7507 a + 1; | |
7508 } | |
7509 }'''); | |
7510 computeLibrarySourceErrors(source); | |
7511 assertNoErrors(source); | |
7512 } | |
7513 | |
7514 void test_undefinedOperator_indexBoth_inSubtype() { | |
7515 Source source = addSource(r''' | |
7516 class A {} | |
7517 class B extends A { | |
7518 operator [](int index) {} | |
7519 } | |
7520 f(var a) { | |
7521 if(a is A) { | |
7522 a[0]++; | |
7523 } | |
7524 }'''); | |
7525 computeLibrarySourceErrors(source); | |
7526 assertNoErrors(source); | |
7527 } | |
7528 | |
7529 void test_undefinedOperator_indexGetter_inSubtype() { | |
7530 Source source = addSource(r''' | |
7531 class A {} | |
7532 class B extends A { | |
7533 operator [](int index) {} | |
7534 } | |
7535 f(var a) { | |
7536 if(a is A) { | |
7537 a[0]; | |
7538 } | |
7539 }'''); | |
7540 computeLibrarySourceErrors(source); | |
7541 assertNoErrors(source); | |
7542 } | |
7543 | |
7544 void test_undefinedOperator_indexSetter_inSubtype() { | |
7545 Source source = addSource(r''' | |
7546 class A {} | |
7547 class B extends A { | |
7548 operator []=(i, v) {} | |
7549 } | |
7550 f(var a) { | |
7551 if(a is A) { | |
7552 a[0] = 1; | |
7553 } | |
7554 }'''); | |
7555 computeLibrarySourceErrors(source); | |
7556 assertNoErrors(source); | |
7557 } | |
7558 | |
7559 void test_undefinedOperator_postfixExpression() { | |
7560 Source source = addSource(r''' | |
7561 class A {} | |
7562 class B extends A { | |
7563 operator +(B b) {return new B();} | |
7564 } | |
7565 f(var a) { | |
7566 if(a is A) { | |
7567 a++; | |
7568 } | |
7569 }'''); | |
7570 computeLibrarySourceErrors(source); | |
7571 assertNoErrors(source); | |
7572 } | |
7573 | |
7574 void test_undefinedOperator_prefixExpression() { | |
7575 Source source = addSource(r''' | |
7576 class A {} | |
7577 class B extends A { | |
7578 operator +(B b) {return new B();} | |
7579 } | |
7580 f(var a) { | |
7581 if(a is A) { | |
7582 ++a; | |
7583 } | |
7584 }'''); | |
7585 computeLibrarySourceErrors(source); | |
7586 assertNoErrors(source); | |
7587 } | |
7588 | |
7589 void test_undefinedSetter_inSubtype() { | |
7590 Source source = addSource(r''' | |
7591 class A {} | |
7592 class B extends A { | |
7593 set b(x) {} | |
7594 } | |
7595 f(var a) { | |
7596 if(a is A) { | |
7597 a.b = 0; | |
7598 } | |
7599 }'''); | |
7600 computeLibrarySourceErrors(source); | |
7601 assertNoErrors(source); | |
7602 } | |
7603 | |
7604 void test_unnecessaryCast_13855_parameter_A() { | |
7605 // dartbug.com/13855, dartbug.com/13732 | |
7606 Source source = addSource(r''' | |
7607 class A{ | |
7608 a() {} | |
7609 } | |
7610 class B<E> { | |
7611 E e; | |
7612 m() { | |
7613 (e as A).a(); | |
7614 } | |
7615 }'''); | |
7616 computeLibrarySourceErrors(source); | |
7617 assertNoErrors(source); | |
7618 verify([source]); | |
7619 } | |
7620 | |
7621 void test_unnecessaryCast_conditionalExpression() { | |
7622 Source source = addSource(r''' | |
7623 abstract class I {} | |
7624 class A implements I {} | |
7625 class B implements I {} | |
7626 I m(A a, B b) { | |
7627 return a == null ? b as I : a as I; | |
7628 }'''); | |
7629 computeLibrarySourceErrors(source); | |
7630 assertNoErrors(source); | |
7631 verify([source]); | |
7632 } | |
7633 | |
7634 void test_unnecessaryCast_dynamic_type() { | |
7635 Source source = addSource(r''' | |
7636 m(v) { | |
7637 var b = v as Object; | |
7638 }'''); | |
7639 computeLibrarySourceErrors(source); | |
7640 assertNoErrors(source); | |
7641 verify([source]); | |
7642 } | |
7643 | |
7644 void test_unnecessaryCast_generics() { | |
7645 // dartbug.com/18953 | |
7646 Source source = addSource(r''' | |
7647 import 'dart:async'; | |
7648 Future<int> f() => new Future.value(0); | |
7649 void g(bool c) { | |
7650 (c ? f(): new Future.value(0) as Future<int>).then((int value) {}); | |
7651 }'''); | |
7652 computeLibrarySourceErrors(source); | |
7653 assertNoErrors(source); | |
7654 verify([source]); | |
7655 } | |
7656 | |
7657 void test_unnecessaryCast_type_dynamic() { | |
7658 Source source = addSource(r''' | |
7659 m(v) { | |
7660 var b = Object as dynamic; | |
7661 }'''); | |
7662 computeLibrarySourceErrors(source); | |
7663 assertNoErrors(source); | |
7664 verify([source]); | |
7665 } | |
7666 | |
7667 void test_unnecessaryNoSuchMethod_blockBody_notReturnStatement() { | |
7668 Source source = addSource(r''' | |
7669 class A { | |
7670 noSuchMethod(x) => super.noSuchMethod(x); | |
7671 } | |
7672 class B extends A { | |
7673 mmm(); | |
7674 noSuchMethod(y) { | |
7675 print(y); | |
7676 } | |
7677 }'''); | |
7678 computeLibrarySourceErrors(source); | |
7679 assertNoErrors(source); | |
7680 verify([source]); | |
7681 } | |
7682 | |
7683 void test_unnecessaryNoSuchMethod_blockBody_notSingleStatement() { | |
7684 Source source = addSource(r''' | |
7685 class A { | |
7686 noSuchMethod(x) => super.noSuchMethod(x); | |
7687 } | |
7688 class B extends A { | |
7689 mmm(); | |
7690 noSuchMethod(y) { | |
7691 print(y); | |
7692 return super.noSuchMethod(y); | |
7693 } | |
7694 }'''); | |
7695 computeLibrarySourceErrors(source); | |
7696 assertNoErrors(source); | |
7697 verify([source]); | |
7698 } | |
7699 | |
7700 void test_unnecessaryNoSuchMethod_expressionBody_notNoSuchMethod() { | |
7701 Source source = addSource(r''' | |
7702 class A { | |
7703 noSuchMethod(x) => super.noSuchMethod(x); | |
7704 } | |
7705 class B extends A { | |
7706 mmm(); | |
7707 noSuchMethod(y) => super.hashCode; | |
7708 }'''); | |
7709 computeLibrarySourceErrors(source); | |
7710 assertNoErrors(source); | |
7711 verify([source]); | |
7712 } | |
7713 | |
7714 void test_unnecessaryNoSuchMethod_expressionBody_notSuper() { | |
7715 Source source = addSource(r''' | |
7716 class A { | |
7717 noSuchMethod(x) => super.noSuchMethod(x); | |
7718 } | |
7719 class B extends A { | |
7720 mmm(); | |
7721 noSuchMethod(y) => 42; | |
7722 }'''); | |
7723 computeLibrarySourceErrors(source); | |
7724 assertNoErrors(source); | |
7725 verify([source]); | |
7726 } | |
7727 | |
7728 void test_unusedImport_annotationOnDirective() { | |
7729 Source source = addSource(r''' | |
7730 library L; | |
7731 @A() | |
7732 import 'lib1.dart';'''); | |
7733 Source source2 = addNamedSource( | |
7734 "/lib1.dart", | |
7735 r''' | |
7736 library lib1; | |
7737 class A { | |
7738 const A() {} | |
7739 }'''); | |
7740 computeLibrarySourceErrors(source); | |
7741 assertErrors(source); | |
7742 verify([source, source2]); | |
7743 } | |
7744 | |
7745 void test_unusedImport_as_equalPrefixes() { | |
7746 // 18818 | |
7747 Source source = addSource(r''' | |
7748 library L; | |
7749 import 'lib1.dart' as one; | |
7750 import 'lib2.dart' as one; | |
7751 one.A a; | |
7752 one.B b;'''); | |
7753 Source source2 = addNamedSource( | |
7754 "/lib1.dart", | |
7755 r''' | |
7756 library lib1; | |
7757 class A {}'''); | |
7758 Source source3 = addNamedSource( | |
7759 "/lib2.dart", | |
7760 r''' | |
7761 library lib2; | |
7762 class B {}'''); | |
7763 computeLibrarySourceErrors(source); | |
7764 assertErrors(source); | |
7765 assertNoErrors(source2); | |
7766 assertNoErrors(source3); | |
7767 verify([source, source2, source3]); | |
7768 } | |
7769 | |
7770 void test_unusedImport_core_library() { | |
7771 Source source = addSource(r''' | |
7772 library L; | |
7773 import 'dart:core';'''); | |
7774 computeLibrarySourceErrors(source); | |
7775 assertNoErrors(source); | |
7776 verify([source]); | |
7777 } | |
7778 | |
7779 void test_unusedImport_export() { | |
7780 Source source = addSource(r''' | |
7781 library L; | |
7782 import 'lib1.dart'; | |
7783 Two two;'''); | |
7784 addNamedSource( | |
7785 "/lib1.dart", | |
7786 r''' | |
7787 library lib1; | |
7788 export 'lib2.dart'; | |
7789 class One {}'''); | |
7790 addNamedSource( | |
7791 "/lib2.dart", | |
7792 r''' | |
7793 library lib2; | |
7794 class Two {}'''); | |
7795 computeLibrarySourceErrors(source); | |
7796 assertNoErrors(source); | |
7797 verify([source]); | |
7798 } | |
7799 | |
7800 void test_unusedImport_export2() { | |
7801 Source source = addSource(r''' | |
7802 library L; | |
7803 import 'lib1.dart'; | |
7804 Three three;'''); | |
7805 addNamedSource( | |
7806 "/lib1.dart", | |
7807 r''' | |
7808 library lib1; | |
7809 export 'lib2.dart'; | |
7810 class One {}'''); | |
7811 addNamedSource( | |
7812 "/lib2.dart", | |
7813 r''' | |
7814 library lib2; | |
7815 export 'lib3.dart'; | |
7816 class Two {}'''); | |
7817 addNamedSource( | |
7818 "/lib3.dart", | |
7819 r''' | |
7820 library lib3; | |
7821 class Three {}'''); | |
7822 computeLibrarySourceErrors(source); | |
7823 assertNoErrors(source); | |
7824 verify([source]); | |
7825 } | |
7826 | |
7827 void test_unusedImport_export_infiniteLoop() { | |
7828 Source source = addSource(r''' | |
7829 library L; | |
7830 import 'lib1.dart'; | |
7831 Two two;'''); | |
7832 addNamedSource( | |
7833 "/lib1.dart", | |
7834 r''' | |
7835 library lib1; | |
7836 export 'lib2.dart'; | |
7837 class One {}'''); | |
7838 addNamedSource( | |
7839 "/lib2.dart", | |
7840 r''' | |
7841 library lib2; | |
7842 export 'lib3.dart'; | |
7843 class Two {}'''); | |
7844 addNamedSource( | |
7845 "/lib3.dart", | |
7846 r''' | |
7847 library lib3; | |
7848 export 'lib2.dart'; | |
7849 class Three {}'''); | |
7850 computeLibrarySourceErrors(source); | |
7851 assertNoErrors(source); | |
7852 verify([source]); | |
7853 } | |
7854 | |
7855 void test_unusedImport_metadata() { | |
7856 Source source = addSource(r''' | |
7857 library L; | |
7858 @A(x) | |
7859 import 'lib1.dart'; | |
7860 class A { | |
7861 final int value; | |
7862 const A(this.value); | |
7863 }'''); | |
7864 addNamedSource( | |
7865 "/lib1.dart", | |
7866 r''' | |
7867 library lib1; | |
7868 const x = 0;'''); | |
7869 computeLibrarySourceErrors(source); | |
7870 assertNoErrors(source); | |
7871 verify([source]); | |
7872 } | |
7873 | |
7874 void test_unusedImport_prefix_topLevelFunction() { | |
7875 Source source = addSource(r''' | |
7876 library L; | |
7877 import 'lib1.dart' hide topLevelFunction; | |
7878 import 'lib1.dart' as one show topLevelFunction; | |
7879 class A { | |
7880 static void x() { | |
7881 One o; | |
7882 one.topLevelFunction(); | |
7883 } | |
7884 }'''); | |
7885 addNamedSource( | |
7886 "/lib1.dart", | |
7887 r''' | |
7888 library lib1; | |
7889 class One {} | |
7890 topLevelFunction() {}'''); | |
7891 computeLibrarySourceErrors(source); | |
7892 assertNoErrors(source); | |
7893 verify([source]); | |
7894 } | |
7895 | |
7896 void test_useOfVoidResult_implicitReturnValue() { | |
7897 Source source = addSource(r''' | |
7898 f() {} | |
7899 class A { | |
7900 n() { | |
7901 var a = f(); | |
7902 } | |
7903 }'''); | |
7904 computeLibrarySourceErrors(source); | |
7905 assertNoErrors(source); | |
7906 verify([source]); | |
7907 } | |
7908 | |
7909 void test_useOfVoidResult_nonVoidReturnValue() { | |
7910 Source source = addSource(r''' | |
7911 int f() => 1; | |
7912 g() { | |
7913 var a = f(); | |
7914 }'''); | |
7915 computeLibrarySourceErrors(source); | |
7916 assertNoErrors(source); | |
7917 verify([source]); | |
7918 } | |
7919 } | |
7920 | |
7921 class PubSuggestionCodeTest extends ResolverTestCase { | |
7922 void test_import_package() { | |
7923 Source source = addSource("import 'package:somepackage/other.dart';"); | |
7924 computeLibrarySourceErrors(source); | |
7925 assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]); | |
7926 } | |
7927 | |
7928 void test_import_packageWithDotDot() { | |
7929 Source source = addSource("import 'package:somepackage/../other.dart';"); | |
7930 computeLibrarySourceErrors(source); | |
7931 assertErrors(source, [ | |
7932 CompileTimeErrorCode.URI_DOES_NOT_EXIST, | |
7933 HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT | |
7934 ]); | |
7935 } | |
7936 | |
7937 void test_import_packageWithLeadingDotDot() { | |
7938 Source source = addSource("import 'package:../other.dart';"); | |
7939 computeLibrarySourceErrors(source); | |
7940 assertErrors(source, [ | |
7941 CompileTimeErrorCode.URI_DOES_NOT_EXIST, | |
7942 HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT | |
7943 ]); | |
7944 } | |
7945 | |
7946 void test_import_referenceIntoLibDirectory() { | |
7947 cacheSource("/myproj/pubspec.yaml", ""); | |
7948 cacheSource("/myproj/lib/other.dart", ""); | |
7949 Source source = | |
7950 addNamedSource("/myproj/web/test.dart", "import '../lib/other.dart';"); | |
7951 computeLibrarySourceErrors(source); | |
7952 assertErrors( | |
7953 source, [HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE]); | |
7954 } | |
7955 | |
7956 void test_import_referenceIntoLibDirectory_no_pubspec() { | |
7957 cacheSource("/myproj/lib/other.dart", ""); | |
7958 Source source = | |
7959 addNamedSource("/myproj/web/test.dart", "import '../lib/other.dart';"); | |
7960 computeLibrarySourceErrors(source); | |
7961 assertNoErrors(source); | |
7962 } | |
7963 | |
7964 void test_import_referenceOutOfLibDirectory() { | |
7965 cacheSource("/myproj/pubspec.yaml", ""); | |
7966 cacheSource("/myproj/web/other.dart", ""); | |
7967 Source source = | |
7968 addNamedSource("/myproj/lib/test.dart", "import '../web/other.dart';"); | |
7969 computeLibrarySourceErrors(source); | |
7970 assertErrors( | |
7971 source, [HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE]); | |
7972 } | |
7973 | |
7974 void test_import_referenceOutOfLibDirectory_no_pubspec() { | |
7975 cacheSource("/myproj/web/other.dart", ""); | |
7976 Source source = | |
7977 addNamedSource("/myproj/lib/test.dart", "import '../web/other.dart';"); | |
7978 computeLibrarySourceErrors(source); | |
7979 assertNoErrors(source); | |
7980 } | |
7981 | |
7982 void test_import_valid_inside_lib1() { | |
7983 cacheSource("/myproj/pubspec.yaml", ""); | |
7984 cacheSource("/myproj/lib/other.dart", ""); | |
7985 Source source = | |
7986 addNamedSource("/myproj/lib/test.dart", "import 'other.dart';"); | |
7987 computeLibrarySourceErrors(source); | |
7988 assertNoErrors(source); | |
7989 } | |
7990 | |
7991 void test_import_valid_inside_lib2() { | |
7992 cacheSource("/myproj/pubspec.yaml", ""); | |
7993 cacheSource("/myproj/lib/bar/other.dart", ""); | |
7994 Source source = addNamedSource( | |
7995 "/myproj/lib/foo/test.dart", "import '../bar/other.dart';"); | |
7996 computeLibrarySourceErrors(source); | |
7997 assertNoErrors(source); | |
7998 } | |
7999 | |
8000 void test_import_valid_outside_lib() { | |
8001 cacheSource("/myproj/pubspec.yaml", ""); | |
8002 cacheSource("/myproj/web/other.dart", ""); | |
8003 Source source = | |
8004 addNamedSource("/myproj/lib2/test.dart", "import '../web/other.dart';"); | |
8005 computeLibrarySourceErrors(source); | |
8006 assertNoErrors(source); | |
8007 } | |
8008 } | |
8009 | |
8010 /** | |
8011 * An AST visitor used to verify that all of the nodes in an AST structure that | |
8012 * should have been resolved were resolved. | |
8013 */ | |
8014 class ResolutionVerifier extends RecursiveAstVisitor<Object> { | |
8015 /** | |
8016 * A set containing nodes that are known to not be resolvable and should | |
8017 * therefore not cause the test to fail. | |
8018 */ | |
8019 final Set<AstNode> _knownExceptions; | |
8020 | |
8021 /** | |
8022 * A list containing all of the AST nodes that were not resolved. | |
8023 */ | |
8024 List<AstNode> _unresolvedNodes = new List<AstNode>(); | |
8025 | |
8026 /** | |
8027 * A list containing all of the AST nodes that were resolved to an element of | |
8028 * the wrong type. | |
8029 */ | |
8030 List<AstNode> _wrongTypedNodes = new List<AstNode>(); | |
8031 | |
8032 /** | |
8033 * Initialize a newly created verifier to verify that all of the identifiers | |
8034 * in the visited AST structures that are expected to have been resolved have | |
8035 * an element associated with them. Nodes in the set of [_knownExceptions] are | |
8036 * not expected to have been resolved, even if they normally would have been | |
8037 * expected to have been resolved. | |
8038 */ | |
8039 ResolutionVerifier([this._knownExceptions]); | |
8040 | |
8041 /** | |
8042 * Assert that all of the visited identifiers were resolved. | |
8043 */ | |
8044 void assertResolved() { | |
8045 if (!_unresolvedNodes.isEmpty || !_wrongTypedNodes.isEmpty) { | |
8046 StringBuffer buffer = new StringBuffer(); | |
8047 if (!_unresolvedNodes.isEmpty) { | |
8048 buffer.write("Failed to resolve "); | |
8049 buffer.write(_unresolvedNodes.length); | |
8050 buffer.writeln(" nodes:"); | |
8051 _printNodes(buffer, _unresolvedNodes); | |
8052 } | |
8053 if (!_wrongTypedNodes.isEmpty) { | |
8054 buffer.write("Resolved "); | |
8055 buffer.write(_wrongTypedNodes.length); | |
8056 buffer.writeln(" to the wrong type of element:"); | |
8057 _printNodes(buffer, _wrongTypedNodes); | |
8058 } | |
8059 fail(buffer.toString()); | |
8060 } | |
8061 } | |
8062 | |
8063 @override | |
8064 Object visitAnnotation(Annotation node) { | |
8065 node.visitChildren(this); | |
8066 ElementAnnotation elementAnnotation = node.elementAnnotation; | |
8067 if (elementAnnotation == null) { | |
8068 if (_knownExceptions == null || !_knownExceptions.contains(node)) { | |
8069 _unresolvedNodes.add(node); | |
8070 } | |
8071 } else if (elementAnnotation is! ElementAnnotation) { | |
8072 _wrongTypedNodes.add(node); | |
8073 } | |
8074 return null; | |
8075 } | |
8076 | |
8077 @override | |
8078 Object visitBinaryExpression(BinaryExpression node) { | |
8079 node.visitChildren(this); | |
8080 if (!node.operator.isUserDefinableOperator) { | |
8081 return null; | |
8082 } | |
8083 DartType operandType = node.leftOperand.staticType; | |
8084 if (operandType == null || operandType.isDynamic) { | |
8085 return null; | |
8086 } | |
8087 return _checkResolved( | |
8088 node, node.staticElement, (node) => node is MethodElement); | |
8089 } | |
8090 | |
8091 @override | |
8092 Object visitCommentReference(CommentReference node) => null; | |
8093 | |
8094 @override | |
8095 Object visitCompilationUnit(CompilationUnit node) { | |
8096 node.visitChildren(this); | |
8097 return _checkResolved( | |
8098 node, node.element, (node) => node is CompilationUnitElement); | |
8099 } | |
8100 | |
8101 @override | |
8102 Object visitExportDirective(ExportDirective node) => | |
8103 _checkResolved(node, node.element, (node) => node is ExportElement); | |
8104 | |
8105 @override | |
8106 Object visitFunctionDeclaration(FunctionDeclaration node) { | |
8107 node.visitChildren(this); | |
8108 if (node.element is LibraryElement) { | |
8109 _wrongTypedNodes.add(node); | |
8110 } | |
8111 return null; | |
8112 } | |
8113 | |
8114 @override | |
8115 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { | |
8116 node.visitChildren(this); | |
8117 // TODO(brianwilkerson) If we start resolving function expressions, then | |
8118 // conditionally check to see whether the node was resolved correctly. | |
8119 return null; | |
8120 //checkResolved(node, node.getElement(), FunctionElement.class); | |
8121 } | |
8122 | |
8123 @override | |
8124 Object visitImportDirective(ImportDirective node) { | |
8125 // Not sure how to test the combinators given that it isn't an error if the | |
8126 // names are not defined. | |
8127 _checkResolved(node, node.element, (node) => node is ImportElement); | |
8128 SimpleIdentifier prefix = node.prefix; | |
8129 if (prefix == null) { | |
8130 return null; | |
8131 } | |
8132 return _checkResolved( | |
8133 prefix, prefix.staticElement, (node) => node is PrefixElement); | |
8134 } | |
8135 | |
8136 @override | |
8137 Object visitIndexExpression(IndexExpression node) { | |
8138 node.visitChildren(this); | |
8139 DartType targetType = node.realTarget.staticType; | |
8140 if (targetType == null || targetType.isDynamic) { | |
8141 return null; | |
8142 } | |
8143 return _checkResolved( | |
8144 node, node.staticElement, (node) => node is MethodElement); | |
8145 } | |
8146 | |
8147 @override | |
8148 Object visitLibraryDirective(LibraryDirective node) => | |
8149 _checkResolved(node, node.element, (node) => node is LibraryElement); | |
8150 | |
8151 @override | |
8152 Object visitNamedExpression(NamedExpression node) => | |
8153 node.expression.accept(this); | |
8154 | |
8155 @override | |
8156 Object visitPartDirective(PartDirective node) => _checkResolved( | |
8157 node, node.element, (node) => node is CompilationUnitElement); | |
8158 | |
8159 @override | |
8160 Object visitPartOfDirective(PartOfDirective node) => | |
8161 _checkResolved(node, node.element, (node) => node is LibraryElement); | |
8162 | |
8163 @override | |
8164 Object visitPostfixExpression(PostfixExpression node) { | |
8165 node.visitChildren(this); | |
8166 if (!node.operator.isUserDefinableOperator) { | |
8167 return null; | |
8168 } | |
8169 DartType operandType = node.operand.staticType; | |
8170 if (operandType == null || operandType.isDynamic) { | |
8171 return null; | |
8172 } | |
8173 return _checkResolved( | |
8174 node, node.staticElement, (node) => node is MethodElement); | |
8175 } | |
8176 | |
8177 @override | |
8178 Object visitPrefixedIdentifier(PrefixedIdentifier node) { | |
8179 SimpleIdentifier prefix = node.prefix; | |
8180 prefix.accept(this); | |
8181 DartType prefixType = prefix.staticType; | |
8182 if (prefixType == null || prefixType.isDynamic) { | |
8183 return null; | |
8184 } | |
8185 return _checkResolved(node, node.staticElement, null); | |
8186 } | |
8187 | |
8188 @override | |
8189 Object visitPrefixExpression(PrefixExpression node) { | |
8190 node.visitChildren(this); | |
8191 if (!node.operator.isUserDefinableOperator) { | |
8192 return null; | |
8193 } | |
8194 DartType operandType = node.operand.staticType; | |
8195 if (operandType == null || operandType.isDynamic) { | |
8196 return null; | |
8197 } | |
8198 return _checkResolved( | |
8199 node, node.staticElement, (node) => node is MethodElement); | |
8200 } | |
8201 | |
8202 @override | |
8203 Object visitPropertyAccess(PropertyAccess node) { | |
8204 Expression target = node.realTarget; | |
8205 target.accept(this); | |
8206 DartType targetType = target.staticType; | |
8207 if (targetType == null || targetType.isDynamic) { | |
8208 return null; | |
8209 } | |
8210 return node.propertyName.accept(this); | |
8211 } | |
8212 | |
8213 @override | |
8214 Object visitSimpleIdentifier(SimpleIdentifier node) { | |
8215 if (node.name == "void") { | |
8216 return null; | |
8217 } | |
8218 if (node.staticType != null && | |
8219 node.staticType.isDynamic && | |
8220 node.staticElement == null) { | |
8221 return null; | |
8222 } | |
8223 AstNode parent = node.parent; | |
8224 if (parent is MethodInvocation) { | |
8225 MethodInvocation invocation = parent; | |
8226 if (identical(invocation.methodName, node)) { | |
8227 Expression target = invocation.realTarget; | |
8228 DartType targetType = target == null ? null : target.staticType; | |
8229 if (targetType == null || targetType.isDynamic) { | |
8230 return null; | |
8231 } | |
8232 } | |
8233 } | |
8234 return _checkResolved(node, node.staticElement, null); | |
8235 } | |
8236 | |
8237 Object _checkResolved( | |
8238 AstNode node, Element element, Predicate<Element> predicate) { | |
8239 if (element == null) { | |
8240 if (_knownExceptions == null || !_knownExceptions.contains(node)) { | |
8241 _unresolvedNodes.add(node); | |
8242 } | |
8243 } else if (predicate != null) { | |
8244 if (!predicate(element)) { | |
8245 _wrongTypedNodes.add(node); | |
8246 } | |
8247 } | |
8248 return null; | |
8249 } | |
8250 | |
8251 String _getFileName(AstNode node) { | |
8252 // TODO (jwren) there are two copies of this method, one here and one in | |
8253 // StaticTypeVerifier, they should be resolved into a single method | |
8254 if (node != null) { | |
8255 AstNode root = node.root; | |
8256 if (root is CompilationUnit) { | |
8257 CompilationUnit rootCU = root; | |
8258 if (rootCU.element != null) { | |
8259 return rootCU.element.source.fullName; | |
8260 } else { | |
8261 return "<unknown file- CompilationUnit.getElement() returned null>"; | |
8262 } | |
8263 } else { | |
8264 return "<unknown file- CompilationUnit.getRoot() is not a CompilationUni
t>"; | |
8265 } | |
8266 } | |
8267 return "<unknown file- ASTNode is null>"; | |
8268 } | |
8269 | |
8270 void _printNodes(StringBuffer buffer, List<AstNode> nodes) { | |
8271 for (AstNode identifier in nodes) { | |
8272 buffer.write(" "); | |
8273 buffer.write(identifier.toString()); | |
8274 buffer.write(" ("); | |
8275 buffer.write(_getFileName(identifier)); | |
8276 buffer.write(" : "); | |
8277 buffer.write(identifier.offset); | |
8278 buffer.writeln(")"); | |
8279 } | |
8280 } | |
8281 } | |
8282 | |
8283 class ResolverTestCase extends EngineTestCase { | |
8284 /** | |
8285 * The analysis context used to parse the compilation units being resolved. | |
8286 */ | |
8287 InternalAnalysisContext analysisContext2; | |
8288 | |
8289 /** | |
8290 * Specifies if [assertErrors] should check for [HintCode.UNUSED_ELEMENT] and | |
8291 * [HintCode.UNUSED_FIELD]. | |
8292 */ | |
8293 bool enableUnusedElement = false; | |
8294 | |
8295 /** | |
8296 * Specifies if [assertErrors] should check for [HintCode.UNUSED_LOCAL_VARIABL
E]. | |
8297 */ | |
8298 bool enableUnusedLocalVariable = false; | |
8299 | |
8300 AnalysisContext get analysisContext => analysisContext2; | |
8301 | |
8302 /** | |
8303 * Return a type provider that can be used to test the results of resolution. | |
8304 * | |
8305 * @return a type provider | |
8306 * @throws AnalysisException if dart:core cannot be resolved | |
8307 */ | |
8308 TypeProvider get typeProvider => analysisContext2.typeProvider; | |
8309 | |
8310 /** | |
8311 * Return a type system that can be used to test the results of resolution. | |
8312 * | |
8313 * @return a type system | |
8314 */ | |
8315 TypeSystem get typeSystem => analysisContext2.typeSystem; | |
8316 | |
8317 /** | |
8318 * Add a source file to the content provider. The file path should be absolute
. | |
8319 * | |
8320 * @param filePath the path of the file being added | |
8321 * @param contents the contents to be returned by the content provider for the
specified file | |
8322 * @return the source object representing the added file | |
8323 */ | |
8324 Source addNamedSource(String filePath, String contents) { | |
8325 Source source = cacheSource(filePath, contents); | |
8326 ChangeSet changeSet = new ChangeSet(); | |
8327 changeSet.addedSource(source); | |
8328 analysisContext2.applyChanges(changeSet); | |
8329 return source; | |
8330 } | |
8331 | |
8332 /** | |
8333 * Add a source file to the content provider. | |
8334 * | |
8335 * @param contents the contents to be returned by the content provider for the
specified file | |
8336 * @return the source object representing the added file | |
8337 */ | |
8338 Source addSource(String contents) => addNamedSource("/test.dart", contents); | |
8339 | |
8340 /** | |
8341 * Assert that the number of errors reported against the given source matches
the number of errors | |
8342 * that are given and that they have the expected error codes. The order in wh
ich the errors were | |
8343 * gathered is ignored. | |
8344 * | |
8345 * @param source the source against which the errors should have been reported | |
8346 * @param expectedErrorCodes the error codes of the errors that should have be
en reported | |
8347 * @throws AnalysisException if the reported errors could not be computed | |
8348 * @throws AssertionFailedError if a different number of errors have been repo
rted than were | |
8349 * expected | |
8350 */ | |
8351 void assertErrors(Source source, | |
8352 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { | |
8353 GatheringErrorListener errorListener = new GatheringErrorListener(); | |
8354 for (AnalysisError error in analysisContext2.computeErrors(source)) { | |
8355 expect(error.source, source); | |
8356 ErrorCode errorCode = error.errorCode; | |
8357 if (!enableUnusedElement && | |
8358 (errorCode == HintCode.UNUSED_ELEMENT || | |
8359 errorCode == HintCode.UNUSED_FIELD)) { | |
8360 continue; | |
8361 } | |
8362 if (!enableUnusedLocalVariable && | |
8363 (errorCode == HintCode.UNUSED_CATCH_CLAUSE || | |
8364 errorCode == HintCode.UNUSED_CATCH_STACK || | |
8365 errorCode == HintCode.UNUSED_LOCAL_VARIABLE)) { | |
8366 continue; | |
8367 } | |
8368 errorListener.onError(error); | |
8369 } | |
8370 errorListener.assertErrorsWithCodes(expectedErrorCodes); | |
8371 } | |
8372 | |
8373 /** | |
8374 * Asserts that [code] verifies, but has errors with the given error codes. | |
8375 * | |
8376 * Like [assertErrors], but takes a string of source code. | |
8377 */ | |
8378 // TODO(rnystrom): Use this in more tests that have the same structure. | |
8379 void assertErrorsInCode(String code, List<ErrorCode> errors) { | |
8380 Source source = addSource(code); | |
8381 computeLibrarySourceErrors(source); | |
8382 assertErrors(source, errors); | |
8383 verify([source]); | |
8384 } | |
8385 | |
8386 /** | |
8387 * Asserts that [code] has errors with the given error codes. | |
8388 * | |
8389 * Like [assertErrors], but takes a string of source code. | |
8390 */ | |
8391 void assertErrorsInUnverifiedCode(String code, List<ErrorCode> errors) { | |
8392 Source source = addSource(code); | |
8393 computeLibrarySourceErrors(source); | |
8394 assertErrors(source, errors); | |
8395 } | |
8396 | |
8397 /** | |
8398 * Assert that no errors have been reported against the given source. | |
8399 * | |
8400 * @param source the source against which no errors should have been reported | |
8401 * @throws AnalysisException if the reported errors could not be computed | |
8402 * @throws AssertionFailedError if any errors have been reported | |
8403 */ | |
8404 void assertNoErrors(Source source) { | |
8405 assertErrors(source); | |
8406 } | |
8407 | |
8408 /** | |
8409 * Asserts that [code] has no errors or warnings. | |
8410 */ | |
8411 // TODO(rnystrom): Use this in more tests that have the same structure. | |
8412 void assertNoErrorsInCode(String code) { | |
8413 Source source = addSource(code); | |
8414 computeLibrarySourceErrors(source); | |
8415 assertNoErrors(source); | |
8416 verify([source]); | |
8417 } | |
8418 | |
8419 /** | |
8420 * Cache the source file content in the source factory but don't add the sourc
e to the analysis | |
8421 * context. The file path should be absolute. | |
8422 * | |
8423 * @param filePath the path of the file being cached | |
8424 * @param contents the contents to be returned by the content provider for the
specified file | |
8425 * @return the source object representing the cached file | |
8426 */ | |
8427 Source cacheSource(String filePath, String contents) { | |
8428 Source source = new FileBasedSource(FileUtilities2.createFile(filePath)); | |
8429 analysisContext2.setContents(source, contents); | |
8430 return source; | |
8431 } | |
8432 | |
8433 /** | |
8434 * Change the contents of the given [source] to the given [contents]. | |
8435 */ | |
8436 void changeSource(Source source, String contents) { | |
8437 analysisContext2.setContents(source, contents); | |
8438 ChangeSet changeSet = new ChangeSet(); | |
8439 changeSet.changedSource(source); | |
8440 analysisContext2.applyChanges(changeSet); | |
8441 } | |
8442 | |
8443 /** | |
8444 * Computes errors for the given [librarySource]. | |
8445 * This assumes that the given [librarySource] and its parts have already | |
8446 * been added to the content provider using the method [addNamedSource]. | |
8447 */ | |
8448 void computeLibrarySourceErrors(Source librarySource) { | |
8449 analysisContext.computeErrors(librarySource); | |
8450 } | |
8451 | |
8452 /** | |
8453 * Create a library element that represents a library named `"test"` containin
g a single | |
8454 * empty compilation unit. | |
8455 * | |
8456 * @return the library element that was created | |
8457 */ | |
8458 LibraryElementImpl createDefaultTestLibrary() => | |
8459 createTestLibrary(AnalysisContextFactory.contextWithCore(), "test"); | |
8460 | |
8461 /** | |
8462 * Create a library element that represents a library with the given name cont
aining a single | |
8463 * empty compilation unit. | |
8464 * | |
8465 * @param libraryName the name of the library to be created | |
8466 * @return the library element that was created | |
8467 */ | |
8468 LibraryElementImpl createTestLibrary( | |
8469 AnalysisContext context, String libraryName, | |
8470 [List<String> typeNames]) { | |
8471 String fileName = "$libraryName.dart"; | |
8472 FileBasedSource definingCompilationUnitSource = | |
8473 _createNamedSource(fileName); | |
8474 List<CompilationUnitElement> sourcedCompilationUnits; | |
8475 if (typeNames == null) { | |
8476 sourcedCompilationUnits = CompilationUnitElement.EMPTY_LIST; | |
8477 } else { | |
8478 int count = typeNames.length; | |
8479 sourcedCompilationUnits = new List<CompilationUnitElement>(count); | |
8480 for (int i = 0; i < count; i++) { | |
8481 String typeName = typeNames[i]; | |
8482 ClassElementImpl type = | |
8483 new ClassElementImpl.forNode(AstFactory.identifier3(typeName)); | |
8484 String fileName = "$typeName.dart"; | |
8485 CompilationUnitElementImpl compilationUnit = | |
8486 new CompilationUnitElementImpl(fileName); | |
8487 compilationUnit.source = _createNamedSource(fileName); | |
8488 compilationUnit.librarySource = definingCompilationUnitSource; | |
8489 compilationUnit.types = <ClassElement>[type]; | |
8490 sourcedCompilationUnits[i] = compilationUnit; | |
8491 } | |
8492 } | |
8493 CompilationUnitElementImpl compilationUnit = | |
8494 new CompilationUnitElementImpl(fileName); | |
8495 compilationUnit.librarySource = | |
8496 compilationUnit.source = definingCompilationUnitSource; | |
8497 LibraryElementImpl library = new LibraryElementImpl.forNode( | |
8498 context, AstFactory.libraryIdentifier2([libraryName])); | |
8499 library.definingCompilationUnit = compilationUnit; | |
8500 library.parts = sourcedCompilationUnits; | |
8501 return library; | |
8502 } | |
8503 | |
8504 Expression findTopLevelConstantExpression( | |
8505 CompilationUnit compilationUnit, String name) => | |
8506 findTopLevelDeclaration(compilationUnit, name).initializer; | |
8507 | |
8508 VariableDeclaration findTopLevelDeclaration( | |
8509 CompilationUnit compilationUnit, String name) { | |
8510 for (CompilationUnitMember member in compilationUnit.declarations) { | |
8511 if (member is TopLevelVariableDeclaration) { | |
8512 for (VariableDeclaration variable in member.variables.variables) { | |
8513 if (variable.name.name == name) { | |
8514 return variable; | |
8515 } | |
8516 } | |
8517 } | |
8518 } | |
8519 return null; | |
8520 // Not found | |
8521 } | |
8522 | |
8523 /** | |
8524 * In the rare cases we want to group several tests into single "test_" method
, so need a way to | |
8525 * reset test instance to reuse it. | |
8526 */ | |
8527 void reset() { | |
8528 analysisContext2 = AnalysisContextFactory.contextWithCore(); | |
8529 } | |
8530 | |
8531 /** | |
8532 * Reset the analysis context to have the given options applied. | |
8533 * | |
8534 * @param options the analysis options to be applied to the context | |
8535 */ | |
8536 void resetWithOptions(AnalysisOptions options) { | |
8537 analysisContext2 = | |
8538 AnalysisContextFactory.contextWithCoreAndOptions(options); | |
8539 } | |
8540 | |
8541 /** | |
8542 * Given a library and all of its parts, resolve the contents of the library a
nd the contents of | |
8543 * the parts. This assumes that the sources for the library and its parts have
already been added | |
8544 * to the content provider using the method [addNamedSource]. | |
8545 * | |
8546 * @param librarySource the source for the compilation unit that defines the l
ibrary | |
8547 * @return the element representing the resolved library | |
8548 * @throws AnalysisException if the analysis could not be performed | |
8549 */ | |
8550 LibraryElement resolve2(Source librarySource) => | |
8551 analysisContext2.computeLibraryElement(librarySource); | |
8552 | |
8553 /** | |
8554 * Return the resolved compilation unit corresponding to the given source in t
he given library. | |
8555 * | |
8556 * @param source the source of the compilation unit to be returned | |
8557 * @param library the library in which the compilation unit is to be resolved | |
8558 * @return the resolved compilation unit | |
8559 * @throws Exception if the compilation unit could not be resolved | |
8560 */ | |
8561 CompilationUnit resolveCompilationUnit( | |
8562 Source source, LibraryElement library) => | |
8563 analysisContext2.resolveCompilationUnit(source, library); | |
8564 | |
8565 CompilationUnit resolveSource(String sourceText) => | |
8566 resolveSource2("/test.dart", sourceText); | |
8567 | |
8568 CompilationUnit resolveSource2(String fileName, String sourceText) { | |
8569 Source source = addNamedSource(fileName, sourceText); | |
8570 LibraryElement library = analysisContext.computeLibraryElement(source); | |
8571 return analysisContext.resolveCompilationUnit(source, library); | |
8572 } | |
8573 | |
8574 Source resolveSources(List<String> sourceTexts) { | |
8575 for (int i = 0; i < sourceTexts.length; i++) { | |
8576 CompilationUnit unit = | |
8577 resolveSource2("/lib${i + 1}.dart", sourceTexts[i]); | |
8578 // reference the source if this is the last source | |
8579 if (i + 1 == sourceTexts.length) { | |
8580 return unit.element.source; | |
8581 } | |
8582 } | |
8583 return null; | |
8584 } | |
8585 | |
8586 void resolveWithAndWithoutExperimental( | |
8587 List<String> strSources, | |
8588 List<ErrorCode> codesWithoutExperimental, | |
8589 List<ErrorCode> codesWithExperimental) { | |
8590 // Setup analysis context as non-experimental | |
8591 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | |
8592 // options.enableDeferredLoading = false; | |
8593 resetWithOptions(options); | |
8594 // Analysis and assertions | |
8595 Source source = resolveSources(strSources); | |
8596 assertErrors(source, codesWithoutExperimental); | |
8597 verify([source]); | |
8598 // Setup analysis context as experimental | |
8599 reset(); | |
8600 // Analysis and assertions | |
8601 source = resolveSources(strSources); | |
8602 assertErrors(source, codesWithExperimental); | |
8603 verify([source]); | |
8604 } | |
8605 | |
8606 void resolveWithErrors(List<String> strSources, List<ErrorCode> codes) { | |
8607 // Analysis and assertions | |
8608 Source source = resolveSources(strSources); | |
8609 assertErrors(source, codes); | |
8610 verify([source]); | |
8611 } | |
8612 | |
8613 @override | |
8614 void setUp() { | |
8615 ElementFactory.flushStaticState(); | |
8616 super.setUp(); | |
8617 reset(); | |
8618 } | |
8619 | |
8620 @override | |
8621 void tearDown() { | |
8622 analysisContext2 = null; | |
8623 super.tearDown(); | |
8624 } | |
8625 | |
8626 /** | |
8627 * Verify that all of the identifiers in the compilation units associated with | |
8628 * the given [sources] have been resolved. | |
8629 */ | |
8630 void verify(List<Source> sources) { | |
8631 ResolutionVerifier verifier = new ResolutionVerifier(); | |
8632 for (Source source in sources) { | |
8633 List<Source> libraries = analysisContext2.getLibrariesContaining(source); | |
8634 for (Source library in libraries) { | |
8635 analysisContext2 | |
8636 .resolveCompilationUnit2(source, library) | |
8637 .accept(verifier); | |
8638 } | |
8639 } | |
8640 verifier.assertResolved(); | |
8641 } | |
8642 | |
8643 /** | |
8644 * @param code the code that assigns the value to the variable "v", no matter
how. We check that | |
8645 * "v" has expected static and propagated type. | |
8646 */ | |
8647 void _assertPropagatedAssignedType(String code, DartType expectedStaticType, | |
8648 DartType expectedPropagatedType) { | |
8649 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = "); | |
8650 expect(identifier.staticType, same(expectedStaticType)); | |
8651 expect(identifier.propagatedType, same(expectedPropagatedType)); | |
8652 } | |
8653 | |
8654 /** | |
8655 * @param code the code that iterates using variable "v". We check that | |
8656 * "v" has expected static and propagated type. | |
8657 */ | |
8658 void _assertPropagatedIterationType(String code, DartType expectedStaticType, | |
8659 DartType expectedPropagatedType) { | |
8660 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v in "); | |
8661 expect(identifier.staticType, same(expectedStaticType)); | |
8662 expect(identifier.propagatedType, same(expectedPropagatedType)); | |
8663 } | |
8664 | |
8665 /** | |
8666 * Check the static and propagated types of the expression marked with "; // m
arker" comment. | |
8667 * | |
8668 * @param code source code to analyze, with the expression to check marked wit
h "// marker". | |
8669 * @param expectedStaticType if non-null, check actual static type is equal to
this. | |
8670 * @param expectedPropagatedType if non-null, check actual static type is equa
l to this. | |
8671 * @throws Exception | |
8672 */ | |
8673 void _assertTypeOfMarkedExpression(String code, DartType expectedStaticType, | |
8674 DartType expectedPropagatedType) { | |
8675 SimpleIdentifier identifier = _findMarkedIdentifier(code, "; // marker"); | |
8676 if (expectedStaticType != null) { | |
8677 expect(identifier.staticType, expectedStaticType); | |
8678 } | |
8679 expect(identifier.propagatedType, expectedPropagatedType); | |
8680 } | |
8681 | |
8682 /** | |
8683 * Create a source object representing a file with the given [fileName] and | |
8684 * give it an empty content. Return the source that was created. | |
8685 */ | |
8686 FileBasedSource _createNamedSource(String fileName) { | |
8687 FileBasedSource source = | |
8688 new FileBasedSource(FileUtilities2.createFile(fileName)); | |
8689 analysisContext2.setContents(source, ""); | |
8690 return source; | |
8691 } | |
8692 | |
8693 /** | |
8694 * Return the `SimpleIdentifier` marked by `marker`. The source code must have
no | |
8695 * errors and be verifiable. | |
8696 * | |
8697 * @param code source code to analyze. | |
8698 * @param marker marker identifying sought after expression in source code. | |
8699 * @return expression marked by the marker. | |
8700 * @throws Exception | |
8701 */ | |
8702 SimpleIdentifier _findMarkedIdentifier(String code, String marker) { | |
8703 try { | |
8704 Source source = addSource(code); | |
8705 LibraryElement library = resolve2(source); | |
8706 assertNoErrors(source); | |
8707 verify([source]); | |
8708 CompilationUnit unit = resolveCompilationUnit(source, library); | |
8709 // Could generalize this further by making [SimpleIdentifier.class] a | |
8710 // parameter. | |
8711 return EngineTestCase.findNode( | |
8712 unit, code, marker, (node) => node is SimpleIdentifier); | |
8713 } catch (exception) { | |
8714 // Is there a better exception to throw here? The point is that an | |
8715 // assertion failure here should be a failure, in both "test_*" and | |
8716 // "fail_*" tests. However, an assertion failure is success for the | |
8717 // purpose of "fail_*" tests, so without catching them here "fail_*" tests | |
8718 // can succeed by failing for the wrong reason. | |
8719 throw new JavaException("Unexexpected assertion failure: $exception"); | |
8720 } | |
8721 } | |
8722 } | |
8723 | |
8724 class Scope_EnclosedScopeTest_test_define_duplicate extends Scope { | 585 class Scope_EnclosedScopeTest_test_define_duplicate extends Scope { |
8725 GatheringErrorListener listener; | 586 GatheringErrorListener listener; |
8726 | 587 |
8727 Scope_EnclosedScopeTest_test_define_duplicate(this.listener) : super(); | 588 Scope_EnclosedScopeTest_test_define_duplicate(this.listener) : super(); |
8728 | 589 |
8729 @override | 590 @override |
8730 AnalysisErrorListener get errorListener => listener; | 591 AnalysisErrorListener get errorListener => listener; |
8731 | 592 |
8732 @override | 593 @override |
8733 Element internalLookup(Identifier identifier, String name, | 594 Element internalLookup(Identifier identifier, String name, |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8800 final AnalysisErrorListener errorListener; | 661 final AnalysisErrorListener errorListener; |
8801 | 662 |
8802 ScopeTest_TestScope(this.errorListener); | 663 ScopeTest_TestScope(this.errorListener); |
8803 | 664 |
8804 @override | 665 @override |
8805 Element internalLookup(Identifier identifier, String name, | 666 Element internalLookup(Identifier identifier, String name, |
8806 LibraryElement referencingLibrary) => | 667 LibraryElement referencingLibrary) => |
8807 localLookup(name, referencingLibrary); | 668 localLookup(name, referencingLibrary); |
8808 } | 669 } |
8809 | 670 |
8810 @reflectiveTest | |
8811 class SimpleResolverTest extends ResolverTestCase { | |
8812 void fail_getter_and_setter_fromMixins_property_access() { | |
8813 // TODO(paulberry): it appears that auxiliaryElements isn't properly set on | |
8814 // a SimpleIdentifier that's inside a property access. This bug should be | |
8815 // fixed. | |
8816 Source source = addSource(''' | |
8817 class B {} | |
8818 class M1 { | |
8819 get x => null; | |
8820 set x(value) {} | |
8821 } | |
8822 class M2 { | |
8823 get x => null; | |
8824 set x(value) {} | |
8825 } | |
8826 class C extends B with M1, M2 {} | |
8827 void main() { | |
8828 new C().x += 1; | |
8829 } | |
8830 '''); | |
8831 LibraryElement library = resolve2(source); | |
8832 assertNoErrors(source); | |
8833 verify([source]); | |
8834 // Verify that both the getter and setter for "x" in "new C().x" refer to | |
8835 // the accessors defined in M2. | |
8836 FunctionDeclaration main = | |
8837 library.definingCompilationUnit.functions[0].computeNode(); | |
8838 BlockFunctionBody body = main.functionExpression.body; | |
8839 ExpressionStatement stmt = body.block.statements[0]; | |
8840 AssignmentExpression assignment = stmt.expression; | |
8841 PropertyAccess propertyAccess = assignment.leftHandSide; | |
8842 expect( | |
8843 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); | |
8844 expect( | |
8845 propertyAccess | |
8846 .propertyName.auxiliaryElements.staticElement.enclosingElement.name, | |
8847 'M2'); | |
8848 } | |
8849 | |
8850 void fail_staticInvocation() { | |
8851 Source source = addSource(r''' | |
8852 class A { | |
8853 static int get g => (a,b) => 0; | |
8854 } | |
8855 class B { | |
8856 f() { | |
8857 A.g(1,0); | |
8858 } | |
8859 }'''); | |
8860 computeLibrarySourceErrors(source); | |
8861 assertNoErrors(source); | |
8862 verify([source]); | |
8863 } | |
8864 | |
8865 void test_argumentResolution_required_matching() { | |
8866 Source source = addSource(r''' | |
8867 class A { | |
8868 void f() { | |
8869 g(1, 2, 3); | |
8870 } | |
8871 void g(a, b, c) {} | |
8872 }'''); | |
8873 _validateArgumentResolution(source, [0, 1, 2]); | |
8874 } | |
8875 | |
8876 void test_argumentResolution_required_tooFew() { | |
8877 Source source = addSource(r''' | |
8878 class A { | |
8879 void f() { | |
8880 g(1, 2); | |
8881 } | |
8882 void g(a, b, c) {} | |
8883 }'''); | |
8884 _validateArgumentResolution(source, [0, 1]); | |
8885 } | |
8886 | |
8887 void test_argumentResolution_required_tooMany() { | |
8888 Source source = addSource(r''' | |
8889 class A { | |
8890 void f() { | |
8891 g(1, 2, 3); | |
8892 } | |
8893 void g(a, b) {} | |
8894 }'''); | |
8895 _validateArgumentResolution(source, [0, 1, -1]); | |
8896 } | |
8897 | |
8898 void test_argumentResolution_requiredAndNamed_extra() { | |
8899 Source source = addSource(r''' | |
8900 class A { | |
8901 void f() { | |
8902 g(1, 2, c: 3, d: 4); | |
8903 } | |
8904 void g(a, b, {c}) {} | |
8905 }'''); | |
8906 _validateArgumentResolution(source, [0, 1, 2, -1]); | |
8907 } | |
8908 | |
8909 void test_argumentResolution_requiredAndNamed_matching() { | |
8910 Source source = addSource(r''' | |
8911 class A { | |
8912 void f() { | |
8913 g(1, 2, c: 3); | |
8914 } | |
8915 void g(a, b, {c}) {} | |
8916 }'''); | |
8917 _validateArgumentResolution(source, [0, 1, 2]); | |
8918 } | |
8919 | |
8920 void test_argumentResolution_requiredAndNamed_missing() { | |
8921 Source source = addSource(r''' | |
8922 class A { | |
8923 void f() { | |
8924 g(1, 2, d: 3); | |
8925 } | |
8926 void g(a, b, {c, d}) {} | |
8927 }'''); | |
8928 _validateArgumentResolution(source, [0, 1, 3]); | |
8929 } | |
8930 | |
8931 void test_argumentResolution_requiredAndPositional_fewer() { | |
8932 Source source = addSource(r''' | |
8933 class A { | |
8934 void f() { | |
8935 g(1, 2, 3); | |
8936 } | |
8937 void g(a, b, [c, d]) {} | |
8938 }'''); | |
8939 _validateArgumentResolution(source, [0, 1, 2]); | |
8940 } | |
8941 | |
8942 void test_argumentResolution_requiredAndPositional_matching() { | |
8943 Source source = addSource(r''' | |
8944 class A { | |
8945 void f() { | |
8946 g(1, 2, 3, 4); | |
8947 } | |
8948 void g(a, b, [c, d]) {} | |
8949 }'''); | |
8950 _validateArgumentResolution(source, [0, 1, 2, 3]); | |
8951 } | |
8952 | |
8953 void test_argumentResolution_requiredAndPositional_more() { | |
8954 Source source = addSource(r''' | |
8955 class A { | |
8956 void f() { | |
8957 g(1, 2, 3, 4); | |
8958 } | |
8959 void g(a, b, [c]) {} | |
8960 }'''); | |
8961 _validateArgumentResolution(source, [0, 1, 2, -1]); | |
8962 } | |
8963 | |
8964 void test_argumentResolution_setter_propagated() { | |
8965 Source source = addSource(r''' | |
8966 main() { | |
8967 var a = new A(); | |
8968 a.sss = 0; | |
8969 } | |
8970 class A { | |
8971 set sss(x) {} | |
8972 }'''); | |
8973 LibraryElement library = resolve2(source); | |
8974 CompilationUnitElement unit = library.definingCompilationUnit; | |
8975 // find "a.sss = 0" | |
8976 AssignmentExpression assignment; | |
8977 { | |
8978 FunctionElement mainElement = unit.functions[0]; | |
8979 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; | |
8980 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; | |
8981 ExpressionStatement expressionStatement = | |
8982 statement as ExpressionStatement; | |
8983 assignment = expressionStatement.expression as AssignmentExpression; | |
8984 } | |
8985 // get parameter | |
8986 Expression rhs = assignment.rightHandSide; | |
8987 expect(rhs.staticParameterElement, isNull); | |
8988 ParameterElement parameter = rhs.propagatedParameterElement; | |
8989 expect(parameter, isNotNull); | |
8990 expect(parameter.displayName, "x"); | |
8991 // validate | |
8992 ClassElement classA = unit.types[0]; | |
8993 PropertyAccessorElement setter = classA.accessors[0]; | |
8994 expect(setter.parameters[0], same(parameter)); | |
8995 } | |
8996 | |
8997 void test_argumentResolution_setter_propagated_propertyAccess() { | |
8998 Source source = addSource(r''' | |
8999 main() { | |
9000 var a = new A(); | |
9001 a.b.sss = 0; | |
9002 } | |
9003 class A { | |
9004 B b = new B(); | |
9005 } | |
9006 class B { | |
9007 set sss(x) {} | |
9008 }'''); | |
9009 LibraryElement library = resolve2(source); | |
9010 CompilationUnitElement unit = library.definingCompilationUnit; | |
9011 // find "a.b.sss = 0" | |
9012 AssignmentExpression assignment; | |
9013 { | |
9014 FunctionElement mainElement = unit.functions[0]; | |
9015 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; | |
9016 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; | |
9017 ExpressionStatement expressionStatement = | |
9018 statement as ExpressionStatement; | |
9019 assignment = expressionStatement.expression as AssignmentExpression; | |
9020 } | |
9021 // get parameter | |
9022 Expression rhs = assignment.rightHandSide; | |
9023 expect(rhs.staticParameterElement, isNull); | |
9024 ParameterElement parameter = rhs.propagatedParameterElement; | |
9025 expect(parameter, isNotNull); | |
9026 expect(parameter.displayName, "x"); | |
9027 // validate | |
9028 ClassElement classB = unit.types[1]; | |
9029 PropertyAccessorElement setter = classB.accessors[0]; | |
9030 expect(setter.parameters[0], same(parameter)); | |
9031 } | |
9032 | |
9033 void test_argumentResolution_setter_static() { | |
9034 Source source = addSource(r''' | |
9035 main() { | |
9036 A a = new A(); | |
9037 a.sss = 0; | |
9038 } | |
9039 class A { | |
9040 set sss(x) {} | |
9041 }'''); | |
9042 LibraryElement library = resolve2(source); | |
9043 CompilationUnitElement unit = library.definingCompilationUnit; | |
9044 // find "a.sss = 0" | |
9045 AssignmentExpression assignment; | |
9046 { | |
9047 FunctionElement mainElement = unit.functions[0]; | |
9048 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; | |
9049 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; | |
9050 ExpressionStatement expressionStatement = | |
9051 statement as ExpressionStatement; | |
9052 assignment = expressionStatement.expression as AssignmentExpression; | |
9053 } | |
9054 // get parameter | |
9055 Expression rhs = assignment.rightHandSide; | |
9056 ParameterElement parameter = rhs.staticParameterElement; | |
9057 expect(parameter, isNotNull); | |
9058 expect(parameter.displayName, "x"); | |
9059 // validate | |
9060 ClassElement classA = unit.types[0]; | |
9061 PropertyAccessorElement setter = classA.accessors[0]; | |
9062 expect(setter.parameters[0], same(parameter)); | |
9063 } | |
9064 | |
9065 void test_argumentResolution_setter_static_propertyAccess() { | |
9066 Source source = addSource(r''' | |
9067 main() { | |
9068 A a = new A(); | |
9069 a.b.sss = 0; | |
9070 } | |
9071 class A { | |
9072 B b = new B(); | |
9073 } | |
9074 class B { | |
9075 set sss(x) {} | |
9076 }'''); | |
9077 LibraryElement library = resolve2(source); | |
9078 CompilationUnitElement unit = library.definingCompilationUnit; | |
9079 // find "a.b.sss = 0" | |
9080 AssignmentExpression assignment; | |
9081 { | |
9082 FunctionElement mainElement = unit.functions[0]; | |
9083 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; | |
9084 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; | |
9085 ExpressionStatement expressionStatement = | |
9086 statement as ExpressionStatement; | |
9087 assignment = expressionStatement.expression as AssignmentExpression; | |
9088 } | |
9089 // get parameter | |
9090 Expression rhs = assignment.rightHandSide; | |
9091 ParameterElement parameter = rhs.staticParameterElement; | |
9092 expect(parameter, isNotNull); | |
9093 expect(parameter.displayName, "x"); | |
9094 // validate | |
9095 ClassElement classB = unit.types[1]; | |
9096 PropertyAccessorElement setter = classB.accessors[0]; | |
9097 expect(setter.parameters[0], same(parameter)); | |
9098 } | |
9099 | |
9100 void test_breakTarget_labeled() { | |
9101 // Verify that the target of the label is correctly found and is recorded | |
9102 // as the unlabeled portion of the statement. | |
9103 String text = r''' | |
9104 void f() { | |
9105 loop1: while (true) { | |
9106 loop2: for (int i = 0; i < 10; i++) { | |
9107 break loop1; | |
9108 break loop2; | |
9109 } | |
9110 } | |
9111 } | |
9112 '''; | |
9113 CompilationUnit unit = resolveSource(text); | |
9114 WhileStatement whileStatement = EngineTestCase.findNode( | |
9115 unit, text, 'while (true)', (n) => n is WhileStatement); | |
9116 ForStatement forStatement = | |
9117 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); | |
9118 BreakStatement break1 = EngineTestCase.findNode( | |
9119 unit, text, 'break loop1', (n) => n is BreakStatement); | |
9120 BreakStatement break2 = EngineTestCase.findNode( | |
9121 unit, text, 'break loop2', (n) => n is BreakStatement); | |
9122 expect(break1.target, same(whileStatement)); | |
9123 expect(break2.target, same(forStatement)); | |
9124 } | |
9125 | |
9126 void test_breakTarget_unlabeledBreakFromDo() { | |
9127 String text = r''' | |
9128 void f() { | |
9129 do { | |
9130 break; | |
9131 } while (true); | |
9132 } | |
9133 '''; | |
9134 CompilationUnit unit = resolveSource(text); | |
9135 DoStatement doStatement = | |
9136 EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement); | |
9137 BreakStatement breakStatement = EngineTestCase.findNode( | |
9138 unit, text, 'break', (n) => n is BreakStatement); | |
9139 expect(breakStatement.target, same(doStatement)); | |
9140 } | |
9141 | |
9142 void test_breakTarget_unlabeledBreakFromFor() { | |
9143 String text = r''' | |
9144 void f() { | |
9145 for (int i = 0; i < 10; i++) { | |
9146 break; | |
9147 } | |
9148 } | |
9149 '''; | |
9150 CompilationUnit unit = resolveSource(text); | |
9151 ForStatement forStatement = | |
9152 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); | |
9153 BreakStatement breakStatement = EngineTestCase.findNode( | |
9154 unit, text, 'break', (n) => n is BreakStatement); | |
9155 expect(breakStatement.target, same(forStatement)); | |
9156 } | |
9157 | |
9158 void test_breakTarget_unlabeledBreakFromForEach() { | |
9159 String text = r''' | |
9160 void f() { | |
9161 for (x in []) { | |
9162 break; | |
9163 } | |
9164 } | |
9165 '''; | |
9166 CompilationUnit unit = resolveSource(text); | |
9167 ForEachStatement forStatement = EngineTestCase.findNode( | |
9168 unit, text, 'for', (n) => n is ForEachStatement); | |
9169 BreakStatement breakStatement = EngineTestCase.findNode( | |
9170 unit, text, 'break', (n) => n is BreakStatement); | |
9171 expect(breakStatement.target, same(forStatement)); | |
9172 } | |
9173 | |
9174 void test_breakTarget_unlabeledBreakFromSwitch() { | |
9175 String text = r''' | |
9176 void f() { | |
9177 while (true) { | |
9178 switch (0) { | |
9179 case 0: | |
9180 break; | |
9181 } | |
9182 } | |
9183 } | |
9184 '''; | |
9185 CompilationUnit unit = resolveSource(text); | |
9186 SwitchStatement switchStatement = EngineTestCase.findNode( | |
9187 unit, text, 'switch', (n) => n is SwitchStatement); | |
9188 BreakStatement breakStatement = EngineTestCase.findNode( | |
9189 unit, text, 'break', (n) => n is BreakStatement); | |
9190 expect(breakStatement.target, same(switchStatement)); | |
9191 } | |
9192 | |
9193 void test_breakTarget_unlabeledBreakFromWhile() { | |
9194 String text = r''' | |
9195 void f() { | |
9196 while (true) { | |
9197 break; | |
9198 } | |
9199 } | |
9200 '''; | |
9201 CompilationUnit unit = resolveSource(text); | |
9202 WhileStatement whileStatement = EngineTestCase.findNode( | |
9203 unit, text, 'while', (n) => n is WhileStatement); | |
9204 BreakStatement breakStatement = EngineTestCase.findNode( | |
9205 unit, text, 'break', (n) => n is BreakStatement); | |
9206 expect(breakStatement.target, same(whileStatement)); | |
9207 } | |
9208 | |
9209 void test_breakTarget_unlabeledBreakToOuterFunction() { | |
9210 // Verify that unlabeled break statements can't resolve to loops in an | |
9211 // outer function. | |
9212 String text = r''' | |
9213 void f() { | |
9214 while (true) { | |
9215 void g() { | |
9216 break; | |
9217 } | |
9218 } | |
9219 } | |
9220 '''; | |
9221 CompilationUnit unit = resolveSource(text); | |
9222 BreakStatement breakStatement = EngineTestCase.findNode( | |
9223 unit, text, 'break', (n) => n is BreakStatement); | |
9224 expect(breakStatement.target, isNull); | |
9225 } | |
9226 | |
9227 void test_class_definesCall() { | |
9228 Source source = addSource(r''' | |
9229 class A { | |
9230 int call(int x) { return x; } | |
9231 } | |
9232 int f(A a) { | |
9233 return a(0); | |
9234 }'''); | |
9235 computeLibrarySourceErrors(source); | |
9236 assertNoErrors(source); | |
9237 verify([source]); | |
9238 } | |
9239 | |
9240 void test_class_extends_implements() { | |
9241 Source source = addSource(r''' | |
9242 class A extends B implements C {} | |
9243 class B {} | |
9244 class C {}'''); | |
9245 computeLibrarySourceErrors(source); | |
9246 assertNoErrors(source); | |
9247 verify([source]); | |
9248 } | |
9249 | |
9250 void test_commentReference_class() { | |
9251 Source source = addSource(r''' | |
9252 f() {} | |
9253 /** [A] [new A] [A.n] [new A.n] [m] [f] */ | |
9254 class A { | |
9255 A() {} | |
9256 A.n() {} | |
9257 m() {} | |
9258 }'''); | |
9259 computeLibrarySourceErrors(source); | |
9260 assertNoErrors(source); | |
9261 verify([source]); | |
9262 } | |
9263 | |
9264 void test_commentReference_parameter() { | |
9265 Source source = addSource(r''' | |
9266 class A { | |
9267 A() {} | |
9268 A.n() {} | |
9269 /** [e] [f] */ | |
9270 m(e, f()) {} | |
9271 }'''); | |
9272 computeLibrarySourceErrors(source); | |
9273 assertNoErrors(source); | |
9274 verify([source]); | |
9275 } | |
9276 | |
9277 void test_commentReference_singleLine() { | |
9278 Source source = addSource(r''' | |
9279 /// [A] | |
9280 class A {}'''); | |
9281 computeLibrarySourceErrors(source); | |
9282 assertNoErrors(source); | |
9283 verify([source]); | |
9284 } | |
9285 | |
9286 void test_continueTarget_labeled() { | |
9287 // Verify that the target of the label is correctly found and is recorded | |
9288 // as the unlabeled portion of the statement. | |
9289 String text = r''' | |
9290 void f() { | |
9291 loop1: while (true) { | |
9292 loop2: for (int i = 0; i < 10; i++) { | |
9293 continue loop1; | |
9294 continue loop2; | |
9295 } | |
9296 } | |
9297 } | |
9298 '''; | |
9299 CompilationUnit unit = resolveSource(text); | |
9300 WhileStatement whileStatement = EngineTestCase.findNode( | |
9301 unit, text, 'while (true)', (n) => n is WhileStatement); | |
9302 ForStatement forStatement = | |
9303 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); | |
9304 ContinueStatement continue1 = EngineTestCase.findNode( | |
9305 unit, text, 'continue loop1', (n) => n is ContinueStatement); | |
9306 ContinueStatement continue2 = EngineTestCase.findNode( | |
9307 unit, text, 'continue loop2', (n) => n is ContinueStatement); | |
9308 expect(continue1.target, same(whileStatement)); | |
9309 expect(continue2.target, same(forStatement)); | |
9310 } | |
9311 | |
9312 void test_continueTarget_unlabeledContinueFromDo() { | |
9313 String text = r''' | |
9314 void f() { | |
9315 do { | |
9316 continue; | |
9317 } while (true); | |
9318 } | |
9319 '''; | |
9320 CompilationUnit unit = resolveSource(text); | |
9321 DoStatement doStatement = | |
9322 EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement); | |
9323 ContinueStatement continueStatement = EngineTestCase.findNode( | |
9324 unit, text, 'continue', (n) => n is ContinueStatement); | |
9325 expect(continueStatement.target, same(doStatement)); | |
9326 } | |
9327 | |
9328 void test_continueTarget_unlabeledContinueFromFor() { | |
9329 String text = r''' | |
9330 void f() { | |
9331 for (int i = 0; i < 10; i++) { | |
9332 continue; | |
9333 } | |
9334 } | |
9335 '''; | |
9336 CompilationUnit unit = resolveSource(text); | |
9337 ForStatement forStatement = | |
9338 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); | |
9339 ContinueStatement continueStatement = EngineTestCase.findNode( | |
9340 unit, text, 'continue', (n) => n is ContinueStatement); | |
9341 expect(continueStatement.target, same(forStatement)); | |
9342 } | |
9343 | |
9344 void test_continueTarget_unlabeledContinueFromForEach() { | |
9345 String text = r''' | |
9346 void f() { | |
9347 for (x in []) { | |
9348 continue; | |
9349 } | |
9350 } | |
9351 '''; | |
9352 CompilationUnit unit = resolveSource(text); | |
9353 ForEachStatement forStatement = EngineTestCase.findNode( | |
9354 unit, text, 'for', (n) => n is ForEachStatement); | |
9355 ContinueStatement continueStatement = EngineTestCase.findNode( | |
9356 unit, text, 'continue', (n) => n is ContinueStatement); | |
9357 expect(continueStatement.target, same(forStatement)); | |
9358 } | |
9359 | |
9360 void test_continueTarget_unlabeledContinueFromWhile() { | |
9361 String text = r''' | |
9362 void f() { | |
9363 while (true) { | |
9364 continue; | |
9365 } | |
9366 } | |
9367 '''; | |
9368 CompilationUnit unit = resolveSource(text); | |
9369 WhileStatement whileStatement = EngineTestCase.findNode( | |
9370 unit, text, 'while', (n) => n is WhileStatement); | |
9371 ContinueStatement continueStatement = EngineTestCase.findNode( | |
9372 unit, text, 'continue', (n) => n is ContinueStatement); | |
9373 expect(continueStatement.target, same(whileStatement)); | |
9374 } | |
9375 | |
9376 void test_continueTarget_unlabeledContinueSkipsSwitch() { | |
9377 String text = r''' | |
9378 void f() { | |
9379 while (true) { | |
9380 switch (0) { | |
9381 case 0: | |
9382 continue; | |
9383 } | |
9384 } | |
9385 } | |
9386 '''; | |
9387 CompilationUnit unit = resolveSource(text); | |
9388 WhileStatement whileStatement = EngineTestCase.findNode( | |
9389 unit, text, 'while', (n) => n is WhileStatement); | |
9390 ContinueStatement continueStatement = EngineTestCase.findNode( | |
9391 unit, text, 'continue', (n) => n is ContinueStatement); | |
9392 expect(continueStatement.target, same(whileStatement)); | |
9393 } | |
9394 | |
9395 void test_continueTarget_unlabeledContinueToOuterFunction() { | |
9396 // Verify that unlabeled continue statements can't resolve to loops in an | |
9397 // outer function. | |
9398 String text = r''' | |
9399 void f() { | |
9400 while (true) { | |
9401 void g() { | |
9402 continue; | |
9403 } | |
9404 } | |
9405 } | |
9406 '''; | |
9407 CompilationUnit unit = resolveSource(text); | |
9408 ContinueStatement continueStatement = EngineTestCase.findNode( | |
9409 unit, text, 'continue', (n) => n is ContinueStatement); | |
9410 expect(continueStatement.target, isNull); | |
9411 } | |
9412 | |
9413 void test_empty() { | |
9414 Source source = addSource(""); | |
9415 computeLibrarySourceErrors(source); | |
9416 assertNoErrors(source); | |
9417 verify([source]); | |
9418 } | |
9419 | |
9420 void test_entryPoint_exported() { | |
9421 addNamedSource( | |
9422 "/two.dart", | |
9423 r''' | |
9424 library two; | |
9425 main() {}'''); | |
9426 Source source = addNamedSource( | |
9427 "/one.dart", | |
9428 r''' | |
9429 library one; | |
9430 export 'two.dart';'''); | |
9431 LibraryElement library = resolve2(source); | |
9432 expect(library, isNotNull); | |
9433 FunctionElement main = library.entryPoint; | |
9434 expect(main, isNotNull); | |
9435 expect(main.library, isNot(same(library))); | |
9436 assertNoErrors(source); | |
9437 verify([source]); | |
9438 } | |
9439 | |
9440 void test_entryPoint_local() { | |
9441 Source source = addNamedSource( | |
9442 "/one.dart", | |
9443 r''' | |
9444 library one; | |
9445 main() {}'''); | |
9446 LibraryElement library = resolve2(source); | |
9447 expect(library, isNotNull); | |
9448 FunctionElement main = library.entryPoint; | |
9449 expect(main, isNotNull); | |
9450 expect(main.library, same(library)); | |
9451 assertNoErrors(source); | |
9452 verify([source]); | |
9453 } | |
9454 | |
9455 void test_entryPoint_none() { | |
9456 Source source = addNamedSource("/one.dart", "library one;"); | |
9457 LibraryElement library = resolve2(source); | |
9458 expect(library, isNotNull); | |
9459 expect(library.entryPoint, isNull); | |
9460 assertNoErrors(source); | |
9461 verify([source]); | |
9462 } | |
9463 | |
9464 void test_enum_externalLibrary() { | |
9465 addNamedSource( | |
9466 "/my_lib.dart", | |
9467 r''' | |
9468 library my_lib; | |
9469 enum EEE {A, B, C}'''); | |
9470 Source source = addSource(r''' | |
9471 import 'my_lib.dart'; | |
9472 main() { | |
9473 EEE e = null; | |
9474 }'''); | |
9475 computeLibrarySourceErrors(source); | |
9476 assertNoErrors(source); | |
9477 verify([source]); | |
9478 } | |
9479 | |
9480 void test_extractedMethodAsConstant() { | |
9481 Source source = addSource(r''' | |
9482 abstract class Comparable<T> { | |
9483 int compareTo(T other); | |
9484 static int compare(Comparable a, Comparable b) => a.compareTo(b); | |
9485 } | |
9486 class A { | |
9487 void sort([compare = Comparable.compare]) {} | |
9488 }'''); | |
9489 computeLibrarySourceErrors(source); | |
9490 assertNoErrors(source); | |
9491 verify([source]); | |
9492 } | |
9493 | |
9494 void test_fieldFormalParameter() { | |
9495 Source source = addSource(r''' | |
9496 class A { | |
9497 int x; | |
9498 A(this.x) {} | |
9499 }'''); | |
9500 computeLibrarySourceErrors(source); | |
9501 assertNoErrors(source); | |
9502 verify([source]); | |
9503 } | |
9504 | |
9505 void test_forEachLoops_nonConflicting() { | |
9506 Source source = addSource(r''' | |
9507 f() { | |
9508 List list = [1,2,3]; | |
9509 for (int x in list) {} | |
9510 for (int x in list) {} | |
9511 }'''); | |
9512 computeLibrarySourceErrors(source); | |
9513 assertNoErrors(source); | |
9514 verify([source]); | |
9515 } | |
9516 | |
9517 void test_forLoops_nonConflicting() { | |
9518 Source source = addSource(r''' | |
9519 f() { | |
9520 for (int i = 0; i < 3; i++) { | |
9521 } | |
9522 for (int i = 0; i < 3; i++) { | |
9523 } | |
9524 }'''); | |
9525 computeLibrarySourceErrors(source); | |
9526 assertNoErrors(source); | |
9527 verify([source]); | |
9528 } | |
9529 | |
9530 void test_functionTypeAlias() { | |
9531 Source source = addSource(r''' | |
9532 typedef bool P(e); | |
9533 class A { | |
9534 P p; | |
9535 m(e) { | |
9536 if (p(e)) {} | |
9537 } | |
9538 }'''); | |
9539 computeLibrarySourceErrors(source); | |
9540 assertNoErrors(source); | |
9541 verify([source]); | |
9542 } | |
9543 | |
9544 void test_getter_and_setter_fromMixins_bare_identifier() { | |
9545 Source source = addSource(''' | |
9546 class B {} | |
9547 class M1 { | |
9548 get x => null; | |
9549 set x(value) {} | |
9550 } | |
9551 class M2 { | |
9552 get x => null; | |
9553 set x(value) {} | |
9554 } | |
9555 class C extends B with M1, M2 { | |
9556 void f() { | |
9557 x += 1; | |
9558 } | |
9559 } | |
9560 '''); | |
9561 LibraryElement library = resolve2(source); | |
9562 assertNoErrors(source); | |
9563 verify([source]); | |
9564 // Verify that both the getter and setter for "x" in C.f() refer to the | |
9565 // accessors defined in M2. | |
9566 ClassElement classC = library.definingCompilationUnit.types[3]; | |
9567 MethodDeclaration f = classC.getMethod('f').computeNode(); | |
9568 BlockFunctionBody body = f.body; | |
9569 ExpressionStatement stmt = body.block.statements[0]; | |
9570 AssignmentExpression assignment = stmt.expression; | |
9571 SimpleIdentifier leftHandSide = assignment.leftHandSide; | |
9572 expect(leftHandSide.staticElement.enclosingElement.name, 'M2'); | |
9573 expect(leftHandSide.auxiliaryElements.staticElement.enclosingElement.name, | |
9574 'M2'); | |
9575 } | |
9576 | |
9577 void test_getter_fromMixins_bare_identifier() { | |
9578 Source source = addSource(''' | |
9579 class B {} | |
9580 class M1 { | |
9581 get x => null; | |
9582 } | |
9583 class M2 { | |
9584 get x => null; | |
9585 } | |
9586 class C extends B with M1, M2 { | |
9587 f() { | |
9588 return x; | |
9589 } | |
9590 } | |
9591 '''); | |
9592 LibraryElement library = resolve2(source); | |
9593 assertNoErrors(source); | |
9594 verify([source]); | |
9595 // Verify that the getter for "x" in C.f() refers to the getter defined in | |
9596 // M2. | |
9597 ClassElement classC = library.definingCompilationUnit.types[3]; | |
9598 MethodDeclaration f = classC.getMethod('f').computeNode(); | |
9599 BlockFunctionBody body = f.body; | |
9600 ReturnStatement stmt = body.block.statements[0]; | |
9601 SimpleIdentifier x = stmt.expression; | |
9602 expect(x.staticElement.enclosingElement.name, 'M2'); | |
9603 } | |
9604 | |
9605 void test_getter_fromMixins_property_access() { | |
9606 Source source = addSource(''' | |
9607 class B {} | |
9608 class M1 { | |
9609 get x => null; | |
9610 } | |
9611 class M2 { | |
9612 get x => null; | |
9613 } | |
9614 class C extends B with M1, M2 {} | |
9615 void main() { | |
9616 var y = new C().x; | |
9617 } | |
9618 '''); | |
9619 LibraryElement library = resolve2(source); | |
9620 assertNoErrors(source); | |
9621 verify([source]); | |
9622 // Verify that the getter for "x" in "new C().x" refers to the getter | |
9623 // defined in M2. | |
9624 FunctionDeclaration main = | |
9625 library.definingCompilationUnit.functions[0].computeNode(); | |
9626 BlockFunctionBody body = main.functionExpression.body; | |
9627 VariableDeclarationStatement stmt = body.block.statements[0]; | |
9628 PropertyAccess propertyAccess = stmt.variables.variables[0].initializer; | |
9629 expect( | |
9630 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); | |
9631 } | |
9632 | |
9633 void test_getterAndSetterWithDifferentTypes() { | |
9634 Source source = addSource(r''' | |
9635 class A { | |
9636 int get f => 0; | |
9637 void set f(String s) {} | |
9638 } | |
9639 g (A a) { | |
9640 a.f = a.f.toString(); | |
9641 }'''); | |
9642 computeLibrarySourceErrors(source); | |
9643 assertErrors( | |
9644 source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]); | |
9645 verify([source]); | |
9646 } | |
9647 | |
9648 void test_hasReferenceToSuper() { | |
9649 Source source = addSource(r''' | |
9650 class A {} | |
9651 class B {toString() => super.toString();}'''); | |
9652 LibraryElement library = resolve2(source); | |
9653 expect(library, isNotNull); | |
9654 CompilationUnitElement unit = library.definingCompilationUnit; | |
9655 expect(unit, isNotNull); | |
9656 List<ClassElement> classes = unit.types; | |
9657 expect(classes, hasLength(2)); | |
9658 expect(classes[0].hasReferenceToSuper, isFalse); | |
9659 expect(classes[1].hasReferenceToSuper, isTrue); | |
9660 assertNoErrors(source); | |
9661 verify([source]); | |
9662 } | |
9663 | |
9664 void test_import_hide() { | |
9665 addNamedSource( | |
9666 "/lib1.dart", | |
9667 r''' | |
9668 library lib1; | |
9669 set foo(value) {} | |
9670 class A {}'''); | |
9671 addNamedSource( | |
9672 "/lib2.dart", | |
9673 r''' | |
9674 library lib2; | |
9675 set foo(value) {}'''); | |
9676 Source source = addNamedSource( | |
9677 "/lib3.dart", | |
9678 r''' | |
9679 import 'lib1.dart' hide foo; | |
9680 import 'lib2.dart'; | |
9681 | |
9682 main() { | |
9683 foo = 0; | |
9684 } | |
9685 A a;'''); | |
9686 computeLibrarySourceErrors(source); | |
9687 assertNoErrors(source); | |
9688 verify([source]); | |
9689 } | |
9690 | |
9691 void test_import_prefix() { | |
9692 addNamedSource( | |
9693 "/two.dart", | |
9694 r''' | |
9695 library two; | |
9696 f(int x) { | |
9697 return x * x; | |
9698 }'''); | |
9699 Source source = addNamedSource( | |
9700 "/one.dart", | |
9701 r''' | |
9702 library one; | |
9703 import 'two.dart' as _two; | |
9704 main() { | |
9705 _two.f(0); | |
9706 }'''); | |
9707 computeLibrarySourceErrors(source); | |
9708 assertNoErrors(source); | |
9709 verify([source]); | |
9710 } | |
9711 | |
9712 void test_import_spaceInUri() { | |
9713 addNamedSource( | |
9714 "/sub folder/lib.dart", | |
9715 r''' | |
9716 library lib; | |
9717 foo() {}'''); | |
9718 Source source = addNamedSource( | |
9719 "/app.dart", | |
9720 r''' | |
9721 import 'sub folder/lib.dart'; | |
9722 | |
9723 main() { | |
9724 foo(); | |
9725 }'''); | |
9726 computeLibrarySourceErrors(source); | |
9727 assertNoErrors(source); | |
9728 verify([source]); | |
9729 } | |
9730 | |
9731 void test_indexExpression_typeParameters() { | |
9732 Source source = addSource(r''' | |
9733 f() { | |
9734 List<int> a; | |
9735 a[0]; | |
9736 List<List<int>> b; | |
9737 b[0][0]; | |
9738 List<List<List<int>>> c; | |
9739 c[0][0][0]; | |
9740 }'''); | |
9741 computeLibrarySourceErrors(source); | |
9742 assertNoErrors(source); | |
9743 verify([source]); | |
9744 } | |
9745 | |
9746 void test_indexExpression_typeParameters_invalidAssignmentWarning() { | |
9747 Source source = addSource(r''' | |
9748 f() { | |
9749 List<List<int>> b; | |
9750 b[0][0] = 'hi'; | |
9751 }'''); | |
9752 computeLibrarySourceErrors(source); | |
9753 assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); | |
9754 verify([source]); | |
9755 } | |
9756 | |
9757 void test_indirectOperatorThroughCall() { | |
9758 Source source = addSource(r''' | |
9759 class A { | |
9760 B call() { return new B(); } | |
9761 } | |
9762 | |
9763 class B { | |
9764 int operator [](int i) { return i; } | |
9765 } | |
9766 | |
9767 A f = new A(); | |
9768 | |
9769 g(int x) {} | |
9770 | |
9771 main() { | |
9772 g(f()[0]); | |
9773 }'''); | |
9774 computeLibrarySourceErrors(source); | |
9775 assertNoErrors(source); | |
9776 verify([source]); | |
9777 } | |
9778 | |
9779 void test_invoke_dynamicThroughGetter() { | |
9780 Source source = addSource(r''' | |
9781 class A { | |
9782 List get X => [() => 0]; | |
9783 m(A a) { | |
9784 X.last; | |
9785 } | |
9786 }'''); | |
9787 computeLibrarySourceErrors(source); | |
9788 assertNoErrors(source); | |
9789 verify([source]); | |
9790 } | |
9791 | |
9792 void test_isValidMixin_badSuperclass() { | |
9793 Source source = addSource(r''' | |
9794 class A extends B {} | |
9795 class B {} | |
9796 class C = Object with A;'''); | |
9797 LibraryElement library = resolve2(source); | |
9798 expect(library, isNotNull); | |
9799 CompilationUnitElement unit = library.definingCompilationUnit; | |
9800 expect(unit, isNotNull); | |
9801 ClassElement a = unit.getType('A'); | |
9802 expect(a.isValidMixin, isFalse); | |
9803 assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]); | |
9804 verify([source]); | |
9805 } | |
9806 | |
9807 void test_isValidMixin_badSuperclass_withSuperMixins() { | |
9808 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); | |
9809 Source source = addSource(r''' | |
9810 class A extends B {} | |
9811 class B {} | |
9812 class C = Object with A;'''); | |
9813 LibraryElement library = resolve2(source); | |
9814 expect(library, isNotNull); | |
9815 CompilationUnitElement unit = library.definingCompilationUnit; | |
9816 expect(unit, isNotNull); | |
9817 ClassElement a = unit.getType('A'); | |
9818 expect(a.isValidMixin, isTrue); | |
9819 assertNoErrors(source); | |
9820 verify([source]); | |
9821 } | |
9822 | |
9823 void test_isValidMixin_constructor() { | |
9824 Source source = addSource(r''' | |
9825 class A { | |
9826 A() {} | |
9827 } | |
9828 class C = Object with A;'''); | |
9829 LibraryElement library = resolve2(source); | |
9830 expect(library, isNotNull); | |
9831 CompilationUnitElement unit = library.definingCompilationUnit; | |
9832 expect(unit, isNotNull); | |
9833 ClassElement a = unit.getType('A'); | |
9834 expect(a.isValidMixin, isFalse); | |
9835 assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]); | |
9836 verify([source]); | |
9837 } | |
9838 | |
9839 void test_isValidMixin_constructor_withSuperMixins() { | |
9840 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); | |
9841 Source source = addSource(r''' | |
9842 class A { | |
9843 A() {} | |
9844 } | |
9845 class C = Object with A;'''); | |
9846 LibraryElement library = resolve2(source); | |
9847 expect(library, isNotNull); | |
9848 CompilationUnitElement unit = library.definingCompilationUnit; | |
9849 expect(unit, isNotNull); | |
9850 ClassElement a = unit.getType('A'); | |
9851 expect(a.isValidMixin, isFalse); | |
9852 assertErrors(source, [CompileTimeErrorCode.MIXIN_DECLARES_CONSTRUCTOR]); | |
9853 verify([source]); | |
9854 } | |
9855 | |
9856 void test_isValidMixin_factoryConstructor() { | |
9857 Source source = addSource(r''' | |
9858 class A { | |
9859 factory A() => null; | |
9860 } | |
9861 class C = Object with A;'''); | |
9862 LibraryElement library = resolve2(source); | |
9863 expect(library, isNotNull); | |
9864 CompilationUnitElement unit = library.definingCompilationUnit; | |
9865 expect(unit, isNotNull); | |
9866 ClassElement a = unit.getType('A'); | |
9867 expect(a.isValidMixin, isTrue); | |
9868 assertNoErrors(source); | |
9869 verify([source]); | |
9870 } | |
9871 | |
9872 void test_isValidMixin_factoryConstructor_withSuperMixins() { | |
9873 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); | |
9874 Source source = addSource(r''' | |
9875 class A { | |
9876 factory A() => null; | |
9877 } | |
9878 class C = Object with A;'''); | |
9879 LibraryElement library = resolve2(source); | |
9880 expect(library, isNotNull); | |
9881 CompilationUnitElement unit = library.definingCompilationUnit; | |
9882 expect(unit, isNotNull); | |
9883 ClassElement a = unit.getType('A'); | |
9884 expect(a.isValidMixin, isTrue); | |
9885 assertNoErrors(source); | |
9886 verify([source]); | |
9887 } | |
9888 | |
9889 void test_isValidMixin_super() { | |
9890 Source source = addSource(r''' | |
9891 class A { | |
9892 toString() { | |
9893 return super.toString(); | |
9894 } | |
9895 } | |
9896 class C = Object with A;'''); | |
9897 LibraryElement library = resolve2(source); | |
9898 expect(library, isNotNull); | |
9899 CompilationUnitElement unit = library.definingCompilationUnit; | |
9900 expect(unit, isNotNull); | |
9901 ClassElement a = unit.getType('A'); | |
9902 expect(a.isValidMixin, isFalse); | |
9903 assertErrors(source, [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]); | |
9904 verify([source]); | |
9905 } | |
9906 | |
9907 void test_isValidMixin_super_withSuperMixins() { | |
9908 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); | |
9909 Source source = addSource(r''' | |
9910 class A { | |
9911 toString() { | |
9912 return super.toString(); | |
9913 } | |
9914 } | |
9915 class C = Object with A;'''); | |
9916 LibraryElement library = resolve2(source); | |
9917 expect(library, isNotNull); | |
9918 CompilationUnitElement unit = library.definingCompilationUnit; | |
9919 expect(unit, isNotNull); | |
9920 ClassElement a = unit.getType('A'); | |
9921 expect(a.isValidMixin, isTrue); | |
9922 assertNoErrors(source); | |
9923 verify([source]); | |
9924 } | |
9925 | |
9926 void test_isValidMixin_valid() { | |
9927 Source source = addSource(''' | |
9928 class A {} | |
9929 class C = Object with A;'''); | |
9930 LibraryElement library = resolve2(source); | |
9931 expect(library, isNotNull); | |
9932 CompilationUnitElement unit = library.definingCompilationUnit; | |
9933 expect(unit, isNotNull); | |
9934 ClassElement a = unit.getType('A'); | |
9935 expect(a.isValidMixin, isTrue); | |
9936 assertNoErrors(source); | |
9937 verify([source]); | |
9938 } | |
9939 | |
9940 void test_isValidMixin_valid_withSuperMixins() { | |
9941 resetWithOptions(new AnalysisOptionsImpl()..enableSuperMixins = true); | |
9942 Source source = addSource(''' | |
9943 class A {} | |
9944 class C = Object with A;'''); | |
9945 LibraryElement library = resolve2(source); | |
9946 expect(library, isNotNull); | |
9947 CompilationUnitElement unit = library.definingCompilationUnit; | |
9948 expect(unit, isNotNull); | |
9949 ClassElement a = unit.getType('A'); | |
9950 expect(a.isValidMixin, isTrue); | |
9951 assertNoErrors(source); | |
9952 verify([source]); | |
9953 } | |
9954 | |
9955 void test_labels_switch() { | |
9956 Source source = addSource(r''' | |
9957 void doSwitch(int target) { | |
9958 switch (target) { | |
9959 l0: case 0: | |
9960 continue l1; | |
9961 l1: case 1: | |
9962 continue l0; | |
9963 default: | |
9964 continue l1; | |
9965 } | |
9966 }'''); | |
9967 LibraryElement library = resolve2(source); | |
9968 expect(library, isNotNull); | |
9969 assertNoErrors(source); | |
9970 verify([source]); | |
9971 } | |
9972 | |
9973 void test_localVariable_types_invoked() { | |
9974 Source source = addSource(r''' | |
9975 const A = null; | |
9976 main() { | |
9977 var myVar = (int p) => 'foo'; | |
9978 myVar(42); | |
9979 }'''); | |
9980 LibraryElement library = resolve2(source); | |
9981 expect(library, isNotNull); | |
9982 CompilationUnit unit = | |
9983 analysisContext.resolveCompilationUnit(source, library); | |
9984 expect(unit, isNotNull); | |
9985 List<bool> found = [false]; | |
9986 List<CaughtException> thrownException = new List<CaughtException>(1); | |
9987 unit.accept(new _SimpleResolverTest_localVariable_types_invoked( | |
9988 this, found, thrownException)); | |
9989 if (thrownException[0] != null) { | |
9990 throw new AnalysisException( | |
9991 "Exception", new CaughtException(thrownException[0], null)); | |
9992 } | |
9993 expect(found[0], isTrue); | |
9994 } | |
9995 | |
9996 void test_metadata_class() { | |
9997 Source source = addSource(r''' | |
9998 const A = null; | |
9999 @A class C<A> {}'''); | |
10000 LibraryElement library = resolve2(source); | |
10001 expect(library, isNotNull); | |
10002 CompilationUnitElement unitElement = library.definingCompilationUnit; | |
10003 expect(unitElement, isNotNull); | |
10004 List<ClassElement> classes = unitElement.types; | |
10005 expect(classes, hasLength(1)); | |
10006 List<ElementAnnotation> annotations = classes[0].metadata; | |
10007 expect(annotations, hasLength(1)); | |
10008 assertNoErrors(source); | |
10009 verify([source]); | |
10010 CompilationUnit unit = resolveCompilationUnit(source, library); | |
10011 NodeList<CompilationUnitMember> declarations = unit.declarations; | |
10012 expect(declarations, hasLength(2)); | |
10013 Element expectedElement = (declarations[0] as TopLevelVariableDeclaration) | |
10014 .variables | |
10015 .variables[0] | |
10016 .name | |
10017 .staticElement; | |
10018 EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement, | |
10019 PropertyInducingElement, expectedElement); | |
10020 expectedElement = (expectedElement as PropertyInducingElement).getter; | |
10021 Element actualElement = | |
10022 (declarations[1] as ClassDeclaration).metadata[0].name.staticElement; | |
10023 expect(actualElement, same(expectedElement)); | |
10024 } | |
10025 | |
10026 void test_metadata_field() { | |
10027 Source source = addSource(r''' | |
10028 const A = null; | |
10029 class C { | |
10030 @A int f; | |
10031 }'''); | |
10032 LibraryElement library = resolve2(source); | |
10033 expect(library, isNotNull); | |
10034 CompilationUnitElement unit = library.definingCompilationUnit; | |
10035 expect(unit, isNotNull); | |
10036 List<ClassElement> classes = unit.types; | |
10037 expect(classes, hasLength(1)); | |
10038 FieldElement field = classes[0].fields[0]; | |
10039 List<ElementAnnotation> annotations = field.metadata; | |
10040 expect(annotations, hasLength(1)); | |
10041 assertNoErrors(source); | |
10042 verify([source]); | |
10043 } | |
10044 | |
10045 void test_metadata_fieldFormalParameter() { | |
10046 Source source = addSource(r''' | |
10047 const A = null; | |
10048 class C { | |
10049 int f; | |
10050 C(@A this.f); | |
10051 }'''); | |
10052 LibraryElement library = resolve2(source); | |
10053 expect(library, isNotNull); | |
10054 CompilationUnitElement unit = library.definingCompilationUnit; | |
10055 expect(unit, isNotNull); | |
10056 List<ClassElement> classes = unit.types; | |
10057 expect(classes, hasLength(1)); | |
10058 List<ConstructorElement> constructors = classes[0].constructors; | |
10059 expect(constructors, hasLength(1)); | |
10060 List<ParameterElement> parameters = constructors[0].parameters; | |
10061 expect(parameters, hasLength(1)); | |
10062 List<ElementAnnotation> annotations = parameters[0].metadata; | |
10063 expect(annotations, hasLength(1)); | |
10064 assertNoErrors(source); | |
10065 verify([source]); | |
10066 } | |
10067 | |
10068 void test_metadata_function() { | |
10069 Source source = addSource(r''' | |
10070 const A = null; | |
10071 @A f() {}'''); | |
10072 LibraryElement library = resolve2(source); | |
10073 expect(library, isNotNull); | |
10074 CompilationUnitElement unit = library.definingCompilationUnit; | |
10075 expect(unit, isNotNull); | |
10076 List<FunctionElement> functions = unit.functions; | |
10077 expect(functions, hasLength(1)); | |
10078 List<ElementAnnotation> annotations = functions[0].metadata; | |
10079 expect(annotations, hasLength(1)); | |
10080 assertNoErrors(source); | |
10081 verify([source]); | |
10082 } | |
10083 | |
10084 void test_metadata_functionTypedParameter() { | |
10085 Source source = addSource(r''' | |
10086 const A = null; | |
10087 f(@A int p(int x)) {}'''); | |
10088 LibraryElement library = resolve2(source); | |
10089 expect(library, isNotNull); | |
10090 CompilationUnitElement unit = library.definingCompilationUnit; | |
10091 expect(unit, isNotNull); | |
10092 List<FunctionElement> functions = unit.functions; | |
10093 expect(functions, hasLength(1)); | |
10094 List<ParameterElement> parameters = functions[0].parameters; | |
10095 expect(parameters, hasLength(1)); | |
10096 List<ElementAnnotation> annotations1 = parameters[0].metadata; | |
10097 expect(annotations1, hasLength(1)); | |
10098 assertNoErrors(source); | |
10099 verify([source]); | |
10100 } | |
10101 | |
10102 void test_metadata_libraryDirective() { | |
10103 Source source = addSource(r''' | |
10104 @A library lib; | |
10105 const A = null;'''); | |
10106 LibraryElement library = resolve2(source); | |
10107 expect(library, isNotNull); | |
10108 List<ElementAnnotation> annotations = library.metadata; | |
10109 expect(annotations, hasLength(1)); | |
10110 assertNoErrors(source); | |
10111 verify([source]); | |
10112 } | |
10113 | |
10114 void test_metadata_method() { | |
10115 Source source = addSource(r''' | |
10116 const A = null; | |
10117 class C { | |
10118 @A void m() {} | |
10119 }'''); | |
10120 LibraryElement library = resolve2(source); | |
10121 expect(library, isNotNull); | |
10122 CompilationUnitElement unit = library.definingCompilationUnit; | |
10123 expect(unit, isNotNull); | |
10124 List<ClassElement> classes = unit.types; | |
10125 expect(classes, hasLength(1)); | |
10126 MethodElement method = classes[0].methods[0]; | |
10127 List<ElementAnnotation> annotations = method.metadata; | |
10128 expect(annotations, hasLength(1)); | |
10129 assertNoErrors(source); | |
10130 verify([source]); | |
10131 } | |
10132 | |
10133 void test_metadata_namedParameter() { | |
10134 Source source = addSource(r''' | |
10135 const A = null; | |
10136 f({@A int p : 0}) {}'''); | |
10137 LibraryElement library = resolve2(source); | |
10138 expect(library, isNotNull); | |
10139 CompilationUnitElement unit = library.definingCompilationUnit; | |
10140 expect(unit, isNotNull); | |
10141 List<FunctionElement> functions = unit.functions; | |
10142 expect(functions, hasLength(1)); | |
10143 List<ParameterElement> parameters = functions[0].parameters; | |
10144 expect(parameters, hasLength(1)); | |
10145 List<ElementAnnotation> annotations1 = parameters[0].metadata; | |
10146 expect(annotations1, hasLength(1)); | |
10147 assertNoErrors(source); | |
10148 verify([source]); | |
10149 } | |
10150 | |
10151 void test_metadata_positionalParameter() { | |
10152 Source source = addSource(r''' | |
10153 const A = null; | |
10154 f([@A int p = 0]) {}'''); | |
10155 LibraryElement library = resolve2(source); | |
10156 expect(library, isNotNull); | |
10157 CompilationUnitElement unit = library.definingCompilationUnit; | |
10158 expect(unit, isNotNull); | |
10159 List<FunctionElement> functions = unit.functions; | |
10160 expect(functions, hasLength(1)); | |
10161 List<ParameterElement> parameters = functions[0].parameters; | |
10162 expect(parameters, hasLength(1)); | |
10163 List<ElementAnnotation> annotations1 = parameters[0].metadata; | |
10164 expect(annotations1, hasLength(1)); | |
10165 assertNoErrors(source); | |
10166 verify([source]); | |
10167 } | |
10168 | |
10169 void test_metadata_simpleParameter() { | |
10170 Source source = addSource(r''' | |
10171 const A = null; | |
10172 f(@A p1, @A int p2) {}'''); | |
10173 LibraryElement library = resolve2(source); | |
10174 expect(library, isNotNull); | |
10175 CompilationUnitElement unit = library.definingCompilationUnit; | |
10176 expect(unit, isNotNull); | |
10177 List<FunctionElement> functions = unit.functions; | |
10178 expect(functions, hasLength(1)); | |
10179 List<ParameterElement> parameters = functions[0].parameters; | |
10180 expect(parameters, hasLength(2)); | |
10181 List<ElementAnnotation> annotations1 = parameters[0].metadata; | |
10182 expect(annotations1, hasLength(1)); | |
10183 List<ElementAnnotation> annotations2 = parameters[1].metadata; | |
10184 expect(annotations2, hasLength(1)); | |
10185 assertNoErrors(source); | |
10186 verify([source]); | |
10187 } | |
10188 | |
10189 void test_metadata_typedef() { | |
10190 Source source = addSource(r''' | |
10191 const A = null; | |
10192 @A typedef F<A>();'''); | |
10193 LibraryElement library = resolve2(source); | |
10194 expect(library, isNotNull); | |
10195 CompilationUnitElement unitElement = library.definingCompilationUnit; | |
10196 expect(unitElement, isNotNull); | |
10197 List<FunctionTypeAliasElement> aliases = unitElement.functionTypeAliases; | |
10198 expect(aliases, hasLength(1)); | |
10199 List<ElementAnnotation> annotations = aliases[0].metadata; | |
10200 expect(annotations, hasLength(1)); | |
10201 assertNoErrors(source); | |
10202 verify([source]); | |
10203 CompilationUnit unit = resolveCompilationUnit(source, library); | |
10204 NodeList<CompilationUnitMember> declarations = unit.declarations; | |
10205 expect(declarations, hasLength(2)); | |
10206 Element expectedElement = (declarations[0] as TopLevelVariableDeclaration) | |
10207 .variables | |
10208 .variables[0] | |
10209 .name | |
10210 .staticElement; | |
10211 EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement, | |
10212 PropertyInducingElement, expectedElement); | |
10213 expectedElement = (expectedElement as PropertyInducingElement).getter; | |
10214 Element actualElement = | |
10215 (declarations[1] as FunctionTypeAlias).metadata[0].name.staticElement; | |
10216 expect(actualElement, same(expectedElement)); | |
10217 } | |
10218 | |
10219 void test_method_fromMixin() { | |
10220 Source source = addSource(r''' | |
10221 class B { | |
10222 bar() => 1; | |
10223 } | |
10224 class A { | |
10225 foo() => 2; | |
10226 } | |
10227 | |
10228 class C extends B with A { | |
10229 bar() => super.bar(); | |
10230 foo() => super.foo(); | |
10231 }'''); | |
10232 computeLibrarySourceErrors(source); | |
10233 assertNoErrors(source); | |
10234 verify([source]); | |
10235 } | |
10236 | |
10237 void test_method_fromMixins() { | |
10238 Source source = addSource(''' | |
10239 class B {} | |
10240 class M1 { | |
10241 void f() {} | |
10242 } | |
10243 class M2 { | |
10244 void f() {} | |
10245 } | |
10246 class C extends B with M1, M2 {} | |
10247 void main() { | |
10248 new C().f(); | |
10249 } | |
10250 '''); | |
10251 LibraryElement library = resolve2(source); | |
10252 assertNoErrors(source); | |
10253 verify([source]); | |
10254 // Verify that the "f" in "new C().f()" refers to the "f" defined in M2. | |
10255 FunctionDeclaration main = | |
10256 library.definingCompilationUnit.functions[0].computeNode(); | |
10257 BlockFunctionBody body = main.functionExpression.body; | |
10258 ExpressionStatement stmt = body.block.statements[0]; | |
10259 MethodInvocation expr = stmt.expression; | |
10260 expect(expr.methodName.staticElement.enclosingElement.name, 'M2'); | |
10261 } | |
10262 | |
10263 void test_method_fromMixins_bare_identifier() { | |
10264 Source source = addSource(''' | |
10265 class B {} | |
10266 class M1 { | |
10267 void f() {} | |
10268 } | |
10269 class M2 { | |
10270 void f() {} | |
10271 } | |
10272 class C extends B with M1, M2 { | |
10273 void g() { | |
10274 f(); | |
10275 } | |
10276 } | |
10277 '''); | |
10278 LibraryElement library = resolve2(source); | |
10279 assertNoErrors(source); | |
10280 verify([source]); | |
10281 // Verify that the call to f() in C.g() refers to the method defined in M2. | |
10282 ClassElement classC = library.definingCompilationUnit.types[3]; | |
10283 MethodDeclaration g = classC.getMethod('g').computeNode(); | |
10284 BlockFunctionBody body = g.body; | |
10285 ExpressionStatement stmt = body.block.statements[0]; | |
10286 MethodInvocation invocation = stmt.expression; | |
10287 SimpleIdentifier methodName = invocation.methodName; | |
10288 expect(methodName.staticElement.enclosingElement.name, 'M2'); | |
10289 } | |
10290 | |
10291 void test_method_fromMixins_invked_from_outside_class() { | |
10292 Source source = addSource(''' | |
10293 class B {} | |
10294 class M1 { | |
10295 void f() {} | |
10296 } | |
10297 class M2 { | |
10298 void f() {} | |
10299 } | |
10300 class C extends B with M1, M2 {} | |
10301 void main() { | |
10302 new C().f(); | |
10303 } | |
10304 '''); | |
10305 LibraryElement library = resolve2(source); | |
10306 assertNoErrors(source); | |
10307 verify([source]); | |
10308 // Verify that the call to f() in "new C().f()" refers to the method | |
10309 // defined in M2. | |
10310 FunctionDeclaration main = | |
10311 library.definingCompilationUnit.functions[0].computeNode(); | |
10312 BlockFunctionBody body = main.functionExpression.body; | |
10313 ExpressionStatement stmt = body.block.statements[0]; | |
10314 MethodInvocation invocation = stmt.expression; | |
10315 expect(invocation.methodName.staticElement.enclosingElement.name, 'M2'); | |
10316 } | |
10317 | |
10318 void test_method_fromSuperclassMixin() { | |
10319 Source source = addSource(r''' | |
10320 class A { | |
10321 void m1() {} | |
10322 } | |
10323 class B extends Object with A { | |
10324 } | |
10325 class C extends B { | |
10326 } | |
10327 f(C c) { | |
10328 c.m1(); | |
10329 }'''); | |
10330 computeLibrarySourceErrors(source); | |
10331 assertNoErrors(source); | |
10332 verify([source]); | |
10333 } | |
10334 | |
10335 void test_methodCascades() { | |
10336 Source source = addSource(r''' | |
10337 class A { | |
10338 void m1() {} | |
10339 void m2() {} | |
10340 void m() { | |
10341 A a = new A(); | |
10342 a..m1() | |
10343 ..m2(); | |
10344 } | |
10345 }'''); | |
10346 computeLibrarySourceErrors(source); | |
10347 assertNoErrors(source); | |
10348 verify([source]); | |
10349 } | |
10350 | |
10351 void test_methodCascades_withSetter() { | |
10352 Source source = addSource(r''' | |
10353 class A { | |
10354 String name; | |
10355 void m1() {} | |
10356 void m2() {} | |
10357 void m() { | |
10358 A a = new A(); | |
10359 a..m1() | |
10360 ..name = 'name' | |
10361 ..m2(); | |
10362 } | |
10363 }'''); | |
10364 computeLibrarySourceErrors(source); | |
10365 // failing with error code: INVOCATION_OF_NON_FUNCTION | |
10366 assertNoErrors(source); | |
10367 verify([source]); | |
10368 } | |
10369 | |
10370 void test_resolveAgainstNull() { | |
10371 Source source = addSource(r''' | |
10372 f(var p) { | |
10373 return null == p; | |
10374 }'''); | |
10375 computeLibrarySourceErrors(source); | |
10376 assertNoErrors(source); | |
10377 } | |
10378 | |
10379 void test_setter_fromMixins_bare_identifier() { | |
10380 Source source = addSource(''' | |
10381 class B {} | |
10382 class M1 { | |
10383 set x(value) {} | |
10384 } | |
10385 class M2 { | |
10386 set x(value) {} | |
10387 } | |
10388 class C extends B with M1, M2 { | |
10389 void f() { | |
10390 x = 1; | |
10391 } | |
10392 } | |
10393 '''); | |
10394 LibraryElement library = resolve2(source); | |
10395 assertNoErrors(source); | |
10396 verify([source]); | |
10397 // Verify that the setter for "x" in C.f() refers to the setter defined in | |
10398 // M2. | |
10399 ClassElement classC = library.definingCompilationUnit.types[3]; | |
10400 MethodDeclaration f = classC.getMethod('f').computeNode(); | |
10401 BlockFunctionBody body = f.body; | |
10402 ExpressionStatement stmt = body.block.statements[0]; | |
10403 AssignmentExpression assignment = stmt.expression; | |
10404 SimpleIdentifier leftHandSide = assignment.leftHandSide; | |
10405 expect(leftHandSide.staticElement.enclosingElement.name, 'M2'); | |
10406 } | |
10407 | |
10408 void test_setter_fromMixins_property_access() { | |
10409 Source source = addSource(''' | |
10410 class B {} | |
10411 class M1 { | |
10412 set x(value) {} | |
10413 } | |
10414 class M2 { | |
10415 set x(value) {} | |
10416 } | |
10417 class C extends B with M1, M2 {} | |
10418 void main() { | |
10419 new C().x = 1; | |
10420 } | |
10421 '''); | |
10422 LibraryElement library = resolve2(source); | |
10423 assertNoErrors(source); | |
10424 verify([source]); | |
10425 // Verify that the setter for "x" in "new C().x" refers to the setter | |
10426 // defined in M2. | |
10427 FunctionDeclaration main = | |
10428 library.definingCompilationUnit.functions[0].computeNode(); | |
10429 BlockFunctionBody body = main.functionExpression.body; | |
10430 ExpressionStatement stmt = body.block.statements[0]; | |
10431 AssignmentExpression assignment = stmt.expression; | |
10432 PropertyAccess propertyAccess = assignment.leftHandSide; | |
10433 expect( | |
10434 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); | |
10435 } | |
10436 | |
10437 void test_setter_inherited() { | |
10438 Source source = addSource(r''' | |
10439 class A { | |
10440 int get x => 0; | |
10441 set x(int p) {} | |
10442 } | |
10443 class B extends A { | |
10444 int get x => super.x == null ? 0 : super.x; | |
10445 int f() => x = 1; | |
10446 }'''); | |
10447 computeLibrarySourceErrors(source); | |
10448 assertNoErrors(source); | |
10449 verify([source]); | |
10450 } | |
10451 | |
10452 void test_setter_static() { | |
10453 Source source = addSource(r''' | |
10454 set s(x) { | |
10455 } | |
10456 | |
10457 main() { | |
10458 s = 123; | |
10459 }'''); | |
10460 computeLibrarySourceErrors(source); | |
10461 assertNoErrors(source); | |
10462 verify([source]); | |
10463 } | |
10464 | |
10465 /** | |
10466 * Resolve the given source and verify that the arguments in a specific method
invocation were | |
10467 * correctly resolved. | |
10468 * | |
10469 * The source is expected to be source for a compilation unit, the first decla
ration is expected | |
10470 * to be a class, the first member of which is expected to be a method with a
block body, and the | |
10471 * first statement in the body is expected to be an expression statement whose
expression is a | |
10472 * method invocation. It is the arguments to that method invocation that are t
ested. The method | |
10473 * invocation can contain errors. | |
10474 * | |
10475 * The arguments were resolved correctly if the number of expressions in the l
ist matches the | |
10476 * length of the array of indices and if, for each index in the array of indic
es, the parameter to | |
10477 * which the argument expression was resolved is the parameter in the invoked
method's list of | |
10478 * parameters at that index. Arguments that should not be resolved to a parame
ter because of an | |
10479 * error can be denoted by including a negative index in the array of indices. | |
10480 * | |
10481 * @param source the source to be resolved | |
10482 * @param indices the array of indices used to associate arguments with parame
ters | |
10483 * @throws Exception if the source could not be resolved or if the structure o
f the source is not | |
10484 * valid | |
10485 */ | |
10486 void _validateArgumentResolution(Source source, List<int> indices) { | |
10487 LibraryElement library = resolve2(source); | |
10488 expect(library, isNotNull); | |
10489 ClassElement classElement = library.definingCompilationUnit.types[0]; | |
10490 List<ParameterElement> parameters = classElement.methods[1].parameters; | |
10491 CompilationUnit unit = resolveCompilationUnit(source, library); | |
10492 expect(unit, isNotNull); | |
10493 ClassDeclaration classDeclaration = | |
10494 unit.declarations[0] as ClassDeclaration; | |
10495 MethodDeclaration methodDeclaration = | |
10496 classDeclaration.members[0] as MethodDeclaration; | |
10497 Block block = (methodDeclaration.body as BlockFunctionBody).block; | |
10498 ExpressionStatement statement = block.statements[0] as ExpressionStatement; | |
10499 MethodInvocation invocation = statement.expression as MethodInvocation; | |
10500 NodeList<Expression> arguments = invocation.argumentList.arguments; | |
10501 int argumentCount = arguments.length; | |
10502 expect(argumentCount, indices.length); | |
10503 for (int i = 0; i < argumentCount; i++) { | |
10504 Expression argument = arguments[i]; | |
10505 ParameterElement element = argument.staticParameterElement; | |
10506 int index = indices[i]; | |
10507 if (index < 0) { | |
10508 expect(element, isNull); | |
10509 } else { | |
10510 expect(element, same(parameters[index])); | |
10511 } | |
10512 } | |
10513 } | |
10514 } | |
10515 | |
10516 class SourceContainer_ChangeSetTest_test_toString implements SourceContainer { | 671 class SourceContainer_ChangeSetTest_test_toString implements SourceContainer { |
10517 @override | 672 @override |
10518 bool contains(Source source) => false; | 673 bool contains(Source source) => false; |
10519 } | 674 } |
10520 | 675 |
10521 /** | 676 /** |
10522 * Like [StaticTypeAnalyzerTest], but as end-to-end tests. | |
10523 */ | |
10524 @reflectiveTest | |
10525 class StaticTypeAnalyzer2Test extends _StaticTypeAnalyzer2TestShared { | |
10526 void test_FunctionExpressionInvocation_block() { | |
10527 String code = r''' | |
10528 main() { | |
10529 var foo = (() { return 1; })(); | |
10530 } | |
10531 '''; | |
10532 _resolveTestUnit(code); | |
10533 _expectInitializerType('foo', 'dynamic', isNull); | |
10534 } | |
10535 | |
10536 void test_FunctionExpressionInvocation_curried() { | |
10537 String code = r''' | |
10538 typedef int F(); | |
10539 F f() => null; | |
10540 main() { | |
10541 var foo = f()(); | |
10542 } | |
10543 '''; | |
10544 _resolveTestUnit(code); | |
10545 _expectInitializerType('foo', 'int', isNull); | |
10546 } | |
10547 | |
10548 void test_FunctionExpressionInvocation_expression() { | |
10549 String code = r''' | |
10550 main() { | |
10551 var foo = (() => 1)(); | |
10552 } | |
10553 '''; | |
10554 _resolveTestUnit(code); | |
10555 _expectInitializerType('foo', 'int', isNull); | |
10556 } | |
10557 | |
10558 void test_MethodInvocation_nameType_localVariable() { | |
10559 String code = r""" | |
10560 typedef Foo(); | |
10561 main() { | |
10562 Foo foo; | |
10563 foo(); | |
10564 } | |
10565 """; | |
10566 _resolveTestUnit(code); | |
10567 // "foo" should be resolved to the "Foo" type | |
10568 _expectIdentifierType("foo();", new isInstanceOf<FunctionType>()); | |
10569 } | |
10570 | |
10571 void test_MethodInvocation_nameType_parameter_FunctionTypeAlias() { | |
10572 String code = r""" | |
10573 typedef Foo(); | |
10574 main(Foo foo) { | |
10575 foo(); | |
10576 } | |
10577 """; | |
10578 _resolveTestUnit(code); | |
10579 // "foo" should be resolved to the "Foo" type | |
10580 _expectIdentifierType("foo();", new isInstanceOf<FunctionType>()); | |
10581 } | |
10582 | |
10583 void test_MethodInvocation_nameType_parameter_propagatedType() { | |
10584 String code = r""" | |
10585 typedef Foo(); | |
10586 main(p) { | |
10587 if (p is Foo) { | |
10588 p(); | |
10589 } | |
10590 } | |
10591 """; | |
10592 _resolveTestUnit(code); | |
10593 _expectIdentifierType("p()", DynamicTypeImpl.instance, | |
10594 predicate((type) => type.name == 'Foo')); | |
10595 } | |
10596 | |
10597 void test_staticMethods_classTypeParameters() { | |
10598 String code = r''' | |
10599 class C<T> { | |
10600 static void m() => null; | |
10601 } | |
10602 main() { | |
10603 print(C.m); | |
10604 } | |
10605 '''; | |
10606 _resolveTestUnit(code); | |
10607 _expectFunctionType('m);', '() → void'); | |
10608 } | |
10609 | |
10610 void test_staticMethods_classTypeParameters_genericMethod() { | |
10611 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | |
10612 options.enableGenericMethods = true; | |
10613 resetWithOptions(options); | |
10614 String code = r''' | |
10615 class C<T> { | |
10616 static void m<S>(S s) { | |
10617 void f<U>(S s, U u) {} | |
10618 print(f); | |
10619 } | |
10620 } | |
10621 main() { | |
10622 print(C.m); | |
10623 } | |
10624 '''; | |
10625 _resolveTestUnit(code); | |
10626 // C - m | |
10627 TypeParameterType typeS; | |
10628 { | |
10629 _expectFunctionType('m);', '<S>(S) → void', | |
10630 elementTypeParams: '[S]', typeFormals: '[S]'); | |
10631 | |
10632 FunctionTypeImpl type = _findIdentifier('m);').staticType; | |
10633 typeS = type.typeFormals[0].type; | |
10634 type = type.instantiate([DynamicTypeImpl.instance]); | |
10635 expect(type.toString(), '(dynamic) → void'); | |
10636 expect(type.typeParameters.toString(), '[S]'); | |
10637 expect(type.typeArguments, [DynamicTypeImpl.instance]); | |
10638 expect(type.typeFormals, isEmpty); | |
10639 } | |
10640 // C - m - f | |
10641 { | |
10642 _expectFunctionType('f);', '<U>(S, U) → void', | |
10643 elementTypeParams: '[U]', | |
10644 typeParams: '[S]', | |
10645 typeArgs: '[S]', | |
10646 typeFormals: '[U]'); | |
10647 | |
10648 FunctionTypeImpl type = _findIdentifier('f);').staticType; | |
10649 type = type.instantiate([DynamicTypeImpl.instance]); | |
10650 expect(type.toString(), '(S, dynamic) → void'); | |
10651 expect(type.typeParameters.toString(), '[S, U]'); | |
10652 expect(type.typeArguments, [typeS, DynamicTypeImpl.instance]); | |
10653 expect(type.typeFormals, isEmpty); | |
10654 } | |
10655 } | |
10656 } | |
10657 | |
10658 @reflectiveTest | |
10659 class StaticTypeAnalyzerTest extends EngineTestCase { | |
10660 /** | |
10661 * The error listener to which errors will be reported. | |
10662 */ | |
10663 GatheringErrorListener _listener; | |
10664 | |
10665 /** | |
10666 * The resolver visitor used to create the analyzer. | |
10667 */ | |
10668 ResolverVisitor _visitor; | |
10669 | |
10670 /** | |
10671 * The analyzer being used to analyze the test cases. | |
10672 */ | |
10673 StaticTypeAnalyzer _analyzer; | |
10674 | |
10675 /** | |
10676 * The type provider used to access the types. | |
10677 */ | |
10678 TestTypeProvider _typeProvider; | |
10679 | |
10680 /** | |
10681 * The type system used to analyze the test cases. | |
10682 */ | |
10683 TypeSystem get _typeSystem => _visitor.typeSystem; | |
10684 | |
10685 void fail_visitFunctionExpressionInvocation() { | |
10686 fail("Not yet tested"); | |
10687 _listener.assertNoErrors(); | |
10688 } | |
10689 | |
10690 void fail_visitMethodInvocation() { | |
10691 fail("Not yet tested"); | |
10692 _listener.assertNoErrors(); | |
10693 } | |
10694 | |
10695 void fail_visitSimpleIdentifier() { | |
10696 fail("Not yet tested"); | |
10697 _listener.assertNoErrors(); | |
10698 } | |
10699 | |
10700 @override | |
10701 void setUp() { | |
10702 super.setUp(); | |
10703 _listener = new GatheringErrorListener(); | |
10704 _analyzer = _createAnalyzer(); | |
10705 } | |
10706 | |
10707 void test_flatten_derived() { | |
10708 // class Derived<T> extends Future<T> { ... } | |
10709 ClassElementImpl derivedClass = | |
10710 ElementFactory.classElement2('Derived', ['T']); | |
10711 derivedClass.supertype = _typeProvider.futureType | |
10712 .instantiate([derivedClass.typeParameters[0].type]); | |
10713 InterfaceType intType = _typeProvider.intType; | |
10714 DartType dynamicType = _typeProvider.dynamicType; | |
10715 InterfaceType derivedIntType = derivedClass.type.instantiate([intType]); | |
10716 // flatten(Derived) = dynamic | |
10717 InterfaceType derivedDynamicType = | |
10718 derivedClass.type.instantiate([dynamicType]); | |
10719 expect(_flatten(derivedDynamicType), dynamicType); | |
10720 // flatten(Derived<int>) = int | |
10721 expect(_flatten(derivedIntType), intType); | |
10722 // flatten(Derived<Derived>) = Derived | |
10723 expect(_flatten(derivedClass.type.instantiate([derivedDynamicType])), | |
10724 derivedDynamicType); | |
10725 // flatten(Derived<Derived<int>>) = Derived<int> | |
10726 expect(_flatten(derivedClass.type.instantiate([derivedIntType])), | |
10727 derivedIntType); | |
10728 } | |
10729 | |
10730 void test_flatten_inhibit_recursion() { | |
10731 // class A extends B | |
10732 // class B extends A | |
10733 ClassElementImpl classA = ElementFactory.classElement2('A', []); | |
10734 ClassElementImpl classB = ElementFactory.classElement2('B', []); | |
10735 classA.supertype = classB.type; | |
10736 classB.supertype = classA.type; | |
10737 // flatten(A) = A and flatten(B) = B, since neither class contains Future | |
10738 // in its class hierarchy. Even though there is a loop in the class | |
10739 // hierarchy, flatten() should terminate. | |
10740 expect(_flatten(classA.type), classA.type); | |
10741 expect(_flatten(classB.type), classB.type); | |
10742 } | |
10743 | |
10744 void test_flatten_related_derived_types() { | |
10745 InterfaceType intType = _typeProvider.intType; | |
10746 InterfaceType numType = _typeProvider.numType; | |
10747 // class Derived<T> extends Future<T> | |
10748 ClassElementImpl derivedClass = | |
10749 ElementFactory.classElement2('Derived', ['T']); | |
10750 derivedClass.supertype = _typeProvider.futureType | |
10751 .instantiate([derivedClass.typeParameters[0].type]); | |
10752 InterfaceType derivedType = derivedClass.type; | |
10753 // class A extends Derived<int> implements Derived<num> { ... } | |
10754 ClassElementImpl classA = | |
10755 ElementFactory.classElement('A', derivedType.instantiate([intType])); | |
10756 classA.interfaces = <InterfaceType>[ | |
10757 derivedType.instantiate([numType]) | |
10758 ]; | |
10759 // class B extends Future<num> implements Future<int> { ... } | |
10760 ClassElementImpl classB = | |
10761 ElementFactory.classElement('B', derivedType.instantiate([numType])); | |
10762 classB.interfaces = <InterfaceType>[ | |
10763 derivedType.instantiate([intType]) | |
10764 ]; | |
10765 // flatten(A) = flatten(B) = int, since int is more specific than num. | |
10766 // The code in flatten() that inhibits infinite recursion shouldn't be | |
10767 // fooled by the fact that Derived appears twice in the type hierarchy. | |
10768 expect(_flatten(classA.type), intType); | |
10769 expect(_flatten(classB.type), intType); | |
10770 } | |
10771 | |
10772 void test_flatten_related_types() { | |
10773 InterfaceType futureType = _typeProvider.futureType; | |
10774 InterfaceType intType = _typeProvider.intType; | |
10775 InterfaceType numType = _typeProvider.numType; | |
10776 // class A extends Future<int> implements Future<num> { ... } | |
10777 ClassElementImpl classA = | |
10778 ElementFactory.classElement('A', futureType.instantiate([intType])); | |
10779 classA.interfaces = <InterfaceType>[ | |
10780 futureType.instantiate([numType]) | |
10781 ]; | |
10782 // class B extends Future<num> implements Future<int> { ... } | |
10783 ClassElementImpl classB = | |
10784 ElementFactory.classElement('B', futureType.instantiate([numType])); | |
10785 classB.interfaces = <InterfaceType>[ | |
10786 futureType.instantiate([intType]) | |
10787 ]; | |
10788 // flatten(A) = flatten(B) = int, since int is more specific than num. | |
10789 expect(_flatten(classA.type), intType); | |
10790 expect(_flatten(classB.type), intType); | |
10791 } | |
10792 | |
10793 void test_flatten_simple() { | |
10794 InterfaceType intType = _typeProvider.intType; | |
10795 DartType dynamicType = _typeProvider.dynamicType; | |
10796 InterfaceType futureDynamicType = _typeProvider.futureDynamicType; | |
10797 InterfaceType futureIntType = | |
10798 _typeProvider.futureType.instantiate([intType]); | |
10799 InterfaceType futureFutureDynamicType = | |
10800 _typeProvider.futureType.instantiate([futureDynamicType]); | |
10801 InterfaceType futureFutureIntType = | |
10802 _typeProvider.futureType.instantiate([futureIntType]); | |
10803 // flatten(int) = int | |
10804 expect(_flatten(intType), intType); | |
10805 // flatten(dynamic) = dynamic | |
10806 expect(_flatten(dynamicType), dynamicType); | |
10807 // flatten(Future) = dynamic | |
10808 expect(_flatten(futureDynamicType), dynamicType); | |
10809 // flatten(Future<int>) = int | |
10810 expect(_flatten(futureIntType), intType); | |
10811 // flatten(Future<Future>) = dynamic | |
10812 expect(_flatten(futureFutureDynamicType), dynamicType); | |
10813 // flatten(Future<Future<int>>) = int | |
10814 expect(_flatten(futureFutureIntType), intType); | |
10815 } | |
10816 | |
10817 void test_flatten_unrelated_types() { | |
10818 InterfaceType futureType = _typeProvider.futureType; | |
10819 InterfaceType intType = _typeProvider.intType; | |
10820 InterfaceType stringType = _typeProvider.stringType; | |
10821 // class A extends Future<int> implements Future<String> { ... } | |
10822 ClassElementImpl classA = | |
10823 ElementFactory.classElement('A', futureType.instantiate([intType])); | |
10824 classA.interfaces = <InterfaceType>[ | |
10825 futureType.instantiate([stringType]) | |
10826 ]; | |
10827 // class B extends Future<String> implements Future<int> { ... } | |
10828 ClassElementImpl classB = | |
10829 ElementFactory.classElement('B', futureType.instantiate([stringType])); | |
10830 classB.interfaces = <InterfaceType>[ | |
10831 futureType.instantiate([intType]) | |
10832 ]; | |
10833 // flatten(A) = A and flatten(B) = B, since neither string nor int is more | |
10834 // specific than the other. | |
10835 expect(_flatten(classA.type), classA.type); | |
10836 expect(_flatten(classB.type), classB.type); | |
10837 } | |
10838 | |
10839 void test_visitAdjacentStrings() { | |
10840 // "a" "b" | |
10841 Expression node = AstFactory | |
10842 .adjacentStrings([_resolvedString("a"), _resolvedString("b")]); | |
10843 expect(_analyze(node), same(_typeProvider.stringType)); | |
10844 _listener.assertNoErrors(); | |
10845 } | |
10846 | |
10847 void test_visitAsExpression() { | |
10848 // class A { ... this as B ... } | |
10849 // class B extends A {} | |
10850 ClassElement superclass = ElementFactory.classElement2("A"); | |
10851 InterfaceType superclassType = superclass.type; | |
10852 ClassElement subclass = ElementFactory.classElement("B", superclassType); | |
10853 Expression node = AstFactory.asExpression( | |
10854 AstFactory.thisExpression(), AstFactory.typeName(subclass)); | |
10855 expect(_analyze3(node, superclassType), same(subclass.type)); | |
10856 _listener.assertNoErrors(); | |
10857 } | |
10858 | |
10859 void test_visitAssignmentExpression_compound() { | |
10860 // i += 1 | |
10861 InterfaceType numType = _typeProvider.numType; | |
10862 SimpleIdentifier identifier = _resolvedVariable(_typeProvider.intType, "i"); | |
10863 AssignmentExpression node = AstFactory.assignmentExpression( | |
10864 identifier, TokenType.PLUS_EQ, _resolvedInteger(1)); | |
10865 MethodElement plusMethod = getMethod(numType, "+"); | |
10866 node.staticElement = plusMethod; | |
10867 expect(_analyze(node), same(numType)); | |
10868 _listener.assertNoErrors(); | |
10869 } | |
10870 | |
10871 void test_visitAssignmentExpression_compoundIfNull_differentTypes() { | |
10872 // double d; d ??= 0 | |
10873 Expression node = AstFactory.assignmentExpression( | |
10874 _resolvedVariable(_typeProvider.doubleType, 'd'), | |
10875 TokenType.QUESTION_QUESTION_EQ, | |
10876 _resolvedInteger(0)); | |
10877 expect(_analyze(node), same(_typeProvider.numType)); | |
10878 _listener.assertNoErrors(); | |
10879 } | |
10880 | |
10881 void test_visitAssignmentExpression_compoundIfNull_sameTypes() { | |
10882 // int i; i ??= 0 | |
10883 Expression node = AstFactory.assignmentExpression( | |
10884 _resolvedVariable(_typeProvider.intType, 'i'), | |
10885 TokenType.QUESTION_QUESTION_EQ, | |
10886 _resolvedInteger(0)); | |
10887 expect(_analyze(node), same(_typeProvider.intType)); | |
10888 _listener.assertNoErrors(); | |
10889 } | |
10890 | |
10891 void test_visitAssignmentExpression_simple() { | |
10892 // i = 0 | |
10893 InterfaceType intType = _typeProvider.intType; | |
10894 Expression node = AstFactory.assignmentExpression( | |
10895 _resolvedVariable(intType, "i"), TokenType.EQ, _resolvedInteger(0)); | |
10896 expect(_analyze(node), same(intType)); | |
10897 _listener.assertNoErrors(); | |
10898 } | |
10899 | |
10900 void test_visitAwaitExpression_flattened() { | |
10901 // await e, where e has type Future<Future<int>> | |
10902 InterfaceType intType = _typeProvider.intType; | |
10903 InterfaceType futureIntType = | |
10904 _typeProvider.futureType.instantiate(<DartType>[intType]); | |
10905 InterfaceType futureFutureIntType = | |
10906 _typeProvider.futureType.instantiate(<DartType>[futureIntType]); | |
10907 Expression node = | |
10908 AstFactory.awaitExpression(_resolvedVariable(futureFutureIntType, 'e')); | |
10909 expect(_analyze(node), same(intType)); | |
10910 _listener.assertNoErrors(); | |
10911 } | |
10912 | |
10913 void test_visitAwaitExpression_simple() { | |
10914 // await e, where e has type Future<int> | |
10915 InterfaceType intType = _typeProvider.intType; | |
10916 InterfaceType futureIntType = | |
10917 _typeProvider.futureType.instantiate(<DartType>[intType]); | |
10918 Expression node = | |
10919 AstFactory.awaitExpression(_resolvedVariable(futureIntType, 'e')); | |
10920 expect(_analyze(node), same(intType)); | |
10921 _listener.assertNoErrors(); | |
10922 } | |
10923 | |
10924 void test_visitBinaryExpression_equals() { | |
10925 // 2 == 3 | |
10926 Expression node = AstFactory.binaryExpression( | |
10927 _resolvedInteger(2), TokenType.EQ_EQ, _resolvedInteger(3)); | |
10928 expect(_analyze(node), same(_typeProvider.boolType)); | |
10929 _listener.assertNoErrors(); | |
10930 } | |
10931 | |
10932 void test_visitBinaryExpression_ifNull() { | |
10933 // 1 ?? 1.5 | |
10934 Expression node = AstFactory.binaryExpression( | |
10935 _resolvedInteger(1), TokenType.QUESTION_QUESTION, _resolvedDouble(1.5)); | |
10936 expect(_analyze(node), same(_typeProvider.numType)); | |
10937 _listener.assertNoErrors(); | |
10938 } | |
10939 | |
10940 void test_visitBinaryExpression_logicalAnd() { | |
10941 // false && true | |
10942 Expression node = AstFactory.binaryExpression( | |
10943 AstFactory.booleanLiteral(false), | |
10944 TokenType.AMPERSAND_AMPERSAND, | |
10945 AstFactory.booleanLiteral(true)); | |
10946 expect(_analyze(node), same(_typeProvider.boolType)); | |
10947 _listener.assertNoErrors(); | |
10948 } | |
10949 | |
10950 void test_visitBinaryExpression_logicalOr() { | |
10951 // false || true | |
10952 Expression node = AstFactory.binaryExpression( | |
10953 AstFactory.booleanLiteral(false), | |
10954 TokenType.BAR_BAR, | |
10955 AstFactory.booleanLiteral(true)); | |
10956 expect(_analyze(node), same(_typeProvider.boolType)); | |
10957 _listener.assertNoErrors(); | |
10958 } | |
10959 | |
10960 void test_visitBinaryExpression_minusID_propagated() { | |
10961 // a - b | |
10962 BinaryExpression node = AstFactory.binaryExpression( | |
10963 _propagatedVariable(_typeProvider.intType, 'a'), | |
10964 TokenType.MINUS, | |
10965 _propagatedVariable(_typeProvider.doubleType, 'b')); | |
10966 node.propagatedElement = getMethod(_typeProvider.numType, "+"); | |
10967 _analyze(node); | |
10968 expect(node.propagatedType, same(_typeProvider.doubleType)); | |
10969 _listener.assertNoErrors(); | |
10970 } | |
10971 | |
10972 void test_visitBinaryExpression_notEquals() { | |
10973 // 2 != 3 | |
10974 Expression node = AstFactory.binaryExpression( | |
10975 _resolvedInteger(2), TokenType.BANG_EQ, _resolvedInteger(3)); | |
10976 expect(_analyze(node), same(_typeProvider.boolType)); | |
10977 _listener.assertNoErrors(); | |
10978 } | |
10979 | |
10980 void test_visitBinaryExpression_plusID() { | |
10981 // 1 + 2.0 | |
10982 BinaryExpression node = AstFactory.binaryExpression( | |
10983 _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0)); | |
10984 node.staticElement = getMethod(_typeProvider.numType, "+"); | |
10985 expect(_analyze(node), same(_typeProvider.doubleType)); | |
10986 _listener.assertNoErrors(); | |
10987 } | |
10988 | |
10989 void test_visitBinaryExpression_plusII() { | |
10990 // 1 + 2 | |
10991 BinaryExpression node = AstFactory.binaryExpression( | |
10992 _resolvedInteger(1), TokenType.PLUS, _resolvedInteger(2)); | |
10993 node.staticElement = getMethod(_typeProvider.numType, "+"); | |
10994 expect(_analyze(node), same(_typeProvider.intType)); | |
10995 _listener.assertNoErrors(); | |
10996 } | |
10997 | |
10998 void test_visitBinaryExpression_plusII_propagated() { | |
10999 // a + b | |
11000 BinaryExpression node = AstFactory.binaryExpression( | |
11001 _propagatedVariable(_typeProvider.intType, 'a'), | |
11002 TokenType.PLUS, | |
11003 _propagatedVariable(_typeProvider.intType, 'b')); | |
11004 node.propagatedElement = getMethod(_typeProvider.numType, "+"); | |
11005 _analyze(node); | |
11006 expect(node.propagatedType, same(_typeProvider.intType)); | |
11007 _listener.assertNoErrors(); | |
11008 } | |
11009 | |
11010 void test_visitBinaryExpression_slash() { | |
11011 // 2 / 2 | |
11012 BinaryExpression node = AstFactory.binaryExpression( | |
11013 _resolvedInteger(2), TokenType.SLASH, _resolvedInteger(2)); | |
11014 node.staticElement = getMethod(_typeProvider.numType, "/"); | |
11015 expect(_analyze(node), same(_typeProvider.doubleType)); | |
11016 _listener.assertNoErrors(); | |
11017 } | |
11018 | |
11019 void test_visitBinaryExpression_star_notSpecial() { | |
11020 // class A { | |
11021 // A operator *(double value); | |
11022 // } | |
11023 // (a as A) * 2.0 | |
11024 ClassElementImpl classA = ElementFactory.classElement2("A"); | |
11025 InterfaceType typeA = classA.type; | |
11026 MethodElement operator = | |
11027 ElementFactory.methodElement("*", typeA, [_typeProvider.doubleType]); | |
11028 classA.methods = <MethodElement>[operator]; | |
11029 BinaryExpression node = AstFactory.binaryExpression( | |
11030 AstFactory.asExpression( | |
11031 AstFactory.identifier3("a"), AstFactory.typeName(classA)), | |
11032 TokenType.PLUS, | |
11033 _resolvedDouble(2.0)); | |
11034 node.staticElement = operator; | |
11035 expect(_analyze(node), same(typeA)); | |
11036 _listener.assertNoErrors(); | |
11037 } | |
11038 | |
11039 void test_visitBinaryExpression_starID() { | |
11040 // 1 * 2.0 | |
11041 BinaryExpression node = AstFactory.binaryExpression( | |
11042 _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0)); | |
11043 node.staticElement = getMethod(_typeProvider.numType, "*"); | |
11044 expect(_analyze(node), same(_typeProvider.doubleType)); | |
11045 _listener.assertNoErrors(); | |
11046 } | |
11047 | |
11048 void test_visitBooleanLiteral_false() { | |
11049 // false | |
11050 Expression node = AstFactory.booleanLiteral(false); | |
11051 expect(_analyze(node), same(_typeProvider.boolType)); | |
11052 _listener.assertNoErrors(); | |
11053 } | |
11054 | |
11055 void test_visitBooleanLiteral_true() { | |
11056 // true | |
11057 Expression node = AstFactory.booleanLiteral(true); | |
11058 expect(_analyze(node), same(_typeProvider.boolType)); | |
11059 _listener.assertNoErrors(); | |
11060 } | |
11061 | |
11062 void test_visitCascadeExpression() { | |
11063 // a..length | |
11064 Expression node = AstFactory.cascadeExpression( | |
11065 _resolvedString("a"), [AstFactory.propertyAccess2(null, "length")]); | |
11066 expect(_analyze(node), same(_typeProvider.stringType)); | |
11067 _listener.assertNoErrors(); | |
11068 } | |
11069 | |
11070 void test_visitConditionalExpression_differentTypes() { | |
11071 // true ? 1.0 : 0 | |
11072 Expression node = AstFactory.conditionalExpression( | |
11073 AstFactory.booleanLiteral(true), | |
11074 _resolvedDouble(1.0), | |
11075 _resolvedInteger(0)); | |
11076 expect(_analyze(node), same(_typeProvider.numType)); | |
11077 _listener.assertNoErrors(); | |
11078 } | |
11079 | |
11080 void test_visitConditionalExpression_sameTypes() { | |
11081 // true ? 1 : 0 | |
11082 Expression node = AstFactory.conditionalExpression( | |
11083 AstFactory.booleanLiteral(true), | |
11084 _resolvedInteger(1), | |
11085 _resolvedInteger(0)); | |
11086 expect(_analyze(node), same(_typeProvider.intType)); | |
11087 _listener.assertNoErrors(); | |
11088 } | |
11089 | |
11090 void test_visitDoubleLiteral() { | |
11091 // 4.33 | |
11092 Expression node = AstFactory.doubleLiteral(4.33); | |
11093 expect(_analyze(node), same(_typeProvider.doubleType)); | |
11094 _listener.assertNoErrors(); | |
11095 } | |
11096 | |
11097 void test_visitFunctionExpression_async_block() { | |
11098 // () async {} | |
11099 BlockFunctionBody body = AstFactory.blockFunctionBody2(); | |
11100 body.keyword = TokenFactory.tokenFromString('async'); | |
11101 FunctionExpression node = | |
11102 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); | |
11103 DartType resultType = _analyze(node); | |
11104 _assertFunctionType( | |
11105 _typeProvider.futureDynamicType, null, null, null, resultType); | |
11106 _listener.assertNoErrors(); | |
11107 } | |
11108 | |
11109 void test_visitFunctionExpression_async_expression() { | |
11110 // () async => e, where e has type int | |
11111 InterfaceType intType = _typeProvider.intType; | |
11112 InterfaceType futureIntType = | |
11113 _typeProvider.futureType.instantiate(<DartType>[intType]); | |
11114 Expression expression = _resolvedVariable(intType, 'e'); | |
11115 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); | |
11116 body.keyword = TokenFactory.tokenFromString('async'); | |
11117 FunctionExpression node = | |
11118 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); | |
11119 DartType resultType = _analyze(node); | |
11120 _assertFunctionType(futureIntType, null, null, null, resultType); | |
11121 _listener.assertNoErrors(); | |
11122 } | |
11123 | |
11124 void test_visitFunctionExpression_async_expression_flatten() { | |
11125 // () async => e, where e has type Future<int> | |
11126 InterfaceType intType = _typeProvider.intType; | |
11127 InterfaceType futureIntType = | |
11128 _typeProvider.futureType.instantiate(<DartType>[intType]); | |
11129 Expression expression = _resolvedVariable(futureIntType, 'e'); | |
11130 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); | |
11131 body.keyword = TokenFactory.tokenFromString('async'); | |
11132 FunctionExpression node = | |
11133 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); | |
11134 DartType resultType = _analyze(node); | |
11135 _assertFunctionType(futureIntType, null, null, null, resultType); | |
11136 _listener.assertNoErrors(); | |
11137 } | |
11138 | |
11139 void test_visitFunctionExpression_async_expression_flatten_twice() { | |
11140 // () async => e, where e has type Future<Future<int>> | |
11141 InterfaceType intType = _typeProvider.intType; | |
11142 InterfaceType futureIntType = | |
11143 _typeProvider.futureType.instantiate(<DartType>[intType]); | |
11144 InterfaceType futureFutureIntType = | |
11145 _typeProvider.futureType.instantiate(<DartType>[futureIntType]); | |
11146 Expression expression = _resolvedVariable(futureFutureIntType, 'e'); | |
11147 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); | |
11148 body.keyword = TokenFactory.tokenFromString('async'); | |
11149 FunctionExpression node = | |
11150 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); | |
11151 DartType resultType = _analyze(node); | |
11152 _assertFunctionType(futureIntType, null, null, null, resultType); | |
11153 _listener.assertNoErrors(); | |
11154 } | |
11155 | |
11156 void test_visitFunctionExpression_generator_async() { | |
11157 // () async* {} | |
11158 BlockFunctionBody body = AstFactory.blockFunctionBody2(); | |
11159 body.keyword = TokenFactory.tokenFromString('async'); | |
11160 body.star = TokenFactory.tokenFromType(TokenType.STAR); | |
11161 FunctionExpression node = | |
11162 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); | |
11163 DartType resultType = _analyze(node); | |
11164 _assertFunctionType( | |
11165 _typeProvider.streamDynamicType, null, null, null, resultType); | |
11166 _listener.assertNoErrors(); | |
11167 } | |
11168 | |
11169 void test_visitFunctionExpression_generator_sync() { | |
11170 // () sync* {} | |
11171 BlockFunctionBody body = AstFactory.blockFunctionBody2(); | |
11172 body.keyword = TokenFactory.tokenFromString('sync'); | |
11173 body.star = TokenFactory.tokenFromType(TokenType.STAR); | |
11174 FunctionExpression node = | |
11175 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); | |
11176 DartType resultType = _analyze(node); | |
11177 _assertFunctionType( | |
11178 _typeProvider.iterableDynamicType, null, null, null, resultType); | |
11179 _listener.assertNoErrors(); | |
11180 } | |
11181 | |
11182 void test_visitFunctionExpression_named_block() { | |
11183 // ({p1 : 0, p2 : 0}) {} | |
11184 DartType dynamicType = _typeProvider.dynamicType; | |
11185 FormalParameter p1 = AstFactory.namedFormalParameter( | |
11186 AstFactory.simpleFormalParameter3("p1"), _resolvedInteger(0)); | |
11187 _setType(p1, dynamicType); | |
11188 FormalParameter p2 = AstFactory.namedFormalParameter( | |
11189 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); | |
11190 _setType(p2, dynamicType); | |
11191 FunctionExpression node = _resolvedFunctionExpression( | |
11192 AstFactory.formalParameterList([p1, p2]), | |
11193 AstFactory.blockFunctionBody2()); | |
11194 _analyze5(p1); | |
11195 _analyze5(p2); | |
11196 DartType resultType = _analyze(node); | |
11197 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); | |
11198 expectedNamedTypes["p1"] = dynamicType; | |
11199 expectedNamedTypes["p2"] = dynamicType; | |
11200 _assertFunctionType( | |
11201 dynamicType, null, null, expectedNamedTypes, resultType); | |
11202 _listener.assertNoErrors(); | |
11203 } | |
11204 | |
11205 void test_visitFunctionExpression_named_expression() { | |
11206 // ({p : 0}) -> 0; | |
11207 DartType dynamicType = _typeProvider.dynamicType; | |
11208 FormalParameter p = AstFactory.namedFormalParameter( | |
11209 AstFactory.simpleFormalParameter3("p"), _resolvedInteger(0)); | |
11210 _setType(p, dynamicType); | |
11211 FunctionExpression node = _resolvedFunctionExpression( | |
11212 AstFactory.formalParameterList([p]), | |
11213 AstFactory.expressionFunctionBody(_resolvedInteger(0))); | |
11214 _analyze5(p); | |
11215 DartType resultType = _analyze(node); | |
11216 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); | |
11217 expectedNamedTypes["p"] = dynamicType; | |
11218 _assertFunctionType( | |
11219 _typeProvider.intType, null, null, expectedNamedTypes, resultType); | |
11220 _listener.assertNoErrors(); | |
11221 } | |
11222 | |
11223 void test_visitFunctionExpression_normal_block() { | |
11224 // (p1, p2) {} | |
11225 DartType dynamicType = _typeProvider.dynamicType; | |
11226 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); | |
11227 _setType(p1, dynamicType); | |
11228 FormalParameter p2 = AstFactory.simpleFormalParameter3("p2"); | |
11229 _setType(p2, dynamicType); | |
11230 FunctionExpression node = _resolvedFunctionExpression( | |
11231 AstFactory.formalParameterList([p1, p2]), | |
11232 AstFactory.blockFunctionBody2()); | |
11233 _analyze5(p1); | |
11234 _analyze5(p2); | |
11235 DartType resultType = _analyze(node); | |
11236 _assertFunctionType(dynamicType, <DartType>[dynamicType, dynamicType], null, | |
11237 null, resultType); | |
11238 _listener.assertNoErrors(); | |
11239 } | |
11240 | |
11241 void test_visitFunctionExpression_normal_expression() { | |
11242 // (p1, p2) -> 0 | |
11243 DartType dynamicType = _typeProvider.dynamicType; | |
11244 FormalParameter p = AstFactory.simpleFormalParameter3("p"); | |
11245 _setType(p, dynamicType); | |
11246 FunctionExpression node = _resolvedFunctionExpression( | |
11247 AstFactory.formalParameterList([p]), | |
11248 AstFactory.expressionFunctionBody(_resolvedInteger(0))); | |
11249 _analyze5(p); | |
11250 DartType resultType = _analyze(node); | |
11251 _assertFunctionType( | |
11252 _typeProvider.intType, <DartType>[dynamicType], null, null, resultType); | |
11253 _listener.assertNoErrors(); | |
11254 } | |
11255 | |
11256 void test_visitFunctionExpression_normalAndNamed_block() { | |
11257 // (p1, {p2 : 0}) {} | |
11258 DartType dynamicType = _typeProvider.dynamicType; | |
11259 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); | |
11260 _setType(p1, dynamicType); | |
11261 FormalParameter p2 = AstFactory.namedFormalParameter( | |
11262 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); | |
11263 _setType(p2, dynamicType); | |
11264 FunctionExpression node = _resolvedFunctionExpression( | |
11265 AstFactory.formalParameterList([p1, p2]), | |
11266 AstFactory.blockFunctionBody2()); | |
11267 _analyze5(p2); | |
11268 DartType resultType = _analyze(node); | |
11269 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); | |
11270 expectedNamedTypes["p2"] = dynamicType; | |
11271 _assertFunctionType(dynamicType, <DartType>[dynamicType], null, | |
11272 expectedNamedTypes, resultType); | |
11273 _listener.assertNoErrors(); | |
11274 } | |
11275 | |
11276 void test_visitFunctionExpression_normalAndNamed_expression() { | |
11277 // (p1, {p2 : 0}) -> 0 | |
11278 DartType dynamicType = _typeProvider.dynamicType; | |
11279 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); | |
11280 _setType(p1, dynamicType); | |
11281 FormalParameter p2 = AstFactory.namedFormalParameter( | |
11282 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); | |
11283 _setType(p2, dynamicType); | |
11284 FunctionExpression node = _resolvedFunctionExpression( | |
11285 AstFactory.formalParameterList([p1, p2]), | |
11286 AstFactory.expressionFunctionBody(_resolvedInteger(0))); | |
11287 _analyze5(p2); | |
11288 DartType resultType = _analyze(node); | |
11289 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); | |
11290 expectedNamedTypes["p2"] = dynamicType; | |
11291 _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], null, | |
11292 expectedNamedTypes, resultType); | |
11293 _listener.assertNoErrors(); | |
11294 } | |
11295 | |
11296 void test_visitFunctionExpression_normalAndPositional_block() { | |
11297 // (p1, [p2 = 0]) {} | |
11298 DartType dynamicType = _typeProvider.dynamicType; | |
11299 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); | |
11300 _setType(p1, dynamicType); | |
11301 FormalParameter p2 = AstFactory.positionalFormalParameter( | |
11302 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); | |
11303 _setType(p2, dynamicType); | |
11304 FunctionExpression node = _resolvedFunctionExpression( | |
11305 AstFactory.formalParameterList([p1, p2]), | |
11306 AstFactory.blockFunctionBody2()); | |
11307 _analyze5(p1); | |
11308 _analyze5(p2); | |
11309 DartType resultType = _analyze(node); | |
11310 _assertFunctionType(dynamicType, <DartType>[dynamicType], | |
11311 <DartType>[dynamicType], null, resultType); | |
11312 _listener.assertNoErrors(); | |
11313 } | |
11314 | |
11315 void test_visitFunctionExpression_normalAndPositional_expression() { | |
11316 // (p1, [p2 = 0]) -> 0 | |
11317 DartType dynamicType = _typeProvider.dynamicType; | |
11318 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); | |
11319 _setType(p1, dynamicType); | |
11320 FormalParameter p2 = AstFactory.positionalFormalParameter( | |
11321 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); | |
11322 _setType(p2, dynamicType); | |
11323 FunctionExpression node = _resolvedFunctionExpression( | |
11324 AstFactory.formalParameterList([p1, p2]), | |
11325 AstFactory.expressionFunctionBody(_resolvedInteger(0))); | |
11326 _analyze5(p1); | |
11327 _analyze5(p2); | |
11328 DartType resultType = _analyze(node); | |
11329 _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], | |
11330 <DartType>[dynamicType], null, resultType); | |
11331 _listener.assertNoErrors(); | |
11332 } | |
11333 | |
11334 void test_visitFunctionExpression_positional_block() { | |
11335 // ([p1 = 0, p2 = 0]) {} | |
11336 DartType dynamicType = _typeProvider.dynamicType; | |
11337 FormalParameter p1 = AstFactory.positionalFormalParameter( | |
11338 AstFactory.simpleFormalParameter3("p1"), _resolvedInteger(0)); | |
11339 _setType(p1, dynamicType); | |
11340 FormalParameter p2 = AstFactory.positionalFormalParameter( | |
11341 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); | |
11342 _setType(p2, dynamicType); | |
11343 FunctionExpression node = _resolvedFunctionExpression( | |
11344 AstFactory.formalParameterList([p1, p2]), | |
11345 AstFactory.blockFunctionBody2()); | |
11346 _analyze5(p1); | |
11347 _analyze5(p2); | |
11348 DartType resultType = _analyze(node); | |
11349 _assertFunctionType(dynamicType, null, <DartType>[dynamicType, dynamicType], | |
11350 null, resultType); | |
11351 _listener.assertNoErrors(); | |
11352 } | |
11353 | |
11354 void test_visitFunctionExpression_positional_expression() { | |
11355 // ([p1 = 0, p2 = 0]) -> 0 | |
11356 DartType dynamicType = _typeProvider.dynamicType; | |
11357 FormalParameter p = AstFactory.positionalFormalParameter( | |
11358 AstFactory.simpleFormalParameter3("p"), _resolvedInteger(0)); | |
11359 _setType(p, dynamicType); | |
11360 FunctionExpression node = _resolvedFunctionExpression( | |
11361 AstFactory.formalParameterList([p]), | |
11362 AstFactory.expressionFunctionBody(_resolvedInteger(0))); | |
11363 _analyze5(p); | |
11364 DartType resultType = _analyze(node); | |
11365 _assertFunctionType( | |
11366 _typeProvider.intType, null, <DartType>[dynamicType], null, resultType); | |
11367 _listener.assertNoErrors(); | |
11368 } | |
11369 | |
11370 void test_visitIndexExpression_getter() { | |
11371 // List a; | |
11372 // a[2] | |
11373 InterfaceType listType = _typeProvider.listType; | |
11374 SimpleIdentifier identifier = _resolvedVariable(listType, "a"); | |
11375 IndexExpression node = | |
11376 AstFactory.indexExpression(identifier, _resolvedInteger(2)); | |
11377 MethodElement indexMethod = listType.element.methods[0]; | |
11378 node.staticElement = indexMethod; | |
11379 expect(_analyze(node), same(listType.typeArguments[0])); | |
11380 _listener.assertNoErrors(); | |
11381 } | |
11382 | |
11383 void test_visitIndexExpression_setter() { | |
11384 // List a; | |
11385 // a[2] = 0 | |
11386 InterfaceType listType = _typeProvider.listType; | |
11387 SimpleIdentifier identifier = _resolvedVariable(listType, "a"); | |
11388 IndexExpression node = | |
11389 AstFactory.indexExpression(identifier, _resolvedInteger(2)); | |
11390 MethodElement indexMethod = listType.element.methods[1]; | |
11391 node.staticElement = indexMethod; | |
11392 AstFactory.assignmentExpression(node, TokenType.EQ, AstFactory.integer(0)); | |
11393 expect(_analyze(node), same(listType.typeArguments[0])); | |
11394 _listener.assertNoErrors(); | |
11395 } | |
11396 | |
11397 void test_visitIndexExpression_typeParameters() { | |
11398 // List<int> list = ... | |
11399 // list[0] | |
11400 InterfaceType intType = _typeProvider.intType; | |
11401 InterfaceType listType = _typeProvider.listType; | |
11402 // (int) -> E | |
11403 MethodElement methodElement = getMethod(listType, "[]"); | |
11404 // "list" has type List<int> | |
11405 SimpleIdentifier identifier = AstFactory.identifier3("list"); | |
11406 InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]); | |
11407 identifier.staticType = listOfIntType; | |
11408 // list[0] has MethodElement element (int) -> E | |
11409 IndexExpression indexExpression = | |
11410 AstFactory.indexExpression(identifier, AstFactory.integer(0)); | |
11411 MethodElement indexMethod = MethodMember.from(methodElement, listOfIntType); | |
11412 indexExpression.staticElement = indexMethod; | |
11413 // analyze and assert result of the index expression | |
11414 expect(_analyze(indexExpression), same(intType)); | |
11415 _listener.assertNoErrors(); | |
11416 } | |
11417 | |
11418 void test_visitIndexExpression_typeParameters_inSetterContext() { | |
11419 // List<int> list = ... | |
11420 // list[0] = 0; | |
11421 InterfaceType intType = _typeProvider.intType; | |
11422 InterfaceType listType = _typeProvider.listType; | |
11423 // (int, E) -> void | |
11424 MethodElement methodElement = getMethod(listType, "[]="); | |
11425 // "list" has type List<int> | |
11426 SimpleIdentifier identifier = AstFactory.identifier3("list"); | |
11427 InterfaceType listOfIntType = listType.instantiate(<DartType>[intType]); | |
11428 identifier.staticType = listOfIntType; | |
11429 // list[0] has MethodElement element (int) -> E | |
11430 IndexExpression indexExpression = | |
11431 AstFactory.indexExpression(identifier, AstFactory.integer(0)); | |
11432 MethodElement indexMethod = MethodMember.from(methodElement, listOfIntType); | |
11433 indexExpression.staticElement = indexMethod; | |
11434 // list[0] should be in a setter context | |
11435 AstFactory.assignmentExpression( | |
11436 indexExpression, TokenType.EQ, AstFactory.integer(0)); | |
11437 // analyze and assert result of the index expression | |
11438 expect(_analyze(indexExpression), same(intType)); | |
11439 _listener.assertNoErrors(); | |
11440 } | |
11441 | |
11442 void test_visitInstanceCreationExpression_named() { | |
11443 // new C.m() | |
11444 ClassElementImpl classElement = ElementFactory.classElement2("C"); | |
11445 String constructorName = "m"; | |
11446 ConstructorElementImpl constructor = | |
11447 ElementFactory.constructorElement2(classElement, constructorName); | |
11448 constructor.returnType = classElement.type; | |
11449 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); | |
11450 constructor.type = constructorType; | |
11451 classElement.constructors = <ConstructorElement>[constructor]; | |
11452 InstanceCreationExpression node = AstFactory.instanceCreationExpression2( | |
11453 null, | |
11454 AstFactory.typeName(classElement), | |
11455 [AstFactory.identifier3(constructorName)]); | |
11456 node.staticElement = constructor; | |
11457 expect(_analyze(node), same(classElement.type)); | |
11458 _listener.assertNoErrors(); | |
11459 } | |
11460 | |
11461 void test_visitInstanceCreationExpression_typeParameters() { | |
11462 // new C<I>() | |
11463 ClassElementImpl elementC = ElementFactory.classElement2("C", ["E"]); | |
11464 ClassElementImpl elementI = ElementFactory.classElement2("I"); | |
11465 ConstructorElementImpl constructor = | |
11466 ElementFactory.constructorElement2(elementC, null); | |
11467 elementC.constructors = <ConstructorElement>[constructor]; | |
11468 constructor.returnType = elementC.type; | |
11469 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); | |
11470 constructor.type = constructorType; | |
11471 TypeName typeName = | |
11472 AstFactory.typeName(elementC, [AstFactory.typeName(elementI)]); | |
11473 typeName.type = elementC.type.instantiate(<DartType>[elementI.type]); | |
11474 InstanceCreationExpression node = | |
11475 AstFactory.instanceCreationExpression2(null, typeName); | |
11476 node.staticElement = constructor; | |
11477 InterfaceType interfaceType = _analyze(node) as InterfaceType; | |
11478 List<DartType> typeArgs = interfaceType.typeArguments; | |
11479 expect(typeArgs.length, 1); | |
11480 expect(typeArgs[0], elementI.type); | |
11481 _listener.assertNoErrors(); | |
11482 } | |
11483 | |
11484 void test_visitInstanceCreationExpression_unnamed() { | |
11485 // new C() | |
11486 ClassElementImpl classElement = ElementFactory.classElement2("C"); | |
11487 ConstructorElementImpl constructor = | |
11488 ElementFactory.constructorElement2(classElement, null); | |
11489 constructor.returnType = classElement.type; | |
11490 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); | |
11491 constructor.type = constructorType; | |
11492 classElement.constructors = <ConstructorElement>[constructor]; | |
11493 InstanceCreationExpression node = AstFactory.instanceCreationExpression2( | |
11494 null, AstFactory.typeName(classElement)); | |
11495 node.staticElement = constructor; | |
11496 expect(_analyze(node), same(classElement.type)); | |
11497 _listener.assertNoErrors(); | |
11498 } | |
11499 | |
11500 void test_visitIntegerLiteral() { | |
11501 // 42 | |
11502 Expression node = _resolvedInteger(42); | |
11503 expect(_analyze(node), same(_typeProvider.intType)); | |
11504 _listener.assertNoErrors(); | |
11505 } | |
11506 | |
11507 void test_visitIsExpression_negated() { | |
11508 // a is! String | |
11509 Expression node = AstFactory.isExpression( | |
11510 _resolvedString("a"), true, AstFactory.typeName4("String")); | |
11511 expect(_analyze(node), same(_typeProvider.boolType)); | |
11512 _listener.assertNoErrors(); | |
11513 } | |
11514 | |
11515 void test_visitIsExpression_notNegated() { | |
11516 // a is String | |
11517 Expression node = AstFactory.isExpression( | |
11518 _resolvedString("a"), false, AstFactory.typeName4("String")); | |
11519 expect(_analyze(node), same(_typeProvider.boolType)); | |
11520 _listener.assertNoErrors(); | |
11521 } | |
11522 | |
11523 void test_visitListLiteral_empty() { | |
11524 // [] | |
11525 Expression node = AstFactory.listLiteral(); | |
11526 DartType resultType = _analyze(node); | |
11527 _assertType2( | |
11528 _typeProvider.listType | |
11529 .instantiate(<DartType>[_typeProvider.dynamicType]), | |
11530 resultType); | |
11531 _listener.assertNoErrors(); | |
11532 } | |
11533 | |
11534 void test_visitListLiteral_nonEmpty() { | |
11535 // [0] | |
11536 Expression node = AstFactory.listLiteral([_resolvedInteger(0)]); | |
11537 DartType resultType = _analyze(node); | |
11538 _assertType2( | |
11539 _typeProvider.listType | |
11540 .instantiate(<DartType>[_typeProvider.dynamicType]), | |
11541 resultType); | |
11542 _listener.assertNoErrors(); | |
11543 } | |
11544 | |
11545 void test_visitMapLiteral_empty() { | |
11546 // {} | |
11547 Expression node = AstFactory.mapLiteral2(); | |
11548 DartType resultType = _analyze(node); | |
11549 _assertType2( | |
11550 _typeProvider.mapType.instantiate( | |
11551 <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]), | |
11552 resultType); | |
11553 _listener.assertNoErrors(); | |
11554 } | |
11555 | |
11556 void test_visitMapLiteral_nonEmpty() { | |
11557 // {"k" : 0} | |
11558 Expression node = AstFactory | |
11559 .mapLiteral2([AstFactory.mapLiteralEntry("k", _resolvedInteger(0))]); | |
11560 DartType resultType = _analyze(node); | |
11561 _assertType2( | |
11562 _typeProvider.mapType.instantiate( | |
11563 <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]), | |
11564 resultType); | |
11565 _listener.assertNoErrors(); | |
11566 } | |
11567 | |
11568 void test_visitMethodInvocation_then() { | |
11569 // then() | |
11570 Expression node = AstFactory.methodInvocation(null, "then"); | |
11571 _analyze(node); | |
11572 _listener.assertNoErrors(); | |
11573 } | |
11574 | |
11575 void test_visitNamedExpression() { | |
11576 // n: a | |
11577 Expression node = AstFactory.namedExpression2("n", _resolvedString("a")); | |
11578 expect(_analyze(node), same(_typeProvider.stringType)); | |
11579 _listener.assertNoErrors(); | |
11580 } | |
11581 | |
11582 void test_visitNullLiteral() { | |
11583 // null | |
11584 Expression node = AstFactory.nullLiteral(); | |
11585 expect(_analyze(node), same(_typeProvider.bottomType)); | |
11586 _listener.assertNoErrors(); | |
11587 } | |
11588 | |
11589 void test_visitParenthesizedExpression() { | |
11590 // (0) | |
11591 Expression node = AstFactory.parenthesizedExpression(_resolvedInteger(0)); | |
11592 expect(_analyze(node), same(_typeProvider.intType)); | |
11593 _listener.assertNoErrors(); | |
11594 } | |
11595 | |
11596 void test_visitPostfixExpression_minusMinus() { | |
11597 // 0-- | |
11598 PostfixExpression node = AstFactory.postfixExpression( | |
11599 _resolvedInteger(0), TokenType.MINUS_MINUS); | |
11600 expect(_analyze(node), same(_typeProvider.intType)); | |
11601 _listener.assertNoErrors(); | |
11602 } | |
11603 | |
11604 void test_visitPostfixExpression_plusPlus() { | |
11605 // 0++ | |
11606 PostfixExpression node = | |
11607 AstFactory.postfixExpression(_resolvedInteger(0), TokenType.PLUS_PLUS); | |
11608 expect(_analyze(node), same(_typeProvider.intType)); | |
11609 _listener.assertNoErrors(); | |
11610 } | |
11611 | |
11612 void test_visitPrefixedIdentifier_getter() { | |
11613 DartType boolType = _typeProvider.boolType; | |
11614 PropertyAccessorElementImpl getter = | |
11615 ElementFactory.getterElement("b", false, boolType); | |
11616 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); | |
11617 node.identifier.staticElement = getter; | |
11618 expect(_analyze(node), same(boolType)); | |
11619 _listener.assertNoErrors(); | |
11620 } | |
11621 | |
11622 void test_visitPrefixedIdentifier_setter() { | |
11623 DartType boolType = _typeProvider.boolType; | |
11624 FieldElementImpl field = | |
11625 ElementFactory.fieldElement("b", false, false, false, boolType); | |
11626 PropertyAccessorElement setter = field.setter; | |
11627 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); | |
11628 node.identifier.staticElement = setter; | |
11629 expect(_analyze(node), same(boolType)); | |
11630 _listener.assertNoErrors(); | |
11631 } | |
11632 | |
11633 void test_visitPrefixedIdentifier_variable() { | |
11634 VariableElementImpl variable = ElementFactory.localVariableElement2("b"); | |
11635 variable.type = _typeProvider.boolType; | |
11636 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); | |
11637 node.identifier.staticElement = variable; | |
11638 expect(_analyze(node), same(_typeProvider.boolType)); | |
11639 _listener.assertNoErrors(); | |
11640 } | |
11641 | |
11642 void test_visitPrefixExpression_bang() { | |
11643 // !0 | |
11644 PrefixExpression node = | |
11645 AstFactory.prefixExpression(TokenType.BANG, _resolvedInteger(0)); | |
11646 expect(_analyze(node), same(_typeProvider.boolType)); | |
11647 _listener.assertNoErrors(); | |
11648 } | |
11649 | |
11650 void test_visitPrefixExpression_minus() { | |
11651 // -0 | |
11652 PrefixExpression node = | |
11653 AstFactory.prefixExpression(TokenType.MINUS, _resolvedInteger(0)); | |
11654 MethodElement minusMethod = getMethod(_typeProvider.numType, "-"); | |
11655 node.staticElement = minusMethod; | |
11656 expect(_analyze(node), same(_typeProvider.numType)); | |
11657 _listener.assertNoErrors(); | |
11658 } | |
11659 | |
11660 void test_visitPrefixExpression_minusMinus() { | |
11661 // --0 | |
11662 PrefixExpression node = | |
11663 AstFactory.prefixExpression(TokenType.MINUS_MINUS, _resolvedInteger(0)); | |
11664 MethodElement minusMethod = getMethod(_typeProvider.numType, "-"); | |
11665 node.staticElement = minusMethod; | |
11666 expect(_analyze(node), same(_typeProvider.intType)); | |
11667 _listener.assertNoErrors(); | |
11668 } | |
11669 | |
11670 void test_visitPrefixExpression_not() { | |
11671 // !true | |
11672 Expression node = AstFactory.prefixExpression( | |
11673 TokenType.BANG, AstFactory.booleanLiteral(true)); | |
11674 expect(_analyze(node), same(_typeProvider.boolType)); | |
11675 _listener.assertNoErrors(); | |
11676 } | |
11677 | |
11678 void test_visitPrefixExpression_plusPlus() { | |
11679 // ++0 | |
11680 PrefixExpression node = | |
11681 AstFactory.prefixExpression(TokenType.PLUS_PLUS, _resolvedInteger(0)); | |
11682 MethodElement plusMethod = getMethod(_typeProvider.numType, "+"); | |
11683 node.staticElement = plusMethod; | |
11684 expect(_analyze(node), same(_typeProvider.intType)); | |
11685 _listener.assertNoErrors(); | |
11686 } | |
11687 | |
11688 void test_visitPrefixExpression_tilde() { | |
11689 // ~0 | |
11690 PrefixExpression node = | |
11691 AstFactory.prefixExpression(TokenType.TILDE, _resolvedInteger(0)); | |
11692 MethodElement tildeMethod = getMethod(_typeProvider.intType, "~"); | |
11693 node.staticElement = tildeMethod; | |
11694 expect(_analyze(node), same(_typeProvider.intType)); | |
11695 _listener.assertNoErrors(); | |
11696 } | |
11697 | |
11698 void test_visitPropertyAccess_propagated_getter() { | |
11699 DartType boolType = _typeProvider.boolType; | |
11700 PropertyAccessorElementImpl getter = | |
11701 ElementFactory.getterElement("b", false, boolType); | |
11702 PropertyAccess node = | |
11703 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); | |
11704 node.propertyName.propagatedElement = getter; | |
11705 expect(_analyze2(node, false), same(boolType)); | |
11706 _listener.assertNoErrors(); | |
11707 } | |
11708 | |
11709 void test_visitPropertyAccess_propagated_setter() { | |
11710 DartType boolType = _typeProvider.boolType; | |
11711 FieldElementImpl field = | |
11712 ElementFactory.fieldElement("b", false, false, false, boolType); | |
11713 PropertyAccessorElement setter = field.setter; | |
11714 PropertyAccess node = | |
11715 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); | |
11716 node.propertyName.propagatedElement = setter; | |
11717 expect(_analyze2(node, false), same(boolType)); | |
11718 _listener.assertNoErrors(); | |
11719 } | |
11720 | |
11721 void test_visitPropertyAccess_static_getter() { | |
11722 DartType boolType = _typeProvider.boolType; | |
11723 PropertyAccessorElementImpl getter = | |
11724 ElementFactory.getterElement("b", false, boolType); | |
11725 PropertyAccess node = | |
11726 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); | |
11727 node.propertyName.staticElement = getter; | |
11728 expect(_analyze(node), same(boolType)); | |
11729 _listener.assertNoErrors(); | |
11730 } | |
11731 | |
11732 void test_visitPropertyAccess_static_setter() { | |
11733 DartType boolType = _typeProvider.boolType; | |
11734 FieldElementImpl field = | |
11735 ElementFactory.fieldElement("b", false, false, false, boolType); | |
11736 PropertyAccessorElement setter = field.setter; | |
11737 PropertyAccess node = | |
11738 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); | |
11739 node.propertyName.staticElement = setter; | |
11740 expect(_analyze(node), same(boolType)); | |
11741 _listener.assertNoErrors(); | |
11742 } | |
11743 | |
11744 void test_visitSimpleIdentifier_dynamic() { | |
11745 // "dynamic" | |
11746 SimpleIdentifier identifier = AstFactory.identifier3('dynamic'); | |
11747 DynamicElementImpl element = DynamicElementImpl.instance; | |
11748 identifier.staticElement = element; | |
11749 identifier.staticType = _typeProvider.typeType; | |
11750 expect(_analyze(identifier), same(_typeProvider.typeType)); | |
11751 _listener.assertNoErrors(); | |
11752 } | |
11753 | |
11754 void test_visitSimpleStringLiteral() { | |
11755 // "a" | |
11756 Expression node = _resolvedString("a"); | |
11757 expect(_analyze(node), same(_typeProvider.stringType)); | |
11758 _listener.assertNoErrors(); | |
11759 } | |
11760 | |
11761 void test_visitStringInterpolation() { | |
11762 // "a${'b'}c" | |
11763 Expression node = AstFactory.string([ | |
11764 AstFactory.interpolationString("a", "a"), | |
11765 AstFactory.interpolationExpression(_resolvedString("b")), | |
11766 AstFactory.interpolationString("c", "c") | |
11767 ]); | |
11768 expect(_analyze(node), same(_typeProvider.stringType)); | |
11769 _listener.assertNoErrors(); | |
11770 } | |
11771 | |
11772 void test_visitSuperExpression() { | |
11773 // super | |
11774 InterfaceType superType = ElementFactory.classElement2("A").type; | |
11775 InterfaceType thisType = ElementFactory.classElement("B", superType).type; | |
11776 Expression node = AstFactory.superExpression(); | |
11777 expect(_analyze3(node, thisType), same(thisType)); | |
11778 _listener.assertNoErrors(); | |
11779 } | |
11780 | |
11781 void test_visitSymbolLiteral() { | |
11782 expect(_analyze(AstFactory.symbolLiteral(["a"])), | |
11783 same(_typeProvider.symbolType)); | |
11784 } | |
11785 | |
11786 void test_visitThisExpression() { | |
11787 // this | |
11788 InterfaceType thisType = ElementFactory | |
11789 .classElement("B", ElementFactory.classElement2("A").type) | |
11790 .type; | |
11791 Expression node = AstFactory.thisExpression(); | |
11792 expect(_analyze3(node, thisType), same(thisType)); | |
11793 _listener.assertNoErrors(); | |
11794 } | |
11795 | |
11796 void test_visitThrowExpression_withoutValue() { | |
11797 // throw | |
11798 Expression node = AstFactory.throwExpression(); | |
11799 expect(_analyze(node), same(_typeProvider.bottomType)); | |
11800 _listener.assertNoErrors(); | |
11801 } | |
11802 | |
11803 void test_visitThrowExpression_withValue() { | |
11804 // throw 0 | |
11805 Expression node = AstFactory.throwExpression2(_resolvedInteger(0)); | |
11806 expect(_analyze(node), same(_typeProvider.bottomType)); | |
11807 _listener.assertNoErrors(); | |
11808 } | |
11809 | |
11810 /** | |
11811 * Return the type associated with the given expression after the static type
analyzer has | |
11812 * computed a type for it. | |
11813 * | |
11814 * @param node the expression with which the type is associated | |
11815 * @return the type associated with the expression | |
11816 */ | |
11817 DartType _analyze(Expression node) => _analyze4(node, null, true); | |
11818 | |
11819 /** | |
11820 * Return the type associated with the given expression after the static or pr
opagated type | |
11821 * analyzer has computed a type for it. | |
11822 * | |
11823 * @param node the expression with which the type is associated | |
11824 * @param useStaticType `true` if the static type is being requested, and `fal
se` if | |
11825 * the propagated type is being requested | |
11826 * @return the type associated with the expression | |
11827 */ | |
11828 DartType _analyze2(Expression node, bool useStaticType) => | |
11829 _analyze4(node, null, useStaticType); | |
11830 | |
11831 /** | |
11832 * Return the type associated with the given expression after the static type
analyzer has | |
11833 * computed a type for it. | |
11834 * | |
11835 * @param node the expression with which the type is associated | |
11836 * @param thisType the type of 'this' | |
11837 * @return the type associated with the expression | |
11838 */ | |
11839 DartType _analyze3(Expression node, InterfaceType thisType) => | |
11840 _analyze4(node, thisType, true); | |
11841 | |
11842 /** | |
11843 * Return the type associated with the given expression after the static type
analyzer has | |
11844 * computed a type for it. | |
11845 * | |
11846 * @param node the expression with which the type is associated | |
11847 * @param thisType the type of 'this' | |
11848 * @param useStaticType `true` if the static type is being requested, and `fal
se` if | |
11849 * the propagated type is being requested | |
11850 * @return the type associated with the expression | |
11851 */ | |
11852 DartType _analyze4( | |
11853 Expression node, InterfaceType thisType, bool useStaticType) { | |
11854 try { | |
11855 _analyzer.thisType = thisType; | |
11856 } catch (exception) { | |
11857 throw new IllegalArgumentException( | |
11858 "Could not set type of 'this'", exception); | |
11859 } | |
11860 node.accept(_analyzer); | |
11861 if (useStaticType) { | |
11862 return node.staticType; | |
11863 } else { | |
11864 return node.propagatedType; | |
11865 } | |
11866 } | |
11867 | |
11868 /** | |
11869 * Return the type associated with the given parameter after the static type a
nalyzer has computed | |
11870 * a type for it. | |
11871 * | |
11872 * @param node the parameter with which the type is associated | |
11873 * @return the type associated with the parameter | |
11874 */ | |
11875 DartType _analyze5(FormalParameter node) { | |
11876 node.accept(_analyzer); | |
11877 return (node.identifier.staticElement as ParameterElement).type; | |
11878 } | |
11879 | |
11880 /** | |
11881 * Assert that the actual type is a function type with the expected characteri
stics. | |
11882 * | |
11883 * @param expectedReturnType the expected return type of the function | |
11884 * @param expectedNormalTypes the expected types of the normal parameters | |
11885 * @param expectedOptionalTypes the expected types of the optional parameters | |
11886 * @param expectedNamedTypes the expected types of the named parameters | |
11887 * @param actualType the type being tested | |
11888 */ | |
11889 void _assertFunctionType( | |
11890 DartType expectedReturnType, | |
11891 List<DartType> expectedNormalTypes, | |
11892 List<DartType> expectedOptionalTypes, | |
11893 Map<String, DartType> expectedNamedTypes, | |
11894 DartType actualType) { | |
11895 EngineTestCase.assertInstanceOf( | |
11896 (obj) => obj is FunctionType, FunctionType, actualType); | |
11897 FunctionType functionType = actualType as FunctionType; | |
11898 List<DartType> normalTypes = functionType.normalParameterTypes; | |
11899 if (expectedNormalTypes == null) { | |
11900 expect(normalTypes, hasLength(0)); | |
11901 } else { | |
11902 int expectedCount = expectedNormalTypes.length; | |
11903 expect(normalTypes, hasLength(expectedCount)); | |
11904 for (int i = 0; i < expectedCount; i++) { | |
11905 expect(normalTypes[i], same(expectedNormalTypes[i])); | |
11906 } | |
11907 } | |
11908 List<DartType> optionalTypes = functionType.optionalParameterTypes; | |
11909 if (expectedOptionalTypes == null) { | |
11910 expect(optionalTypes, hasLength(0)); | |
11911 } else { | |
11912 int expectedCount = expectedOptionalTypes.length; | |
11913 expect(optionalTypes, hasLength(expectedCount)); | |
11914 for (int i = 0; i < expectedCount; i++) { | |
11915 expect(optionalTypes[i], same(expectedOptionalTypes[i])); | |
11916 } | |
11917 } | |
11918 Map<String, DartType> namedTypes = functionType.namedParameterTypes; | |
11919 if (expectedNamedTypes == null) { | |
11920 expect(namedTypes, hasLength(0)); | |
11921 } else { | |
11922 expect(namedTypes, hasLength(expectedNamedTypes.length)); | |
11923 expectedNamedTypes.forEach((String name, DartType type) { | |
11924 expect(namedTypes[name], same(type)); | |
11925 }); | |
11926 } | |
11927 expect(functionType.returnType, equals(expectedReturnType)); | |
11928 } | |
11929 | |
11930 void _assertType( | |
11931 InterfaceTypeImpl expectedType, InterfaceTypeImpl actualType) { | |
11932 expect(actualType.displayName, expectedType.displayName); | |
11933 expect(actualType.element, expectedType.element); | |
11934 List<DartType> expectedArguments = expectedType.typeArguments; | |
11935 int length = expectedArguments.length; | |
11936 List<DartType> actualArguments = actualType.typeArguments; | |
11937 expect(actualArguments, hasLength(length)); | |
11938 for (int i = 0; i < length; i++) { | |
11939 _assertType2(expectedArguments[i], actualArguments[i]); | |
11940 } | |
11941 } | |
11942 | |
11943 void _assertType2(DartType expectedType, DartType actualType) { | |
11944 if (expectedType is InterfaceTypeImpl) { | |
11945 EngineTestCase.assertInstanceOf( | |
11946 (obj) => obj is InterfaceTypeImpl, InterfaceTypeImpl, actualType); | |
11947 _assertType(expectedType, actualType as InterfaceTypeImpl); | |
11948 } | |
11949 // TODO(brianwilkerson) Compare other kinds of types then make this a shared | |
11950 // utility method. | |
11951 } | |
11952 | |
11953 /** | |
11954 * Create the analyzer used by the tests. | |
11955 * | |
11956 * @return the analyzer to be used by the tests | |
11957 */ | |
11958 StaticTypeAnalyzer _createAnalyzer() { | |
11959 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); | |
11960 FileBasedSource source = | |
11961 new FileBasedSource(FileUtilities2.createFile("/lib.dart")); | |
11962 CompilationUnitElementImpl definingCompilationUnit = | |
11963 new CompilationUnitElementImpl("lib.dart"); | |
11964 definingCompilationUnit.librarySource = | |
11965 definingCompilationUnit.source = source; | |
11966 LibraryElementImpl definingLibrary = | |
11967 new LibraryElementImpl.forNode(context, null); | |
11968 definingLibrary.definingCompilationUnit = definingCompilationUnit; | |
11969 _typeProvider = new TestTypeProvider(context); | |
11970 _visitor = new ResolverVisitor( | |
11971 definingLibrary, source, _typeProvider, _listener, | |
11972 nameScope: new LibraryScope(definingLibrary, _listener)); | |
11973 _visitor.overrideManager.enterScope(); | |
11974 try { | |
11975 return _visitor.typeAnalyzer; | |
11976 } catch (exception) { | |
11977 throw new IllegalArgumentException( | |
11978 "Could not create analyzer", exception); | |
11979 } | |
11980 } | |
11981 | |
11982 DartType _flatten(DartType type) => type.flattenFutures(_typeSystem); | |
11983 | |
11984 /** | |
11985 * Return a simple identifier that has been resolved to a variable element wit
h the given type. | |
11986 * | |
11987 * @param type the type of the variable being represented | |
11988 * @param variableName the name of the variable | |
11989 * @return a simple identifier that has been resolved to a variable element wi
th the given type | |
11990 */ | |
11991 SimpleIdentifier _propagatedVariable( | |
11992 InterfaceType type, String variableName) { | |
11993 SimpleIdentifier identifier = AstFactory.identifier3(variableName); | |
11994 VariableElementImpl element = | |
11995 ElementFactory.localVariableElement(identifier); | |
11996 element.type = type; | |
11997 identifier.staticType = _typeProvider.dynamicType; | |
11998 identifier.propagatedElement = element; | |
11999 identifier.propagatedType = type; | |
12000 return identifier; | |
12001 } | |
12002 | |
12003 /** | |
12004 * Return an integer literal that has been resolved to the correct type. | |
12005 * | |
12006 * @param value the value of the literal | |
12007 * @return an integer literal that has been resolved to the correct type | |
12008 */ | |
12009 DoubleLiteral _resolvedDouble(double value) { | |
12010 DoubleLiteral literal = AstFactory.doubleLiteral(value); | |
12011 literal.staticType = _typeProvider.doubleType; | |
12012 return literal; | |
12013 } | |
12014 | |
12015 /** | |
12016 * Create a function expression that has an element associated with it, where
the element has an | |
12017 * incomplete type associated with it (just like the one | |
12018 * [ElementBuilder.visitFunctionExpression] would have built if we had | |
12019 * run it). | |
12020 * | |
12021 * @param parameters the parameters to the function | |
12022 * @param body the body of the function | |
12023 * @return a resolved function expression | |
12024 */ | |
12025 FunctionExpression _resolvedFunctionExpression( | |
12026 FormalParameterList parameters, FunctionBody body) { | |
12027 List<ParameterElement> parameterElements = new List<ParameterElement>(); | |
12028 for (FormalParameter parameter in parameters.parameters) { | |
12029 ParameterElementImpl element = | |
12030 new ParameterElementImpl.forNode(parameter.identifier); | |
12031 element.parameterKind = parameter.kind; | |
12032 element.type = _typeProvider.dynamicType; | |
12033 parameter.identifier.staticElement = element; | |
12034 parameterElements.add(element); | |
12035 } | |
12036 FunctionExpression node = AstFactory.functionExpression2(parameters, body); | |
12037 FunctionElementImpl element = new FunctionElementImpl.forNode(null); | |
12038 element.parameters = parameterElements; | |
12039 element.type = new FunctionTypeImpl(element); | |
12040 node.element = element; | |
12041 return node; | |
12042 } | |
12043 | |
12044 /** | |
12045 * Return an integer literal that has been resolved to the correct type. | |
12046 * | |
12047 * @param value the value of the literal | |
12048 * @return an integer literal that has been resolved to the correct type | |
12049 */ | |
12050 IntegerLiteral _resolvedInteger(int value) { | |
12051 IntegerLiteral literal = AstFactory.integer(value); | |
12052 literal.staticType = _typeProvider.intType; | |
12053 return literal; | |
12054 } | |
12055 | |
12056 /** | |
12057 * Return a string literal that has been resolved to the correct type. | |
12058 * | |
12059 * @param value the value of the literal | |
12060 * @return a string literal that has been resolved to the correct type | |
12061 */ | |
12062 SimpleStringLiteral _resolvedString(String value) { | |
12063 SimpleStringLiteral string = AstFactory.string2(value); | |
12064 string.staticType = _typeProvider.stringType; | |
12065 return string; | |
12066 } | |
12067 | |
12068 /** | |
12069 * Return a simple identifier that has been resolved to a variable element wit
h the given type. | |
12070 * | |
12071 * @param type the type of the variable being represented | |
12072 * @param variableName the name of the variable | |
12073 * @return a simple identifier that has been resolved to a variable element wi
th the given type | |
12074 */ | |
12075 SimpleIdentifier _resolvedVariable(InterfaceType type, String variableName) { | |
12076 SimpleIdentifier identifier = AstFactory.identifier3(variableName); | |
12077 VariableElementImpl element = | |
12078 ElementFactory.localVariableElement(identifier); | |
12079 element.type = type; | |
12080 identifier.staticElement = element; | |
12081 identifier.staticType = type; | |
12082 return identifier; | |
12083 } | |
12084 | |
12085 /** | |
12086 * Set the type of the given parameter to the given type. | |
12087 * | |
12088 * @param parameter the parameter whose type is to be set | |
12089 * @param type the new type of the given parameter | |
12090 */ | |
12091 void _setType(FormalParameter parameter, DartType type) { | |
12092 SimpleIdentifier identifier = parameter.identifier; | |
12093 Element element = identifier.staticElement; | |
12094 if (element is! ParameterElement) { | |
12095 element = new ParameterElementImpl.forNode(identifier); | |
12096 identifier.staticElement = element; | |
12097 } | |
12098 (element as ParameterElementImpl).type = type; | |
12099 } | |
12100 } | |
12101 | |
12102 /** | |
12103 * Instances of the class `StaticTypeVerifier` verify that all of the nodes in a
n AST | 677 * Instances of the class `StaticTypeVerifier` verify that all of the nodes in a
n AST |
12104 * structure that should have a static type associated with them do have a stati
c type. | 678 * structure that should have a static type associated with them do have a stati
c type. |
12105 */ | 679 */ |
12106 class StaticTypeVerifier extends GeneralizingAstVisitor<Object> { | 680 class StaticTypeVerifier extends GeneralizingAstVisitor<Object> { |
12107 /** | 681 /** |
12108 * A list containing all of the AST Expression nodes that were not resolved. | 682 * A list containing all of the AST Expression nodes that were not resolved. |
12109 */ | 683 */ |
12110 List<Expression> _unresolvedExpressions = new List<Expression>(); | 684 List<Expression> _unresolvedExpressions = new List<Expression>(); |
12111 | 685 |
12112 /** | 686 /** |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12458 Source source = addSource(r''' | 1032 Source source = addSource(r''' |
12459 int f() { | 1033 int f() { |
12460 num n = 1234; | 1034 num n = 1234; |
12461 return n & 0x0F; | 1035 return n & 0x0F; |
12462 }'''); | 1036 }'''); |
12463 computeLibrarySourceErrors(source); | 1037 computeLibrarySourceErrors(source); |
12464 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); | 1038 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
12465 } | 1039 } |
12466 } | 1040 } |
12467 | 1041 |
12468 /** | |
12469 * Strong mode static analyzer downwards inference tests | |
12470 */ | |
12471 @reflectiveTest | |
12472 class StrongModeDownwardsInferenceTest extends ResolverTestCase { | |
12473 TypeAssertions _assertions; | |
12474 | |
12475 Asserter<DartType> _isDynamic; | |
12476 Asserter<InterfaceType> _isFutureOfDynamic; | |
12477 Asserter<InterfaceType> _isFutureOfInt; | |
12478 Asserter<DartType> _isInt; | |
12479 Asserter<DartType> _isNum; | |
12480 Asserter<DartType> _isString; | |
12481 | |
12482 AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, DartType> | |
12483 _isFunction2Of; | |
12484 AsserterBuilder<List<Asserter<DartType>>, InterfaceType> _isFutureOf; | |
12485 AsserterBuilderBuilder<Asserter<DartType>, List<Asserter<DartType>>, DartType> | |
12486 _isInstantiationOf; | |
12487 AsserterBuilder<Asserter<DartType>, InterfaceType> _isListOf; | |
12488 AsserterBuilder2<Asserter<DartType>, Asserter<DartType>, InterfaceType> | |
12489 _isMapOf; | |
12490 AsserterBuilder<List<Asserter<DartType>>, InterfaceType> _isStreamOf; | |
12491 AsserterBuilder<DartType, DartType> _isType; | |
12492 | |
12493 AsserterBuilder<Element, DartType> _hasElement; | |
12494 AsserterBuilder<DartType, DartType> _sameElement; | |
12495 | |
12496 @override | |
12497 void setUp() { | |
12498 super.setUp(); | |
12499 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | |
12500 options.strongMode = true; | |
12501 resetWithOptions(options); | |
12502 _assertions = new TypeAssertions(typeProvider); | |
12503 _isType = _assertions.isType; | |
12504 _hasElement = _assertions.hasElement; | |
12505 _isInstantiationOf = _assertions.isInstantiationOf; | |
12506 _isInt = _assertions.isInt; | |
12507 _isNum = _assertions.isNum; | |
12508 _isString = _assertions.isString; | |
12509 _isDynamic = _assertions.isDynamic; | |
12510 _isListOf = _assertions.isListOf; | |
12511 _isMapOf = _assertions.isMapOf; | |
12512 _isFunction2Of = _assertions.isFunction2Of; | |
12513 _sameElement = _assertions.sameElement; | |
12514 _isFutureOf = _isInstantiationOf(_sameElement(typeProvider.futureType)); | |
12515 _isFutureOfDynamic = _isFutureOf([_isDynamic]); | |
12516 _isFutureOfInt = _isFutureOf([_isInt]); | |
12517 _isStreamOf = _isInstantiationOf(_sameElement(typeProvider.streamType)); | |
12518 } | |
12519 | |
12520 void test_async_method_propagation() { | |
12521 String code = r''' | |
12522 import "dart:async"; | |
12523 class A { | |
12524 Future f0() => new Future.value(3); | |
12525 Future f1() async => new Future.value(3); | |
12526 Future f2() async => await new Future.value(3); | |
12527 | |
12528 Future<int> f3() => new Future.value(3); | |
12529 Future<int> f4() async => new Future.value(3); | |
12530 Future<int> f5() async => await new Future.value(3); | |
12531 | |
12532 Future g0() { return new Future.value(3); } | |
12533 Future g1() async { return new Future.value(3); } | |
12534 Future g2() async { return await new Future.value(3); } | |
12535 | |
12536 Future<int> g3() { return new Future.value(3); } | |
12537 Future<int> g4() async { return new Future.value(3); } | |
12538 Future<int> g5() async { return await new Future.value(3); } | |
12539 } | |
12540 '''; | |
12541 CompilationUnit unit = resolveSource(code); | |
12542 | |
12543 void check(String name, Asserter<InterfaceType> typeTest) { | |
12544 MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name); | |
12545 FunctionBody body = test.body; | |
12546 Expression returnExp; | |
12547 if (body is ExpressionFunctionBody) { | |
12548 returnExp = body.expression; | |
12549 } else { | |
12550 ReturnStatement stmt = (body as BlockFunctionBody).block.statements[0]; | |
12551 returnExp = stmt.expression; | |
12552 } | |
12553 DartType type = returnExp.staticType; | |
12554 if (returnExp is AwaitExpression) { | |
12555 type = returnExp.expression.staticType; | |
12556 } | |
12557 typeTest(type); | |
12558 } | |
12559 | |
12560 check("f0", _isFutureOfDynamic); | |
12561 check("f1", _isFutureOfDynamic); | |
12562 check("f2", _isFutureOfDynamic); | |
12563 | |
12564 check("f3", _isFutureOfInt); | |
12565 // This should be int when we handle the implicit Future<T> | T union | |
12566 // https://github.com/dart-lang/sdk/issues/25322 | |
12567 check("f4", _isFutureOfDynamic); | |
12568 check("f5", _isFutureOfInt); | |
12569 | |
12570 check("g0", _isFutureOfDynamic); | |
12571 check("g1", _isFutureOfDynamic); | |
12572 check("g2", _isFutureOfDynamic); | |
12573 | |
12574 check("g3", _isFutureOfInt); | |
12575 // This should be int when we handle the implicit Future<T> | T union | |
12576 // https://github.com/dart-lang/sdk/issues/25322 | |
12577 check("g4", _isFutureOfDynamic); | |
12578 check("g5", _isFutureOfInt); | |
12579 } | |
12580 | |
12581 void test_async_propagation() { | |
12582 String code = r''' | |
12583 import "dart:async"; | |
12584 | |
12585 Future f0() => new Future.value(3); | |
12586 Future f1() async => new Future.value(3); | |
12587 Future f2() async => await new Future.value(3); | |
12588 | |
12589 Future<int> f3() => new Future.value(3); | |
12590 Future<int> f4() async => new Future.value(3); | |
12591 Future<int> f5() async => await new Future.value(3); | |
12592 | |
12593 Future g0() { return new Future.value(3); } | |
12594 Future g1() async { return new Future.value(3); } | |
12595 Future g2() async { return await new Future.value(3); } | |
12596 | |
12597 Future<int> g3() { return new Future.value(3); } | |
12598 Future<int> g4() async { return new Future.value(3); } | |
12599 Future<int> g5() async { return await new Future.value(3); } | |
12600 '''; | |
12601 CompilationUnit unit = resolveSource(code); | |
12602 | |
12603 void check(String name, Asserter<InterfaceType> typeTest) { | |
12604 FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name); | |
12605 FunctionBody body = test.functionExpression.body; | |
12606 Expression returnExp; | |
12607 if (body is ExpressionFunctionBody) { | |
12608 returnExp = body.expression; | |
12609 } else { | |
12610 ReturnStatement stmt = (body as BlockFunctionBody).block.statements[0]; | |
12611 returnExp = stmt.expression; | |
12612 } | |
12613 DartType type = returnExp.staticType; | |
12614 if (returnExp is AwaitExpression) { | |
12615 type = returnExp.expression.staticType; | |
12616 } | |
12617 typeTest(type); | |
12618 } | |
12619 | |
12620 check("f0", _isFutureOfDynamic); | |
12621 check("f1", _isFutureOfDynamic); | |
12622 check("f2", _isFutureOfDynamic); | |
12623 | |
12624 check("f3", _isFutureOfInt); | |
12625 // This should be int when we handle the implicit Future<T> | T union | |
12626 // https://github.com/dart-lang/sdk/issues/25322 | |
12627 check("f4", _isFutureOfDynamic); | |
12628 check("f5", _isFutureOfInt); | |
12629 | |
12630 check("g0", _isFutureOfDynamic); | |
12631 check("g1", _isFutureOfDynamic); | |
12632 check("g2", _isFutureOfDynamic); | |
12633 | |
12634 check("g3", _isFutureOfInt); | |
12635 // This should be int when we handle the implicit Future<T> | T union | |
12636 // https://github.com/dart-lang/sdk/issues/25322 | |
12637 check("g4", _isFutureOfDynamic); | |
12638 check("g5", _isFutureOfInt); | |
12639 } | |
12640 | |
12641 void test_async_star_method_propagation() { | |
12642 String code = r''' | |
12643 import "dart:async"; | |
12644 class A { | |
12645 Stream g0() async* { yield []; } | |
12646 Stream g1() async* { yield* new Stream(); } | |
12647 | |
12648 Stream<List<int>> g2() async* { yield []; } | |
12649 Stream<List<int>> g3() async* { yield* new Stream(); } | |
12650 } | |
12651 '''; | |
12652 CompilationUnit unit = resolveSource(code); | |
12653 | |
12654 void check(String name, Asserter<InterfaceType> typeTest) { | |
12655 MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name); | |
12656 BlockFunctionBody body = test.body; | |
12657 YieldStatement stmt = body.block.statements[0]; | |
12658 Expression exp = stmt.expression; | |
12659 typeTest(exp.staticType); | |
12660 } | |
12661 | |
12662 check("g0", _isListOf(_isDynamic)); | |
12663 check("g1", _isStreamOf([_isDynamic])); | |
12664 | |
12665 check("g2", _isListOf(_isInt)); | |
12666 check("g3", _isStreamOf([_isListOf(_isInt)])); | |
12667 } | |
12668 | |
12669 void test_async_star_propagation() { | |
12670 String code = r''' | |
12671 import "dart:async"; | |
12672 | |
12673 Stream g0() async* { yield []; } | |
12674 Stream g1() async* { yield* new Stream(); } | |
12675 | |
12676 Stream<List<int>> g2() async* { yield []; } | |
12677 Stream<List<int>> g3() async* { yield* new Stream(); } | |
12678 '''; | |
12679 CompilationUnit unit = resolveSource(code); | |
12680 | |
12681 void check(String name, Asserter<InterfaceType> typeTest) { | |
12682 FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name); | |
12683 BlockFunctionBody body = test.functionExpression.body; | |
12684 YieldStatement stmt = body.block.statements[0]; | |
12685 Expression exp = stmt.expression; | |
12686 typeTest(exp.staticType); | |
12687 } | |
12688 | |
12689 check("g0", _isListOf(_isDynamic)); | |
12690 check("g1", _isStreamOf([_isDynamic])); | |
12691 | |
12692 check("g2", _isListOf(_isInt)); | |
12693 check("g3", _isStreamOf([_isListOf(_isInt)])); | |
12694 } | |
12695 | |
12696 void test_cascadeExpression() { | |
12697 String code = r''' | |
12698 class A<T> { | |
12699 List<T> map(T a, List<T> mapper(T x)) => mapper(a); | |
12700 } | |
12701 | |
12702 void main () { | |
12703 A<int> a = new A()..map(0, (x) => [x]); | |
12704 } | |
12705 '''; | |
12706 CompilationUnit unit = resolveSource(code); | |
12707 List<Statement> statements = | |
12708 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
12709 CascadeExpression fetch(int i) { | |
12710 VariableDeclarationStatement stmt = statements[i]; | |
12711 VariableDeclaration decl = stmt.variables.variables[0]; | |
12712 CascadeExpression exp = decl.initializer; | |
12713 return exp; | |
12714 } | |
12715 Element elementA = AstFinder.getClass(unit, "A").element; | |
12716 | |
12717 CascadeExpression cascade = fetch(0); | |
12718 _isInstantiationOf(_hasElement(elementA))([_isInt])(cascade.staticType); | |
12719 MethodInvocation invoke = cascade.cascadeSections[0]; | |
12720 FunctionExpression function = invoke.argumentList.arguments[1]; | |
12721 ExecutableElement f0 = function.element; | |
12722 _isListOf(_isInt)(f0.type.returnType); | |
12723 expect(f0.type.normalParameterTypes[0], typeProvider.intType); | |
12724 } | |
12725 | |
12726 void test_constructorInitializer_propagation() { | |
12727 String code = r''' | |
12728 class A { | |
12729 List<String> x; | |
12730 A() : this.x = []; | |
12731 } | |
12732 '''; | |
12733 CompilationUnit unit = resolveSource(code); | |
12734 ConstructorDeclaration constructor = | |
12735 AstFinder.getConstructorInClass(unit, "A", null); | |
12736 ConstructorFieldInitializer assignment = constructor.initializers[0]; | |
12737 Expression exp = assignment.expression; | |
12738 _isListOf(_isString)(exp.staticType); | |
12739 } | |
12740 | |
12741 void test_factoryConstructor_propagation() { | |
12742 String code = r''' | |
12743 class A<T> { | |
12744 factory A() { return new B(); } | |
12745 } | |
12746 class B<S> extends A<S> {} | |
12747 '''; | |
12748 CompilationUnit unit = resolveSource(code); | |
12749 | |
12750 ConstructorDeclaration constructor = | |
12751 AstFinder.getConstructorInClass(unit, "A", null); | |
12752 BlockFunctionBody body = constructor.body; | |
12753 ReturnStatement stmt = body.block.statements[0]; | |
12754 InstanceCreationExpression exp = stmt.expression; | |
12755 ClassElement elementB = AstFinder.getClass(unit, "B").element; | |
12756 ClassElement elementA = AstFinder.getClass(unit, "A").element; | |
12757 expect(exp.constructorName.type.type.element, elementB); | |
12758 _isInstantiationOf(_hasElement(elementB))( | |
12759 [_isType(elementA.typeParameters[0].type)])(exp.staticType); | |
12760 } | |
12761 | |
12762 void test_fieldDeclaration_propagation() { | |
12763 String code = r''' | |
12764 class A { | |
12765 List<String> f0 = ["hello"]; | |
12766 } | |
12767 '''; | |
12768 CompilationUnit unit = resolveSource(code); | |
12769 | |
12770 VariableDeclaration field = AstFinder.getFieldInClass(unit, "A", "f0"); | |
12771 | |
12772 _isListOf(_isString)(field.initializer.staticType); | |
12773 } | |
12774 | |
12775 void test_functionDeclaration_body_propagation() { | |
12776 String code = r''' | |
12777 typedef T Function2<S, T>(S x); | |
12778 | |
12779 List<int> test1() => []; | |
12780 | |
12781 Function2<int, int> test2 (int x) { | |
12782 Function2<String, int> inner() { | |
12783 return (x) => x.length; | |
12784 } | |
12785 return (x) => x; | |
12786 } | |
12787 '''; | |
12788 CompilationUnit unit = resolveSource(code); | |
12789 | |
12790 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt); | |
12791 | |
12792 FunctionDeclaration test1 = AstFinder.getTopLevelFunction(unit, "test1"); | |
12793 ExpressionFunctionBody body = test1.functionExpression.body; | |
12794 assertListOfInt(body.expression.staticType); | |
12795 | |
12796 List<Statement> statements = | |
12797 AstFinder.getStatementsInTopLevelFunction(unit, "test2"); | |
12798 | |
12799 FunctionDeclaration inner = | |
12800 (statements[0] as FunctionDeclarationStatement).functionDeclaration; | |
12801 BlockFunctionBody body0 = inner.functionExpression.body; | |
12802 ReturnStatement return0 = body0.block.statements[0]; | |
12803 Expression anon0 = return0.expression; | |
12804 FunctionType type0 = anon0.staticType; | |
12805 expect(type0.returnType, typeProvider.intType); | |
12806 expect(type0.normalParameterTypes[0], typeProvider.stringType); | |
12807 | |
12808 FunctionExpression anon1 = (statements[1] as ReturnStatement).expression; | |
12809 FunctionType type1 = anon1.element.type; | |
12810 expect(type1.returnType, typeProvider.intType); | |
12811 expect(type1.normalParameterTypes[0], typeProvider.intType); | |
12812 } | |
12813 | |
12814 void test_functionLiteral_assignment_typedArguments() { | |
12815 String code = r''' | |
12816 typedef T Function2<S, T>(S x); | |
12817 | |
12818 void main () { | |
12819 Function2<int, String> l0 = (int x) => null; | |
12820 Function2<int, String> l1 = (int x) => "hello"; | |
12821 Function2<int, String> l2 = (String x) => "hello"; | |
12822 Function2<int, String> l3 = (int x) => 3; | |
12823 Function2<int, String> l4 = (int x) {return 3;}; | |
12824 } | |
12825 '''; | |
12826 CompilationUnit unit = resolveSource(code); | |
12827 List<Statement> statements = | |
12828 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
12829 DartType literal(int i) { | |
12830 VariableDeclarationStatement stmt = statements[i]; | |
12831 VariableDeclaration decl = stmt.variables.variables[0]; | |
12832 FunctionExpression exp = decl.initializer; | |
12833 return exp.element.type; | |
12834 } | |
12835 _isFunction2Of(_isInt, _isString)(literal(0)); | |
12836 _isFunction2Of(_isInt, _isString)(literal(1)); | |
12837 _isFunction2Of(_isString, _isString)(literal(2)); | |
12838 _isFunction2Of(_isInt, _isInt)(literal(3)); | |
12839 _isFunction2Of(_isInt, _isString)(literal(4)); | |
12840 } | |
12841 | |
12842 void test_functionLiteral_assignment_unTypedArguments() { | |
12843 String code = r''' | |
12844 typedef T Function2<S, T>(S x); | |
12845 | |
12846 void main () { | |
12847 Function2<int, String> l0 = (x) => null; | |
12848 Function2<int, String> l1 = (x) => "hello"; | |
12849 Function2<int, String> l2 = (x) => "hello"; | |
12850 Function2<int, String> l3 = (x) => 3; | |
12851 Function2<int, String> l4 = (x) {return 3;}; | |
12852 } | |
12853 '''; | |
12854 CompilationUnit unit = resolveSource(code); | |
12855 List<Statement> statements = | |
12856 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
12857 DartType literal(int i) { | |
12858 VariableDeclarationStatement stmt = statements[i]; | |
12859 VariableDeclaration decl = stmt.variables.variables[0]; | |
12860 FunctionExpression exp = decl.initializer; | |
12861 return exp.element.type; | |
12862 } | |
12863 _isFunction2Of(_isInt, _isString)(literal(0)); | |
12864 _isFunction2Of(_isInt, _isString)(literal(1)); | |
12865 _isFunction2Of(_isInt, _isString)(literal(2)); | |
12866 _isFunction2Of(_isInt, _isInt)(literal(3)); | |
12867 _isFunction2Of(_isInt, _isString)(literal(4)); | |
12868 } | |
12869 | |
12870 void test_functionLiteral_body_propagation() { | |
12871 String code = r''' | |
12872 typedef T Function2<S, T>(S x); | |
12873 | |
12874 void main () { | |
12875 Function2<int, List<String>> l0 = (int x) => ["hello"]; | |
12876 Function2<int, List<String>> l1 = (String x) => ["hello"]; | |
12877 Function2<int, List<String>> l2 = (int x) => [3]; | |
12878 Function2<int, List<String>> l3 = (int x) {return [3];}; | |
12879 } | |
12880 '''; | |
12881 CompilationUnit unit = resolveSource(code); | |
12882 List<Statement> statements = | |
12883 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
12884 Expression functionReturnValue(int i) { | |
12885 VariableDeclarationStatement stmt = statements[i]; | |
12886 VariableDeclaration decl = stmt.variables.variables[0]; | |
12887 FunctionExpression exp = decl.initializer; | |
12888 FunctionBody body = exp.body; | |
12889 if (body is ExpressionFunctionBody) { | |
12890 return body.expression; | |
12891 } else { | |
12892 Statement stmt = (body as BlockFunctionBody).block.statements[0]; | |
12893 return (stmt as ReturnStatement).expression; | |
12894 } | |
12895 } | |
12896 Asserter<InterfaceType> assertListOfString = _isListOf(_isString); | |
12897 assertListOfString(functionReturnValue(0).staticType); | |
12898 assertListOfString(functionReturnValue(1).staticType); | |
12899 assertListOfString(functionReturnValue(2).staticType); | |
12900 assertListOfString(functionReturnValue(3).staticType); | |
12901 } | |
12902 | |
12903 void test_functionLiteral_functionExpressionInvocation_typedArguments() { | |
12904 String code = r''' | |
12905 class Mapper<F, T> { | |
12906 T map(T mapper(F x)) => mapper(null); | |
12907 } | |
12908 | |
12909 void main () { | |
12910 (new Mapper<int, String>().map)((int x) => null); | |
12911 (new Mapper<int, String>().map)((int x) => "hello"); | |
12912 (new Mapper<int, String>().map)((String x) => "hello"); | |
12913 (new Mapper<int, String>().map)((int x) => 3); | |
12914 (new Mapper<int, String>().map)((int x) {return 3;}); | |
12915 } | |
12916 '''; | |
12917 CompilationUnit unit = resolveSource(code); | |
12918 List<Statement> statements = | |
12919 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
12920 DartType literal(int i) { | |
12921 ExpressionStatement stmt = statements[i]; | |
12922 FunctionExpressionInvocation invk = stmt.expression; | |
12923 FunctionExpression exp = invk.argumentList.arguments[0]; | |
12924 return exp.element.type; | |
12925 } | |
12926 _isFunction2Of(_isInt, _isString)(literal(0)); | |
12927 _isFunction2Of(_isInt, _isString)(literal(1)); | |
12928 _isFunction2Of(_isString, _isString)(literal(2)); | |
12929 _isFunction2Of(_isInt, _isInt)(literal(3)); | |
12930 _isFunction2Of(_isInt, _isString)(literal(4)); | |
12931 } | |
12932 | |
12933 void test_functionLiteral_functionExpressionInvocation_unTypedArguments() { | |
12934 String code = r''' | |
12935 class Mapper<F, T> { | |
12936 T map(T mapper(F x)) => mapper(null); | |
12937 } | |
12938 | |
12939 void main () { | |
12940 (new Mapper<int, String>().map)((x) => null); | |
12941 (new Mapper<int, String>().map)((x) => "hello"); | |
12942 (new Mapper<int, String>().map)((x) => "hello"); | |
12943 (new Mapper<int, String>().map)((x) => 3); | |
12944 (new Mapper<int, String>().map)((x) {return 3;}); | |
12945 } | |
12946 '''; | |
12947 CompilationUnit unit = resolveSource(code); | |
12948 List<Statement> statements = | |
12949 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
12950 DartType literal(int i) { | |
12951 ExpressionStatement stmt = statements[i]; | |
12952 FunctionExpressionInvocation invk = stmt.expression; | |
12953 FunctionExpression exp = invk.argumentList.arguments[0]; | |
12954 return exp.element.type; | |
12955 } | |
12956 _isFunction2Of(_isInt, _isString)(literal(0)); | |
12957 _isFunction2Of(_isInt, _isString)(literal(1)); | |
12958 _isFunction2Of(_isInt, _isString)(literal(2)); | |
12959 _isFunction2Of(_isInt, _isInt)(literal(3)); | |
12960 _isFunction2Of(_isInt, _isString)(literal(4)); | |
12961 } | |
12962 | |
12963 void test_functionLiteral_functionInvocation_typedArguments() { | |
12964 String code = r''' | |
12965 String map(String mapper(int x)) => mapper(null); | |
12966 | |
12967 void main () { | |
12968 map((int x) => null); | |
12969 map((int x) => "hello"); | |
12970 map((String x) => "hello"); | |
12971 map((int x) => 3); | |
12972 map((int x) {return 3;}); | |
12973 } | |
12974 '''; | |
12975 CompilationUnit unit = resolveSource(code); | |
12976 List<Statement> statements = | |
12977 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
12978 DartType literal(int i) { | |
12979 ExpressionStatement stmt = statements[i]; | |
12980 MethodInvocation invk = stmt.expression; | |
12981 FunctionExpression exp = invk.argumentList.arguments[0]; | |
12982 return exp.element.type; | |
12983 } | |
12984 _isFunction2Of(_isInt, _isString)(literal(0)); | |
12985 _isFunction2Of(_isInt, _isString)(literal(1)); | |
12986 _isFunction2Of(_isString, _isString)(literal(2)); | |
12987 _isFunction2Of(_isInt, _isInt)(literal(3)); | |
12988 _isFunction2Of(_isInt, _isString)(literal(4)); | |
12989 } | |
12990 | |
12991 void test_functionLiteral_functionInvocation_unTypedArguments() { | |
12992 String code = r''' | |
12993 String map(String mapper(int x)) => mapper(null); | |
12994 | |
12995 void main () { | |
12996 map((x) => null); | |
12997 map((x) => "hello"); | |
12998 map((x) => "hello"); | |
12999 map((x) => 3); | |
13000 map((x) {return 3;}); | |
13001 } | |
13002 '''; | |
13003 CompilationUnit unit = resolveSource(code); | |
13004 List<Statement> statements = | |
13005 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13006 DartType literal(int i) { | |
13007 ExpressionStatement stmt = statements[i]; | |
13008 MethodInvocation invk = stmt.expression; | |
13009 FunctionExpression exp = invk.argumentList.arguments[0]; | |
13010 return exp.element.type; | |
13011 } | |
13012 _isFunction2Of(_isInt, _isString)(literal(0)); | |
13013 _isFunction2Of(_isInt, _isString)(literal(1)); | |
13014 _isFunction2Of(_isInt, _isString)(literal(2)); | |
13015 _isFunction2Of(_isInt, _isInt)(literal(3)); | |
13016 _isFunction2Of(_isInt, _isString)(literal(4)); | |
13017 } | |
13018 | |
13019 void test_functionLiteral_methodInvocation_typedArguments() { | |
13020 String code = r''' | |
13021 class Mapper<F, T> { | |
13022 T map(T mapper(F x)) => mapper(null); | |
13023 } | |
13024 | |
13025 void main () { | |
13026 new Mapper<int, String>().map((int x) => null); | |
13027 new Mapper<int, String>().map((int x) => "hello"); | |
13028 new Mapper<int, String>().map((String x) => "hello"); | |
13029 new Mapper<int, String>().map((int x) => 3); | |
13030 new Mapper<int, String>().map((int x) {return 3;}); | |
13031 } | |
13032 '''; | |
13033 CompilationUnit unit = resolveSource(code); | |
13034 List<Statement> statements = | |
13035 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13036 DartType literal(int i) { | |
13037 ExpressionStatement stmt = statements[i]; | |
13038 MethodInvocation invk = stmt.expression; | |
13039 FunctionExpression exp = invk.argumentList.arguments[0]; | |
13040 return exp.element.type; | |
13041 } | |
13042 _isFunction2Of(_isInt, _isString)(literal(0)); | |
13043 _isFunction2Of(_isInt, _isString)(literal(1)); | |
13044 _isFunction2Of(_isString, _isString)(literal(2)); | |
13045 _isFunction2Of(_isInt, _isInt)(literal(3)); | |
13046 _isFunction2Of(_isInt, _isString)(literal(4)); | |
13047 } | |
13048 | |
13049 void test_functionLiteral_methodInvocation_unTypedArguments() { | |
13050 String code = r''' | |
13051 class Mapper<F, T> { | |
13052 T map(T mapper(F x)) => mapper(null); | |
13053 } | |
13054 | |
13055 void main () { | |
13056 new Mapper<int, String>().map((x) => null); | |
13057 new Mapper<int, String>().map((x) => "hello"); | |
13058 new Mapper<int, String>().map((x) => "hello"); | |
13059 new Mapper<int, String>().map((x) => 3); | |
13060 new Mapper<int, String>().map((x) {return 3;}); | |
13061 } | |
13062 '''; | |
13063 CompilationUnit unit = resolveSource(code); | |
13064 List<Statement> statements = | |
13065 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13066 DartType literal(int i) { | |
13067 ExpressionStatement stmt = statements[i]; | |
13068 MethodInvocation invk = stmt.expression; | |
13069 FunctionExpression exp = invk.argumentList.arguments[0]; | |
13070 return exp.element.type; | |
13071 } | |
13072 _isFunction2Of(_isInt, _isString)(literal(0)); | |
13073 _isFunction2Of(_isInt, _isString)(literal(1)); | |
13074 _isFunction2Of(_isInt, _isString)(literal(2)); | |
13075 _isFunction2Of(_isInt, _isInt)(literal(3)); | |
13076 _isFunction2Of(_isInt, _isString)(literal(4)); | |
13077 } | |
13078 | |
13079 void test_functionLiteral_unTypedArgument_propagation() { | |
13080 String code = r''' | |
13081 typedef T Function2<S, T>(S x); | |
13082 | |
13083 void main () { | |
13084 Function2<int, int> l0 = (x) => x; | |
13085 Function2<int, int> l1 = (x) => x+1; | |
13086 Function2<int, String> l2 = (x) => x; | |
13087 Function2<int, String> l3 = (x) => x.toLowerCase(); | |
13088 Function2<String, String> l4 = (x) => x.toLowerCase(); | |
13089 } | |
13090 '''; | |
13091 CompilationUnit unit = resolveSource(code); | |
13092 List<Statement> statements = | |
13093 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13094 Expression functionReturnValue(int i) { | |
13095 VariableDeclarationStatement stmt = statements[i]; | |
13096 VariableDeclaration decl = stmt.variables.variables[0]; | |
13097 FunctionExpression exp = decl.initializer; | |
13098 FunctionBody body = exp.body; | |
13099 if (body is ExpressionFunctionBody) { | |
13100 return body.expression; | |
13101 } else { | |
13102 Statement stmt = (body as BlockFunctionBody).block.statements[0]; | |
13103 return (stmt as ReturnStatement).expression; | |
13104 } | |
13105 } | |
13106 expect(functionReturnValue(0).staticType, typeProvider.intType); | |
13107 expect(functionReturnValue(1).staticType, typeProvider.intType); | |
13108 expect(functionReturnValue(2).staticType, typeProvider.intType); | |
13109 expect(functionReturnValue(3).staticType, typeProvider.dynamicType); | |
13110 expect(functionReturnValue(4).staticType, typeProvider.stringType); | |
13111 } | |
13112 | |
13113 void test_inference_hints() { | |
13114 Source source = addSource(r''' | |
13115 void main () { | |
13116 var x = 3; | |
13117 List<int> l0 = []; | |
13118 } | |
13119 '''); | |
13120 resolve2(source); | |
13121 assertNoErrors(source); | |
13122 verify([source]); | |
13123 } | |
13124 | |
13125 void test_instanceCreation() { | |
13126 String code = r''' | |
13127 class A<S, T> { | |
13128 S x; | |
13129 T y; | |
13130 A(this.x, this.y); | |
13131 A.named(this.x, this.y); | |
13132 } | |
13133 | |
13134 class B<S, T> extends A<T, S> { | |
13135 B(S y, T x) : super(x, y); | |
13136 B.named(S y, T x) : super.named(x, y); | |
13137 } | |
13138 | |
13139 class C<S> extends B<S, S> { | |
13140 C(S a) : super(a, a); | |
13141 C.named(S a) : super.named(a, a); | |
13142 } | |
13143 | |
13144 class D<S, T> extends B<T, int> { | |
13145 D(T a) : super(a, 3); | |
13146 D.named(T a) : super.named(a, 3); | |
13147 } | |
13148 | |
13149 class E<S, T> extends A<C<S>, T> { | |
13150 E(T a) : super(null, a); | |
13151 } | |
13152 | |
13153 class F<S, T> extends A<S, T> { | |
13154 F(S x, T y, {List<S> a, List<T> b}) : super(x, y); | |
13155 F.named(S x, T y, [S a, T b]) : super(a, b); | |
13156 } | |
13157 | |
13158 void test0() { | |
13159 A<int, String> a0 = new A(3, "hello"); | |
13160 A<int, String> a1 = new A.named(3, "hello"); | |
13161 A<int, String> a2 = new A<int, String>(3, "hello"); | |
13162 A<int, String> a3 = new A<int, String>.named(3, "hello"); | |
13163 A<int, String> a4 = new A<int, dynamic>(3, "hello"); | |
13164 A<int, String> a5 = new A<dynamic, dynamic>.named(3, "hello"); | |
13165 } | |
13166 void test1() { | |
13167 A<int, String> a0 = new A("hello", 3); | |
13168 A<int, String> a1 = new A.named("hello", 3); | |
13169 } | |
13170 void test2() { | |
13171 A<int, String> a0 = new B("hello", 3); | |
13172 A<int, String> a1 = new B.named("hello", 3); | |
13173 A<int, String> a2 = new B<String, int>("hello", 3); | |
13174 A<int, String> a3 = new B<String, int>.named("hello", 3); | |
13175 A<int, String> a4 = new B<String, dynamic>("hello", 3); | |
13176 A<int, String> a5 = new B<dynamic, dynamic>.named("hello", 3); | |
13177 } | |
13178 void test3() { | |
13179 A<int, String> a0 = new B(3, "hello"); | |
13180 A<int, String> a1 = new B.named(3, "hello"); | |
13181 } | |
13182 void test4() { | |
13183 A<int, int> a0 = new C(3); | |
13184 A<int, int> a1 = new C.named(3); | |
13185 A<int, int> a2 = new C<int>(3); | |
13186 A<int, int> a3 = new C<int>.named(3); | |
13187 A<int, int> a4 = new C<dynamic>(3); | |
13188 A<int, int> a5 = new C<dynamic>.named(3); | |
13189 } | |
13190 void test5() { | |
13191 A<int, int> a0 = new C("hello"); | |
13192 A<int, int> a1 = new C.named("hello"); | |
13193 } | |
13194 void test6() { | |
13195 A<int, String> a0 = new D("hello"); | |
13196 A<int, String> a1 = new D.named("hello"); | |
13197 A<int, String> a2 = new D<int, String>("hello"); | |
13198 A<int, String> a3 = new D<String, String>.named("hello"); | |
13199 A<int, String> a4 = new D<num, dynamic>("hello"); | |
13200 A<int, String> a5 = new D<dynamic, dynamic>.named("hello"); | |
13201 } | |
13202 void test7() { | |
13203 A<int, String> a0 = new D(3); | |
13204 A<int, String> a1 = new D.named(3); | |
13205 } | |
13206 void test8() { | |
13207 // Currently we only allow variable constraints. Test that we reject. | |
13208 A<C<int>, String> a0 = new E("hello"); | |
13209 } | |
13210 void test9() { // Check named and optional arguments | |
13211 A<int, String> a0 = new F(3, "hello", a: [3], b: ["hello"]); | |
13212 A<int, String> a1 = new F(3, "hello", a: ["hello"], b:[3]); | |
13213 A<int, String> a2 = new F.named(3, "hello", 3, "hello"); | |
13214 A<int, String> a3 = new F.named(3, "hello"); | |
13215 A<int, String> a4 = new F.named(3, "hello", "hello", 3); | |
13216 A<int, String> a5 = new F.named(3, "hello", "hello"); | |
13217 } | |
13218 }'''; | |
13219 CompilationUnit unit = resolveSource(code); | |
13220 | |
13221 Expression rhs(VariableDeclarationStatement stmt) { | |
13222 VariableDeclaration decl = stmt.variables.variables[0]; | |
13223 Expression exp = decl.initializer; | |
13224 return exp; | |
13225 } | |
13226 | |
13227 void hasType(Asserter<DartType> assertion, Expression exp) => | |
13228 assertion(exp.staticType); | |
13229 | |
13230 Element elementA = AstFinder.getClass(unit, "A").element; | |
13231 Element elementB = AstFinder.getClass(unit, "B").element; | |
13232 Element elementC = AstFinder.getClass(unit, "C").element; | |
13233 Element elementD = AstFinder.getClass(unit, "D").element; | |
13234 Element elementE = AstFinder.getClass(unit, "E").element; | |
13235 Element elementF = AstFinder.getClass(unit, "F").element; | |
13236 | |
13237 AsserterBuilder<List<Asserter<DartType>>, DartType> assertAOf = | |
13238 _isInstantiationOf(_hasElement(elementA)); | |
13239 AsserterBuilder<List<Asserter<DartType>>, DartType> assertBOf = | |
13240 _isInstantiationOf(_hasElement(elementB)); | |
13241 AsserterBuilder<List<Asserter<DartType>>, DartType> assertCOf = | |
13242 _isInstantiationOf(_hasElement(elementC)); | |
13243 AsserterBuilder<List<Asserter<DartType>>, DartType> assertDOf = | |
13244 _isInstantiationOf(_hasElement(elementD)); | |
13245 AsserterBuilder<List<Asserter<DartType>>, DartType> assertEOf = | |
13246 _isInstantiationOf(_hasElement(elementE)); | |
13247 AsserterBuilder<List<Asserter<DartType>>, DartType> assertFOf = | |
13248 _isInstantiationOf(_hasElement(elementF)); | |
13249 | |
13250 { | |
13251 List<Statement> statements = | |
13252 AstFinder.getStatementsInTopLevelFunction(unit, "test0"); | |
13253 | |
13254 hasType(assertAOf([_isInt, _isString]), rhs(statements[0])); | |
13255 hasType(assertAOf([_isInt, _isString]), rhs(statements[0])); | |
13256 hasType(assertAOf([_isInt, _isString]), rhs(statements[1])); | |
13257 hasType(assertAOf([_isInt, _isString]), rhs(statements[2])); | |
13258 hasType(assertAOf([_isInt, _isString]), rhs(statements[3])); | |
13259 hasType(assertAOf([_isInt, _isDynamic]), rhs(statements[4])); | |
13260 hasType(assertAOf([_isDynamic, _isDynamic]), rhs(statements[5])); | |
13261 } | |
13262 | |
13263 { | |
13264 List<Statement> statements = | |
13265 AstFinder.getStatementsInTopLevelFunction(unit, "test1"); | |
13266 hasType(assertAOf([_isInt, _isString]), rhs(statements[0])); | |
13267 hasType(assertAOf([_isInt, _isString]), rhs(statements[1])); | |
13268 } | |
13269 | |
13270 { | |
13271 List<Statement> statements = | |
13272 AstFinder.getStatementsInTopLevelFunction(unit, "test2"); | |
13273 hasType(assertBOf([_isString, _isInt]), rhs(statements[0])); | |
13274 hasType(assertBOf([_isString, _isInt]), rhs(statements[1])); | |
13275 hasType(assertBOf([_isString, _isInt]), rhs(statements[2])); | |
13276 hasType(assertBOf([_isString, _isInt]), rhs(statements[3])); | |
13277 hasType(assertBOf([_isString, _isDynamic]), rhs(statements[4])); | |
13278 hasType(assertBOf([_isDynamic, _isDynamic]), rhs(statements[5])); | |
13279 } | |
13280 | |
13281 { | |
13282 List<Statement> statements = | |
13283 AstFinder.getStatementsInTopLevelFunction(unit, "test3"); | |
13284 hasType(assertBOf([_isString, _isInt]), rhs(statements[0])); | |
13285 hasType(assertBOf([_isString, _isInt]), rhs(statements[1])); | |
13286 } | |
13287 | |
13288 { | |
13289 List<Statement> statements = | |
13290 AstFinder.getStatementsInTopLevelFunction(unit, "test4"); | |
13291 hasType(assertCOf([_isInt]), rhs(statements[0])); | |
13292 hasType(assertCOf([_isInt]), rhs(statements[1])); | |
13293 hasType(assertCOf([_isInt]), rhs(statements[2])); | |
13294 hasType(assertCOf([_isInt]), rhs(statements[3])); | |
13295 hasType(assertCOf([_isDynamic]), rhs(statements[4])); | |
13296 hasType(assertCOf([_isDynamic]), rhs(statements[5])); | |
13297 } | |
13298 | |
13299 { | |
13300 List<Statement> statements = | |
13301 AstFinder.getStatementsInTopLevelFunction(unit, "test5"); | |
13302 hasType(assertCOf([_isInt]), rhs(statements[0])); | |
13303 hasType(assertCOf([_isInt]), rhs(statements[1])); | |
13304 } | |
13305 | |
13306 { | |
13307 // The first type parameter is not constrained by the | |
13308 // context. We could choose a tighter type, but currently | |
13309 // we just use dynamic. | |
13310 List<Statement> statements = | |
13311 AstFinder.getStatementsInTopLevelFunction(unit, "test6"); | |
13312 hasType(assertDOf([_isDynamic, _isString]), rhs(statements[0])); | |
13313 hasType(assertDOf([_isDynamic, _isString]), rhs(statements[1])); | |
13314 hasType(assertDOf([_isInt, _isString]), rhs(statements[2])); | |
13315 hasType(assertDOf([_isString, _isString]), rhs(statements[3])); | |
13316 hasType(assertDOf([_isNum, _isDynamic]), rhs(statements[4])); | |
13317 hasType(assertDOf([_isDynamic, _isDynamic]), rhs(statements[5])); | |
13318 } | |
13319 | |
13320 { | |
13321 List<Statement> statements = | |
13322 AstFinder.getStatementsInTopLevelFunction(unit, "test7"); | |
13323 hasType(assertDOf([_isDynamic, _isString]), rhs(statements[0])); | |
13324 hasType(assertDOf([_isDynamic, _isString]), rhs(statements[1])); | |
13325 } | |
13326 | |
13327 { | |
13328 List<Statement> statements = | |
13329 AstFinder.getStatementsInTopLevelFunction(unit, "test8"); | |
13330 hasType(assertEOf([_isDynamic, _isDynamic]), rhs(statements[0])); | |
13331 } | |
13332 | |
13333 { | |
13334 List<Statement> statements = | |
13335 AstFinder.getStatementsInTopLevelFunction(unit, "test9"); | |
13336 hasType(assertFOf([_isInt, _isString]), rhs(statements[0])); | |
13337 hasType(assertFOf([_isInt, _isString]), rhs(statements[1])); | |
13338 hasType(assertFOf([_isInt, _isString]), rhs(statements[2])); | |
13339 hasType(assertFOf([_isInt, _isString]), rhs(statements[3])); | |
13340 hasType(assertFOf([_isInt, _isString]), rhs(statements[4])); | |
13341 hasType(assertFOf([_isInt, _isString]), rhs(statements[5])); | |
13342 } | |
13343 } | |
13344 | |
13345 void test_listLiteral_nested() { | |
13346 String code = r''' | |
13347 void main () { | |
13348 List<List<int>> l0 = [[]]; | |
13349 Iterable<List<int>> l1 = [[3]]; | |
13350 Iterable<List<int>> l2 = [[3], [4]]; | |
13351 List<List<int>> l3 = [["hello", 3], []]; | |
13352 } | |
13353 '''; | |
13354 CompilationUnit unit = resolveSource(code); | |
13355 List<Statement> statements = | |
13356 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13357 ListLiteral literal(int i) { | |
13358 VariableDeclarationStatement stmt = statements[i]; | |
13359 VariableDeclaration decl = stmt.variables.variables[0]; | |
13360 ListLiteral exp = decl.initializer; | |
13361 return exp; | |
13362 } | |
13363 | |
13364 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt); | |
13365 Asserter<InterfaceType> assertListOfListOfInt = _isListOf(assertListOfInt); | |
13366 | |
13367 assertListOfListOfInt(literal(0).staticType); | |
13368 assertListOfListOfInt(literal(1).staticType); | |
13369 assertListOfListOfInt(literal(2).staticType); | |
13370 assertListOfListOfInt(literal(3).staticType); | |
13371 | |
13372 assertListOfInt(literal(1).elements[0].staticType); | |
13373 assertListOfInt(literal(2).elements[0].staticType); | |
13374 assertListOfInt(literal(3).elements[0].staticType); | |
13375 } | |
13376 | |
13377 void test_listLiteral_simple() { | |
13378 String code = r''' | |
13379 void main () { | |
13380 List<int> l0 = []; | |
13381 List<int> l1 = [3]; | |
13382 List<int> l2 = ["hello"]; | |
13383 List<int> l3 = ["hello", 3]; | |
13384 } | |
13385 '''; | |
13386 CompilationUnit unit = resolveSource(code); | |
13387 List<Statement> statements = | |
13388 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13389 DartType literal(int i) { | |
13390 VariableDeclarationStatement stmt = statements[i]; | |
13391 VariableDeclaration decl = stmt.variables.variables[0]; | |
13392 ListLiteral exp = decl.initializer; | |
13393 return exp.staticType; | |
13394 } | |
13395 | |
13396 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt); | |
13397 | |
13398 assertListOfInt(literal(0)); | |
13399 assertListOfInt(literal(1)); | |
13400 assertListOfInt(literal(2)); | |
13401 assertListOfInt(literal(3)); | |
13402 } | |
13403 | |
13404 void test_listLiteral_simple_const() { | |
13405 String code = r''' | |
13406 void main () { | |
13407 const List<int> c0 = const []; | |
13408 const List<int> c1 = const [3]; | |
13409 const List<int> c2 = const ["hello"]; | |
13410 const List<int> c3 = const ["hello", 3]; | |
13411 } | |
13412 '''; | |
13413 CompilationUnit unit = resolveSource(code); | |
13414 List<Statement> statements = | |
13415 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13416 DartType literal(int i) { | |
13417 VariableDeclarationStatement stmt = statements[i]; | |
13418 VariableDeclaration decl = stmt.variables.variables[0]; | |
13419 ListLiteral exp = decl.initializer; | |
13420 return exp.staticType; | |
13421 } | |
13422 | |
13423 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt); | |
13424 | |
13425 assertListOfInt(literal(0)); | |
13426 assertListOfInt(literal(1)); | |
13427 assertListOfInt(literal(2)); | |
13428 assertListOfInt(literal(3)); | |
13429 } | |
13430 | |
13431 void test_listLiteral_simple_disabled() { | |
13432 String code = r''' | |
13433 void main () { | |
13434 List<int> l0 = <num>[]; | |
13435 List<int> l1 = <num>[3]; | |
13436 List<int> l2 = <String>["hello"]; | |
13437 List<int> l3 = <dynamic>["hello", 3]; | |
13438 } | |
13439 '''; | |
13440 CompilationUnit unit = resolveSource(code); | |
13441 List<Statement> statements = | |
13442 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13443 DartType literal(int i) { | |
13444 VariableDeclarationStatement stmt = statements[i]; | |
13445 VariableDeclaration decl = stmt.variables.variables[0]; | |
13446 ListLiteral exp = decl.initializer; | |
13447 return exp.staticType; | |
13448 } | |
13449 | |
13450 _isListOf(_isNum)(literal(0)); | |
13451 _isListOf(_isNum)(literal(1)); | |
13452 _isListOf(_isString)(literal(2)); | |
13453 _isListOf(_isDynamic)(literal(3)); | |
13454 } | |
13455 | |
13456 void test_listLiteral_simple_subtype() { | |
13457 String code = r''' | |
13458 void main () { | |
13459 Iterable<int> l0 = []; | |
13460 Iterable<int> l1 = [3]; | |
13461 Iterable<int> l2 = ["hello"]; | |
13462 Iterable<int> l3 = ["hello", 3]; | |
13463 } | |
13464 '''; | |
13465 CompilationUnit unit = resolveSource(code); | |
13466 List<Statement> statements = | |
13467 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13468 DartType literal(int i) { | |
13469 VariableDeclarationStatement stmt = statements[i]; | |
13470 VariableDeclaration decl = stmt.variables.variables[0]; | |
13471 ListLiteral exp = decl.initializer; | |
13472 return exp.staticType; | |
13473 } | |
13474 | |
13475 Asserter<InterfaceType> assertListOfInt = _isListOf(_isInt); | |
13476 | |
13477 assertListOfInt(literal(0)); | |
13478 assertListOfInt(literal(1)); | |
13479 assertListOfInt(literal(2)); | |
13480 assertListOfInt(literal(3)); | |
13481 } | |
13482 | |
13483 void test_mapLiteral_nested() { | |
13484 String code = r''' | |
13485 void main () { | |
13486 Map<int, List<String>> l0 = {}; | |
13487 Map<int, List<String>> l1 = {3: ["hello"]}; | |
13488 Map<int, List<String>> l2 = {"hello": ["hello"]}; | |
13489 Map<int, List<String>> l3 = {3: [3]}; | |
13490 Map<int, List<String>> l4 = {3:["hello"], "hello": [3]}; | |
13491 } | |
13492 '''; | |
13493 CompilationUnit unit = resolveSource(code); | |
13494 List<Statement> statements = | |
13495 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13496 MapLiteral literal(int i) { | |
13497 VariableDeclarationStatement stmt = statements[i]; | |
13498 VariableDeclaration decl = stmt.variables.variables[0]; | |
13499 MapLiteral exp = decl.initializer; | |
13500 return exp; | |
13501 } | |
13502 | |
13503 Asserter<InterfaceType> assertListOfString = _isListOf(_isString); | |
13504 Asserter<InterfaceType> assertMapOfIntToListOfString = | |
13505 _isMapOf(_isInt, assertListOfString); | |
13506 | |
13507 assertMapOfIntToListOfString(literal(0).staticType); | |
13508 assertMapOfIntToListOfString(literal(1).staticType); | |
13509 assertMapOfIntToListOfString(literal(2).staticType); | |
13510 assertMapOfIntToListOfString(literal(3).staticType); | |
13511 assertMapOfIntToListOfString(literal(4).staticType); | |
13512 | |
13513 assertListOfString(literal(1).entries[0].value.staticType); | |
13514 assertListOfString(literal(2).entries[0].value.staticType); | |
13515 assertListOfString(literal(3).entries[0].value.staticType); | |
13516 assertListOfString(literal(4).entries[0].value.staticType); | |
13517 } | |
13518 | |
13519 void test_mapLiteral_simple() { | |
13520 String code = r''' | |
13521 void main () { | |
13522 Map<int, String> l0 = {}; | |
13523 Map<int, String> l1 = {3: "hello"}; | |
13524 Map<int, String> l2 = {"hello": "hello"}; | |
13525 Map<int, String> l3 = {3: 3}; | |
13526 Map<int, String> l4 = {3:"hello", "hello": 3}; | |
13527 } | |
13528 '''; | |
13529 CompilationUnit unit = resolveSource(code); | |
13530 List<Statement> statements = | |
13531 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13532 DartType literal(int i) { | |
13533 VariableDeclarationStatement stmt = statements[i]; | |
13534 VariableDeclaration decl = stmt.variables.variables[0]; | |
13535 MapLiteral exp = decl.initializer; | |
13536 return exp.staticType; | |
13537 } | |
13538 | |
13539 Asserter<InterfaceType> assertMapOfIntToString = | |
13540 _isMapOf(_isInt, _isString); | |
13541 | |
13542 assertMapOfIntToString(literal(0)); | |
13543 assertMapOfIntToString(literal(1)); | |
13544 assertMapOfIntToString(literal(2)); | |
13545 assertMapOfIntToString(literal(3)); | |
13546 } | |
13547 | |
13548 void test_mapLiteral_simple_disabled() { | |
13549 String code = r''' | |
13550 void main () { | |
13551 Map<int, String> l0 = <int, dynamic>{}; | |
13552 Map<int, String> l1 = <int, dynamic>{3: "hello"}; | |
13553 Map<int, String> l2 = <int, dynamic>{"hello": "hello"}; | |
13554 Map<int, String> l3 = <int, dynamic>{3: 3}; | |
13555 } | |
13556 '''; | |
13557 CompilationUnit unit = resolveSource(code); | |
13558 List<Statement> statements = | |
13559 AstFinder.getStatementsInTopLevelFunction(unit, "main"); | |
13560 DartType literal(int i) { | |
13561 VariableDeclarationStatement stmt = statements[i]; | |
13562 VariableDeclaration decl = stmt.variables.variables[0]; | |
13563 MapLiteral exp = decl.initializer; | |
13564 return exp.staticType; | |
13565 } | |
13566 | |
13567 Asserter<InterfaceType> assertMapOfIntToDynamic = | |
13568 _isMapOf(_isInt, _isDynamic); | |
13569 | |
13570 assertMapOfIntToDynamic(literal(0)); | |
13571 assertMapOfIntToDynamic(literal(1)); | |
13572 assertMapOfIntToDynamic(literal(2)); | |
13573 assertMapOfIntToDynamic(literal(3)); | |
13574 } | |
13575 | |
13576 void test_methodDeclaration_body_propagation() { | |
13577 String code = r''' | |
13578 class A { | |
13579 List<String> m0(int x) => ["hello"]; | |
13580 List<String> m1(int x) {return [3];}; | |
13581 } | |
13582 '''; | |
13583 CompilationUnit unit = resolveSource(code); | |
13584 Expression methodReturnValue(String methodName) { | |
13585 MethodDeclaration method = | |
13586 AstFinder.getMethodInClass(unit, "A", methodName); | |
13587 FunctionBody body = method.body; | |
13588 if (body is ExpressionFunctionBody) { | |
13589 return body.expression; | |
13590 } else { | |
13591 Statement stmt = (body as BlockFunctionBody).block.statements[0]; | |
13592 return (stmt as ReturnStatement).expression; | |
13593 } | |
13594 } | |
13595 Asserter<InterfaceType> assertListOfString = _isListOf(_isString); | |
13596 assertListOfString(methodReturnValue("m0").staticType); | |
13597 assertListOfString(methodReturnValue("m1").staticType); | |
13598 } | |
13599 | |
13600 void test_redirectingConstructor_propagation() { | |
13601 String code = r''' | |
13602 class A { | |
13603 A() : this.named([]); | |
13604 A.named(List<String> x); | |
13605 } | |
13606 '''; | |
13607 CompilationUnit unit = resolveSource(code); | |
13608 | |
13609 ConstructorDeclaration constructor = | |
13610 AstFinder.getConstructorInClass(unit, "A", null); | |
13611 RedirectingConstructorInvocation invocation = constructor.initializers[0]; | |
13612 Expression exp = invocation.argumentList.arguments[0]; | |
13613 _isListOf(_isString)(exp.staticType); | |
13614 } | |
13615 | |
13616 void test_superConstructorInvocation_propagation() { | |
13617 String code = r''' | |
13618 class B { | |
13619 B(List<String>); | |
13620 } | |
13621 class A extends B { | |
13622 A() : super([]); | |
13623 } | |
13624 '''; | |
13625 CompilationUnit unit = resolveSource(code); | |
13626 | |
13627 ConstructorDeclaration constructor = | |
13628 AstFinder.getConstructorInClass(unit, "A", null); | |
13629 SuperConstructorInvocation invocation = constructor.initializers[0]; | |
13630 Expression exp = invocation.argumentList.arguments[0]; | |
13631 _isListOf(_isString)(exp.staticType); | |
13632 } | |
13633 | |
13634 void test_sync_star_method_propagation() { | |
13635 String code = r''' | |
13636 import "dart:async"; | |
13637 class A { | |
13638 Iterable f0() sync* { yield []; } | |
13639 Iterable f1() sync* { yield* new List(); } | |
13640 | |
13641 Iterable<List<int>> f2() sync* { yield []; } | |
13642 Iterable<List<int>> f3() sync* { yield* new List(); } | |
13643 } | |
13644 '''; | |
13645 CompilationUnit unit = resolveSource(code); | |
13646 | |
13647 void check(String name, Asserter<InterfaceType> typeTest) { | |
13648 MethodDeclaration test = AstFinder.getMethodInClass(unit, "A", name); | |
13649 BlockFunctionBody body = test.body; | |
13650 YieldStatement stmt = body.block.statements[0]; | |
13651 Expression exp = stmt.expression; | |
13652 typeTest(exp.staticType); | |
13653 } | |
13654 | |
13655 check("f0", _isListOf(_isDynamic)); | |
13656 check("f1", _isListOf(_isDynamic)); | |
13657 | |
13658 check("f2", _isListOf(_isInt)); | |
13659 check("f3", _isListOf(_isListOf(_isInt))); | |
13660 } | |
13661 | |
13662 void test_sync_star_propagation() { | |
13663 String code = r''' | |
13664 import "dart:async"; | |
13665 | |
13666 Iterable f0() sync* { yield []; } | |
13667 Iterable f1() sync* { yield* new List(); } | |
13668 | |
13669 Iterable<List<int>> f2() sync* { yield []; } | |
13670 Iterable<List<int>> f3() sync* { yield* new List(); } | |
13671 '''; | |
13672 CompilationUnit unit = resolveSource(code); | |
13673 | |
13674 void check(String name, Asserter<InterfaceType> typeTest) { | |
13675 FunctionDeclaration test = AstFinder.getTopLevelFunction(unit, name); | |
13676 BlockFunctionBody body = test.functionExpression.body; | |
13677 YieldStatement stmt = body.block.statements[0]; | |
13678 Expression exp = stmt.expression; | |
13679 typeTest(exp.staticType); | |
13680 } | |
13681 | |
13682 check("f0", _isListOf(_isDynamic)); | |
13683 check("f1", _isListOf(_isDynamic)); | |
13684 | |
13685 check("f2", _isListOf(_isInt)); | |
13686 check("f3", _isListOf(_isListOf(_isInt))); | |
13687 } | |
13688 } | |
13689 | |
13690 /** | |
13691 * Strong mode static analyzer end to end tests | |
13692 */ | |
13693 @reflectiveTest | |
13694 class StrongModeStaticTypeAnalyzer2Test extends _StaticTypeAnalyzer2TestShared { | |
13695 void fail_genericMethod_tearoff_instantiated() { | |
13696 _resolveTestUnit(r''' | |
13697 class C<E> { | |
13698 /*=T*/ f/*<T>*/(E e) => null; | |
13699 static /*=T*/ g/*<T>*/(/*=T*/ e) => null; | |
13700 static final h = g; | |
13701 } | |
13702 | |
13703 /*=T*/ topF/*<T>*/(/*=T*/ e) => null; | |
13704 var topG = topF; | |
13705 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) { | |
13706 var c = new C<int>(); | |
13707 /*=T*/ lf/*<T>*/(/*=T*/ e) => null; | |
13708 var methodTearOffInst = c.f/*<int>*/; | |
13709 var staticTearOffInst = C.g/*<int>*/; | |
13710 var staticFieldTearOffInst = C.h/*<int>*/; | |
13711 var topFunTearOffInst = topF/*<int>*/; | |
13712 var topFieldTearOffInst = topG/*<int>*/; | |
13713 var localTearOffInst = lf/*<int>*/; | |
13714 var paramTearOffInst = pf/*<int>*/; | |
13715 } | |
13716 '''); | |
13717 _expectIdentifierType('methodTearOffInst', "(int) → int"); | |
13718 _expectIdentifierType('staticTearOffInst', "(int) → int"); | |
13719 _expectIdentifierType('staticFieldTearOffInst', "(int) → int"); | |
13720 _expectIdentifierType('topFunTearOffInst', "(int) → int"); | |
13721 _expectIdentifierType('topFieldTearOffInst', "(int) → int"); | |
13722 _expectIdentifierType('localTearOffInst', "(int) → int"); | |
13723 _expectIdentifierType('paramTearOffInst', "(int) → int"); | |
13724 } | |
13725 | |
13726 void setUp() { | |
13727 super.setUp(); | |
13728 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | |
13729 options.strongMode = true; | |
13730 resetWithOptions(options); | |
13731 } | |
13732 | |
13733 void test_dynamicObjectGetter_hashCode() { | |
13734 String code = r''' | |
13735 main() { | |
13736 dynamic a = null; | |
13737 var foo = a.hashCode; | |
13738 } | |
13739 '''; | |
13740 _resolveTestUnit(code); | |
13741 _expectInitializerType('foo', 'int', isNull); | |
13742 } | |
13743 | |
13744 void test_dynamicObjectMethod_toString() { | |
13745 String code = r''' | |
13746 main() { | |
13747 dynamic a = null; | |
13748 var foo = a.toString(); | |
13749 } | |
13750 '''; | |
13751 _resolveTestUnit(code); | |
13752 _expectInitializerType('foo', 'String', isNull); | |
13753 } | |
13754 | |
13755 void test_genericFunction() { | |
13756 _resolveTestUnit(r'/*=T*/ f/*<T>*/(/*=T*/ x) => null;'); | |
13757 _expectFunctionType('f', '<T>(T) → T', | |
13758 elementTypeParams: '[T]', typeFormals: '[T]'); | |
13759 SimpleIdentifier f = _findIdentifier('f'); | |
13760 FunctionElementImpl e = f.staticElement; | |
13761 FunctionType ft = e.type.instantiate([typeProvider.stringType]); | |
13762 expect(ft.toString(), '(String) → String'); | |
13763 } | |
13764 | |
13765 void test_genericFunction_bounds() { | |
13766 _resolveTestUnit(r'/*=T*/ f/*<T extends num>*/(/*=T*/ x) => null;'); | |
13767 _expectFunctionType('f', '<T extends num>(T) → T', | |
13768 elementTypeParams: '[T extends num]', typeFormals: '[T extends num]'); | |
13769 } | |
13770 | |
13771 void test_genericFunction_parameter() { | |
13772 _resolveTestUnit(r''' | |
13773 void g(/*=T*/ f/*<T>*/(/*=T*/ x)) {} | |
13774 '''); | |
13775 _expectFunctionType('f', '<T>(T) → T', | |
13776 elementTypeParams: '[T]', typeFormals: '[T]'); | |
13777 SimpleIdentifier f = _findIdentifier('f'); | |
13778 ParameterElementImpl e = f.staticElement; | |
13779 FunctionType type = e.type; | |
13780 FunctionType ft = type.instantiate([typeProvider.stringType]); | |
13781 expect(ft.toString(), '(String) → String'); | |
13782 } | |
13783 | |
13784 void test_genericFunction_static() { | |
13785 _resolveTestUnit(r''' | |
13786 class C<E> { | |
13787 static /*=T*/ f/*<T>*/(/*=T*/ x) => null; | |
13788 } | |
13789 '''); | |
13790 _expectFunctionType('f', '<T>(T) → T', | |
13791 elementTypeParams: '[T]', typeFormals: '[T]'); | |
13792 SimpleIdentifier f = _findIdentifier('f'); | |
13793 MethodElementImpl e = f.staticElement; | |
13794 FunctionType ft = e.type.instantiate([typeProvider.stringType]); | |
13795 expect(ft.toString(), '(String) → String'); | |
13796 } | |
13797 | |
13798 void test_genericFunction_typedef() { | |
13799 String code = r''' | |
13800 typedef T F<T>(T x); | |
13801 F f0; | |
13802 | |
13803 class C { | |
13804 static F f1; | |
13805 F f2; | |
13806 void g(F f3) { | |
13807 F f4; | |
13808 f0(3); | |
13809 f1(3); | |
13810 f2(3); | |
13811 f3(3); | |
13812 f4(3); | |
13813 } | |
13814 } | |
13815 | |
13816 class D<S> { | |
13817 static F f1; | |
13818 F f2; | |
13819 void g(F f3) { | |
13820 F f4; | |
13821 f0(3); | |
13822 f1(3); | |
13823 f2(3); | |
13824 f3(3); | |
13825 f4(3); | |
13826 } | |
13827 } | |
13828 '''; | |
13829 _resolveTestUnit(code); | |
13830 | |
13831 checkBody(String className) { | |
13832 List<Statement> statements = | |
13833 AstFinder.getStatementsInMethod(testUnit, className, "g"); | |
13834 | |
13835 for (int i = 1; i <= 5; i++) { | |
13836 Expression exp = (statements[i] as ExpressionStatement).expression; | |
13837 expect(exp.staticType, typeProvider.dynamicType); | |
13838 } | |
13839 } | |
13840 | |
13841 checkBody("C"); | |
13842 checkBody("D"); | |
13843 } | |
13844 | |
13845 void test_genericMethod() { | |
13846 _resolveTestUnit(r''' | |
13847 class C<E> { | |
13848 List/*<T>*/ f/*<T>*/(E e) => null; | |
13849 } | |
13850 main() { | |
13851 C<String> cOfString; | |
13852 } | |
13853 '''); | |
13854 _expectFunctionType('f', '<T>(E) → List<T>', | |
13855 elementTypeParams: '[T]', | |
13856 typeParams: '[E]', | |
13857 typeArgs: '[E]', | |
13858 typeFormals: '[T]'); | |
13859 SimpleIdentifier c = _findIdentifier('cOfString'); | |
13860 FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type; | |
13861 expect(ft.toString(), '<T>(String) → List<T>'); | |
13862 ft = ft.instantiate([typeProvider.intType]); | |
13863 expect(ft.toString(), '(String) → List<int>'); | |
13864 expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]'); | |
13865 } | |
13866 | |
13867 void test_genericMethod_explicitTypeParams() { | |
13868 _resolveTestUnit(r''' | |
13869 class C<E> { | |
13870 List/*<T>*/ f/*<T>*/(E e) => null; | |
13871 } | |
13872 main() { | |
13873 C<String> cOfString; | |
13874 var x = cOfString.f/*<int>*/('hi'); | |
13875 } | |
13876 '''); | |
13877 MethodInvocation f = _findIdentifier('f/*<int>*/').parent; | |
13878 FunctionType ft = f.staticInvokeType; | |
13879 expect(ft.toString(), '(String) → List<int>'); | |
13880 expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]'); | |
13881 | |
13882 SimpleIdentifier x = _findIdentifier('x'); | |
13883 expect(x.staticType, | |
13884 typeProvider.listType.instantiate([typeProvider.intType])); | |
13885 } | |
13886 | |
13887 void test_genericMethod_functionExpressionInvocation_explicit() { | |
13888 _resolveTestUnit(r''' | |
13889 class C<E> { | |
13890 /*=T*/ f/*<T>*/(/*=T*/ e) => null; | |
13891 static /*=T*/ g/*<T>*/(/*=T*/ e) => null; | |
13892 static final h = g; | |
13893 } | |
13894 | |
13895 /*=T*/ topF/*<T>*/(/*=T*/ e) => null; | |
13896 var topG = topF; | |
13897 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) { | |
13898 var c = new C<int>(); | |
13899 /*=T*/ lf/*<T>*/(/*=T*/ e) => null; | |
13900 | |
13901 var lambdaCall = (/*<E>*/(/*=E*/ e) => e)/*<int>*/(3); | |
13902 var methodCall = (c.f)/*<int>*/(3); | |
13903 var staticCall = (C.g)/*<int>*/(3); | |
13904 var staticFieldCall = (C.h)/*<int>*/(3); | |
13905 var topFunCall = (topF)/*<int>*/(3); | |
13906 var topFieldCall = (topG)/*<int>*/(3); | |
13907 var localCall = (lf)/*<int>*/(3); | |
13908 var paramCall = (pf)/*<int>*/(3); | |
13909 } | |
13910 '''); | |
13911 _expectIdentifierType('methodCall', "int"); | |
13912 _expectIdentifierType('staticCall', "int"); | |
13913 _expectIdentifierType('staticFieldCall', "int"); | |
13914 _expectIdentifierType('topFunCall', "int"); | |
13915 _expectIdentifierType('topFieldCall', "int"); | |
13916 _expectIdentifierType('localCall', "int"); | |
13917 _expectIdentifierType('paramCall', "int"); | |
13918 _expectIdentifierType('lambdaCall', "int"); | |
13919 } | |
13920 | |
13921 void test_genericMethod_functionExpressionInvocation_inferred() { | |
13922 _resolveTestUnit(r''' | |
13923 class C<E> { | |
13924 /*=T*/ f/*<T>*/(/*=T*/ e) => null; | |
13925 static /*=T*/ g/*<T>*/(/*=T*/ e) => null; | |
13926 static final h = g; | |
13927 } | |
13928 | |
13929 /*=T*/ topF/*<T>*/(/*=T*/ e) => null; | |
13930 var topG = topF; | |
13931 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) { | |
13932 var c = new C<int>(); | |
13933 /*=T*/ lf/*<T>*/(/*=T*/ e) => null; | |
13934 | |
13935 var lambdaCall = (/*<E>*/(/*=E*/ e) => e)(3); | |
13936 var methodCall = (c.f)(3); | |
13937 var staticCall = (C.g)(3); | |
13938 var staticFieldCall = (C.h)(3); | |
13939 var topFunCall = (topF)(3); | |
13940 var topFieldCall = (topG)(3); | |
13941 var localCall = (lf)(3); | |
13942 var paramCall = (pf)(3); | |
13943 } | |
13944 '''); | |
13945 _expectIdentifierType('methodCall', "int"); | |
13946 _expectIdentifierType('staticCall', "int"); | |
13947 _expectIdentifierType('staticFieldCall', "int"); | |
13948 _expectIdentifierType('topFunCall', "int"); | |
13949 _expectIdentifierType('topFieldCall', "int"); | |
13950 _expectIdentifierType('localCall', "int"); | |
13951 _expectIdentifierType('paramCall', "int"); | |
13952 _expectIdentifierType('lambdaCall', "int"); | |
13953 } | |
13954 | |
13955 void test_genericMethod_functionInvocation_explicit() { | |
13956 _resolveTestUnit(r''' | |
13957 class C<E> { | |
13958 /*=T*/ f/*<T>*/(/*=T*/ e) => null; | |
13959 static /*=T*/ g/*<T>*/(/*=T*/ e) => null; | |
13960 static final h = g; | |
13961 } | |
13962 | |
13963 /*=T*/ topF/*<T>*/(/*=T*/ e) => null; | |
13964 var topG = topF; | |
13965 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) { | |
13966 var c = new C<int>(); | |
13967 /*=T*/ lf/*<T>*/(/*=T*/ e) => null; | |
13968 var methodCall = c.f/*<int>*/(3); | |
13969 var staticCall = C.g/*<int>*/(3); | |
13970 var staticFieldCall = C.h/*<int>*/(3); | |
13971 var topFunCall = topF/*<int>*/(3); | |
13972 var topFieldCall = topG/*<int>*/(3); | |
13973 var localCall = lf/*<int>*/(3); | |
13974 var paramCall = pf/*<int>*/(3); | |
13975 } | |
13976 '''); | |
13977 _expectIdentifierType('methodCall', "int"); | |
13978 _expectIdentifierType('staticCall', "int"); | |
13979 _expectIdentifierType('staticFieldCall', "int"); | |
13980 _expectIdentifierType('topFunCall', "int"); | |
13981 _expectIdentifierType('topFieldCall', "int"); | |
13982 _expectIdentifierType('localCall', "int"); | |
13983 _expectIdentifierType('paramCall', "int"); | |
13984 } | |
13985 | |
13986 void test_genericMethod_functionInvocation_inferred() { | |
13987 _resolveTestUnit(r''' | |
13988 class C<E> { | |
13989 /*=T*/ f/*<T>*/(/*=T*/ e) => null; | |
13990 static /*=T*/ g/*<T>*/(/*=T*/ e) => null; | |
13991 static final h = g; | |
13992 } | |
13993 | |
13994 /*=T*/ topF/*<T>*/(/*=T*/ e) => null; | |
13995 var topG = topF; | |
13996 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) { | |
13997 var c = new C<int>(); | |
13998 /*=T*/ lf/*<T>*/(/*=T*/ e) => null; | |
13999 var methodCall = c.f(3); | |
14000 var staticCall = C.g(3); | |
14001 var staticFieldCall = C.h(3); | |
14002 var topFunCall = topF(3); | |
14003 var topFieldCall = topG(3); | |
14004 var localCall = lf(3); | |
14005 var paramCall = pf(3); | |
14006 } | |
14007 '''); | |
14008 _expectIdentifierType('methodCall', "int"); | |
14009 _expectIdentifierType('staticCall', "int"); | |
14010 _expectIdentifierType('staticFieldCall', "int"); | |
14011 _expectIdentifierType('topFunCall', "int"); | |
14012 _expectIdentifierType('topFieldCall', "int"); | |
14013 _expectIdentifierType('localCall', "int"); | |
14014 _expectIdentifierType('paramCall', "int"); | |
14015 } | |
14016 | |
14017 void test_genericMethod_functionTypedParameter() { | |
14018 _resolveTestUnit(r''' | |
14019 class C<E> { | |
14020 List/*<T>*/ f/*<T>*/(/*=T*/ f(E e)) => null; | |
14021 } | |
14022 main() { | |
14023 C<String> cOfString; | |
14024 } | |
14025 '''); | |
14026 _expectFunctionType('f', '<T>((E) → T) → List<T>', | |
14027 elementTypeParams: '[T]', | |
14028 typeParams: '[E]', | |
14029 typeArgs: '[E]', | |
14030 typeFormals: '[T]'); | |
14031 | |
14032 SimpleIdentifier c = _findIdentifier('cOfString'); | |
14033 FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type; | |
14034 expect(ft.toString(), '<T>((String) → T) → List<T>'); | |
14035 ft = ft.instantiate([typeProvider.intType]); | |
14036 expect(ft.toString(), '((String) → int) → List<int>'); | |
14037 } | |
14038 | |
14039 void test_genericMethod_implicitDynamic() { | |
14040 // Regression test for: | |
14041 // https://github.com/dart-lang/sdk/issues/25100#issuecomment-162047588 | |
14042 // These should not cause any hints or warnings. | |
14043 _resolveTestUnit(r''' | |
14044 class List<E> { | |
14045 /*=T*/ map/*<T>*/(/*=T*/ f(E e)) => null; | |
14046 } | |
14047 void foo() { | |
14048 List list = null; | |
14049 list.map((e) => e); | |
14050 list.map((e) => 3); | |
14051 }'''); | |
14052 _expectIdentifierType('map((e) => e);', '<T>((dynamic) → T) → T', isNull); | |
14053 _expectIdentifierType('map((e) => 3);', '<T>((dynamic) → T) → T', isNull); | |
14054 | |
14055 MethodInvocation m1 = _findIdentifier('map((e) => e);').parent; | |
14056 expect(m1.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic'); | |
14057 MethodInvocation m2 = _findIdentifier('map((e) => 3);').parent; | |
14058 expect(m2.staticInvokeType.toString(), '((dynamic) → int) → int'); | |
14059 } | |
14060 | |
14061 void test_genericMethod_max_doubleDouble() { | |
14062 String code = r''' | |
14063 import 'dart:math'; | |
14064 main() { | |
14065 var foo = max(1.0, 2.0); | |
14066 } | |
14067 '''; | |
14068 _resolveTestUnit(code); | |
14069 _expectInitializerType('foo', 'double', isNull); | |
14070 } | |
14071 | |
14072 void test_genericMethod_max_doubleDouble_prefixed() { | |
14073 String code = r''' | |
14074 import 'dart:math' as math; | |
14075 main() { | |
14076 var foo = math.max(1.0, 2.0); | |
14077 } | |
14078 '''; | |
14079 _resolveTestUnit(code); | |
14080 _expectInitializerType('foo', 'double', isNull); | |
14081 } | |
14082 | |
14083 void test_genericMethod_max_doubleInt() { | |
14084 String code = r''' | |
14085 import 'dart:math'; | |
14086 main() { | |
14087 var foo = max(1.0, 2); | |
14088 } | |
14089 '''; | |
14090 _resolveTestUnit(code); | |
14091 _expectInitializerType('foo', 'num', isNull); | |
14092 } | |
14093 | |
14094 void test_genericMethod_max_intDouble() { | |
14095 String code = r''' | |
14096 import 'dart:math'; | |
14097 main() { | |
14098 var foo = max(1, 2.0); | |
14099 } | |
14100 '''; | |
14101 _resolveTestUnit(code); | |
14102 _expectInitializerType('foo', 'num', isNull); | |
14103 } | |
14104 | |
14105 void test_genericMethod_max_intInt() { | |
14106 String code = r''' | |
14107 import 'dart:math'; | |
14108 main() { | |
14109 var foo = max(1, 2); | |
14110 } | |
14111 '''; | |
14112 _resolveTestUnit(code); | |
14113 _expectInitializerType('foo', 'int', isNull); | |
14114 } | |
14115 | |
14116 void test_genericMethod_nestedBound() { | |
14117 String code = r''' | |
14118 class Foo<T extends num> { | |
14119 void method/*<U extends T>*/(dynamic/*=U*/ u) { | |
14120 u.abs(); | |
14121 } | |
14122 } | |
14123 '''; | |
14124 // Just validate that there is no warning on the call to `.abs()`. | |
14125 _resolveTestUnit(code); | |
14126 } | |
14127 | |
14128 void test_genericMethod_nestedCapture() { | |
14129 _resolveTestUnit(r''' | |
14130 class C<T> { | |
14131 /*=T*/ f/*<S>*/(/*=S*/ x) { | |
14132 new C<S>().f/*<int>*/(3); | |
14133 new C<S>().f; // tear-off | |
14134 return null; | |
14135 } | |
14136 } | |
14137 '''); | |
14138 MethodInvocation f = _findIdentifier('f/*<int>*/(3);').parent; | |
14139 expect(f.staticInvokeType.toString(), '(int) → S'); | |
14140 FunctionType ft = f.staticInvokeType; | |
14141 expect('${ft.typeArguments}/${ft.typeParameters}', '[S, int]/[T, S]'); | |
14142 | |
14143 _expectIdentifierType('f;', '<S₀>(S₀) → S'); | |
14144 } | |
14145 | |
14146 void test_genericMethod_nestedFunctions() { | |
14147 _resolveTestUnit(r''' | |
14148 /*=S*/ f/*<S>*/(/*=S*/ x) { | |
14149 g/*<S>*/(/*=S*/ x) => f; | |
14150 return null; | |
14151 } | |
14152 '''); | |
14153 _expectIdentifierType('f', '<S>(S) → S'); | |
14154 _expectIdentifierType('g', '<S>(S) → dynamic'); | |
14155 } | |
14156 | |
14157 void test_genericMethod_override() { | |
14158 _resolveTestUnit(r''' | |
14159 class C { | |
14160 /*=T*/ f/*<T>*/(/*=T*/ x) => null; | |
14161 } | |
14162 class D extends C { | |
14163 /*=T*/ f/*<T>*/(/*=T*/ x) => null; // from D | |
14164 } | |
14165 '''); | |
14166 _expectFunctionType('f/*<T>*/(/*=T*/ x) => null; // from D', '<T>(T) → T', | |
14167 elementTypeParams: '[T]', typeFormals: '[T]'); | |
14168 SimpleIdentifier f = | |
14169 _findIdentifier('f/*<T>*/(/*=T*/ x) => null; // from D'); | |
14170 MethodElementImpl e = f.staticElement; | |
14171 FunctionType ft = e.type.instantiate([typeProvider.stringType]); | |
14172 expect(ft.toString(), '(String) → String'); | |
14173 } | |
14174 | |
14175 void test_genericMethod_override_bounds() { | |
14176 _resolveTestUnit(r''' | |
14177 class A {} | |
14178 class B extends A {} | |
14179 class C { | |
14180 /*=T*/ f/*<T extends B>*/(/*=T*/ x) => null; | |
14181 } | |
14182 class D extends C { | |
14183 /*=T*/ f/*<T extends A>*/(/*=T*/ x) => null; | |
14184 } | |
14185 '''); | |
14186 } | |
14187 | |
14188 void test_genericMethod_override_invalidReturnType() { | |
14189 Source source = addSource(r''' | |
14190 class C { | |
14191 Iterable/*<T>*/ f/*<T>*/(/*=T*/ x) => null; | |
14192 } | |
14193 class D extends C { | |
14194 String f/*<S>*/(/*=S*/ x) => null; | |
14195 }'''); | |
14196 // TODO(jmesserly): we can't use assertErrors because STRONG_MODE_* errors | |
14197 // from CodeChecker don't have working equality. | |
14198 List<AnalysisError> errors = analysisContext2.computeErrors(source); | |
14199 | |
14200 // Sort errors by name. | |
14201 errors.sort((AnalysisError e1, AnalysisError e2) => | |
14202 e1.errorCode.name.compareTo(e2.errorCode.name)); | |
14203 | |
14204 expect(errors.map((e) => e.errorCode.name), [ | |
14205 'INVALID_METHOD_OVERRIDE_RETURN_TYPE', | |
14206 'STRONG_MODE_INVALID_METHOD_OVERRIDE' | |
14207 ]); | |
14208 expect(errors[0].message, contains('Iterable<S>'), | |
14209 reason: 'errors should be in terms of the type parameters ' | |
14210 'at the error location'); | |
14211 verify([source]); | |
14212 } | |
14213 | |
14214 void test_genericMethod_override_invalidTypeParamBounds() { | |
14215 Source source = addSource(r''' | |
14216 class A {} | |
14217 class B extends A {} | |
14218 class C { | |
14219 /*=T*/ f/*<T extends A>*/(/*=T*/ x) => null; | |
14220 } | |
14221 class D extends C { | |
14222 /*=T*/ f/*<T extends B>*/(/*=T*/ x) => null; | |
14223 }'''); | |
14224 // TODO(jmesserly): this is modified code from assertErrors, which we can't | |
14225 // use directly because STRONG_MODE_* errors don't have working equality. | |
14226 List<AnalysisError> errors = analysisContext2.computeErrors(source); | |
14227 List errorNames = errors.map((e) => e.errorCode.name).toList(); | |
14228 expect(errorNames, hasLength(2)); | |
14229 expect(errorNames, contains('STRONG_MODE_INVALID_METHOD_OVERRIDE')); | |
14230 expect( | |
14231 errorNames, contains('INVALID_METHOD_OVERRIDE_TYPE_PARAMETER_BOUND')); | |
14232 verify([source]); | |
14233 } | |
14234 | |
14235 void test_genericMethod_override_invalidTypeParamCount() { | |
14236 Source source = addSource(r''' | |
14237 class C { | |
14238 /*=T*/ f/*<T>*/(/*=T*/ x) => null; | |
14239 } | |
14240 class D extends C { | |
14241 /*=S*/ f/*<T, S>*/(/*=T*/ x) => null; | |
14242 }'''); | |
14243 // TODO(jmesserly): we can't use assertErrors because STRONG_MODE_* errors | |
14244 // from CodeChecker don't have working equality. | |
14245 List<AnalysisError> errors = analysisContext2.computeErrors(source); | |
14246 expect(errors.map((e) => e.errorCode.name), [ | |
14247 'STRONG_MODE_INVALID_METHOD_OVERRIDE', | |
14248 'INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS' | |
14249 ]); | |
14250 verify([source]); | |
14251 } | |
14252 | |
14253 void test_genericMethod_propagatedType_promotion() { | |
14254 // Regression test for: | |
14255 // https://github.com/dart-lang/sdk/issues/25340 | |
14256 | |
14257 // Note, after https://github.com/dart-lang/sdk/issues/25486 the original | |
14258 // example won't work, as we now compute a static type and therefore discard | |
14259 // the propagated type. So a new test was created that doesn't run under | |
14260 // strong mode. | |
14261 _resolveTestUnit(r''' | |
14262 abstract class Iter { | |
14263 List/*<S>*/ map/*<S>*/(/*=S*/ f(x)); | |
14264 } | |
14265 class C {} | |
14266 C toSpan(dynamic element) { | |
14267 if (element is Iter) { | |
14268 var y = element.map(toSpan); | |
14269 } | |
14270 return null; | |
14271 }'''); | |
14272 _expectIdentifierType('y = ', 'List<C>', isNull); | |
14273 } | |
14274 | |
14275 void test_genericMethod_tearoff() { | |
14276 _resolveTestUnit(r''' | |
14277 class C<E> { | |
14278 /*=T*/ f/*<T>*/(E e) => null; | |
14279 static /*=T*/ g/*<T>*/(/*=T*/ e) => null; | |
14280 static final h = g; | |
14281 } | |
14282 | |
14283 /*=T*/ topF/*<T>*/(/*=T*/ e) => null; | |
14284 var topG = topF; | |
14285 void test/*<S>*/(/*=T*/ pf/*<T>*/(/*=T*/ e)) { | |
14286 var c = new C<int>(); | |
14287 /*=T*/ lf/*<T>*/(/*=T*/ e) => null; | |
14288 var methodTearOff = c.f; | |
14289 var staticTearOff = C.g; | |
14290 var staticFieldTearOff = C.h; | |
14291 var topFunTearOff = topF; | |
14292 var topFieldTearOff = topG; | |
14293 var localTearOff = lf; | |
14294 var paramTearOff = pf; | |
14295 } | |
14296 '''); | |
14297 _expectIdentifierType('methodTearOff', "<T>(int) → T"); | |
14298 _expectIdentifierType('staticTearOff', "<T>(T) → T"); | |
14299 _expectIdentifierType('staticFieldTearOff', "<T>(T) → T"); | |
14300 _expectIdentifierType('topFunTearOff', "<T>(T) → T"); | |
14301 _expectIdentifierType('topFieldTearOff', "<T>(T) → T"); | |
14302 _expectIdentifierType('localTearOff', "<T>(T) → T"); | |
14303 _expectIdentifierType('paramTearOff', "<T>(T) → T"); | |
14304 } | |
14305 | |
14306 void test_genericMethod_then() { | |
14307 String code = r''' | |
14308 import 'dart:async'; | |
14309 String toString(int x) => x.toString(); | |
14310 main() { | |
14311 Future<int> bar = null; | |
14312 var foo = bar.then(toString); | |
14313 } | |
14314 '''; | |
14315 _resolveTestUnit(code); | |
14316 _expectInitializerType('foo', 'Future<String>', isNull); | |
14317 } | |
14318 | |
14319 void test_genericMethod_then_prefixed() { | |
14320 String code = r''' | |
14321 import 'dart:async' as async; | |
14322 String toString(int x) => x.toString(); | |
14323 main() { | |
14324 async.Future<int> bar = null; | |
14325 var foo = bar.then(toString); | |
14326 } | |
14327 '''; | |
14328 _resolveTestUnit(code); | |
14329 _expectInitializerType('foo', 'Future<String>', isNull); | |
14330 } | |
14331 | |
14332 void test_genericMethod_then_propagatedType() { | |
14333 // Regression test for https://github.com/dart-lang/sdk/issues/25482. | |
14334 String code = r''' | |
14335 import 'dart:async'; | |
14336 void main() { | |
14337 Future<String> p; | |
14338 var foo = p.then((r) => new Future<String>.value(3)); | |
14339 } | |
14340 '''; | |
14341 // This should produce no hints or warnings. | |
14342 _resolveTestUnit(code); | |
14343 _expectInitializerType('foo', 'Future<String>', isNull); | |
14344 } | |
14345 | |
14346 void test_implicitBounds() { | |
14347 String code = r''' | |
14348 class A<T> {} | |
14349 | |
14350 class B<T extends num> {} | |
14351 | |
14352 class C<S extends int, T extends B<S>, U extends B> {} | |
14353 | |
14354 void test() { | |
14355 // | |
14356 A ai; | |
14357 B bi; | |
14358 C ci; | |
14359 var aa = new A(); | |
14360 var bb = new B(); | |
14361 var cc = new C(); | |
14362 } | |
14363 '''; | |
14364 _resolveTestUnit(code); | |
14365 _expectIdentifierType('ai', "A<dynamic>"); | |
14366 _expectIdentifierType('bi', "B<num>"); | |
14367 _expectIdentifierType('ci', "C<int, B<int>, B<num>>"); | |
14368 _expectIdentifierType('aa', "A<dynamic>"); | |
14369 _expectIdentifierType('bb', "B<num>"); | |
14370 _expectIdentifierType('cc', "C<int, B<int>, B<num>>"); | |
14371 } | |
14372 | |
14373 void test_setterWithDynamicTypeIsError() { | |
14374 Source source = addSource(r''' | |
14375 class A { | |
14376 dynamic set f(String s) => null; | |
14377 } | |
14378 dynamic set g(int x) => null; | |
14379 '''); | |
14380 computeLibrarySourceErrors(source); | |
14381 assertErrors(source, [ | |
14382 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, | |
14383 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER | |
14384 ]); | |
14385 verify([source]); | |
14386 } | |
14387 | |
14388 void test_setterWithExplicitVoidType_returningVoid() { | |
14389 Source source = addSource(r''' | |
14390 void returnsVoid() {} | |
14391 class A { | |
14392 void set f(String s) => returnsVoid(); | |
14393 } | |
14394 void set g(int x) => returnsVoid(); | |
14395 '''); | |
14396 computeLibrarySourceErrors(source); | |
14397 assertNoErrors(source); | |
14398 verify([source]); | |
14399 } | |
14400 | |
14401 void test_setterWithNoVoidType() { | |
14402 Source source = addSource(r''' | |
14403 class A { | |
14404 set f(String s) { | |
14405 return '42'; | |
14406 } | |
14407 } | |
14408 set g(int x) => 42; | |
14409 '''); | |
14410 computeLibrarySourceErrors(source); | |
14411 assertErrors(source, [ | |
14412 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, | |
14413 StaticTypeWarningCode.RETURN_OF_INVALID_TYPE | |
14414 ]); | |
14415 verify([source]); | |
14416 } | |
14417 | |
14418 void test_setterWithNoVoidType_returningVoid() { | |
14419 Source source = addSource(r''' | |
14420 void returnsVoid() {} | |
14421 class A { | |
14422 set f(String s) => returnsVoid(); | |
14423 } | |
14424 set g(int x) => returnsVoid(); | |
14425 '''); | |
14426 computeLibrarySourceErrors(source); | |
14427 assertNoErrors(source); | |
14428 verify([source]); | |
14429 } | |
14430 | |
14431 void test_setterWithOtherTypeIsError() { | |
14432 Source source = addSource(r''' | |
14433 class A { | |
14434 String set f(String s) => null; | |
14435 } | |
14436 Object set g(x) => null; | |
14437 '''); | |
14438 computeLibrarySourceErrors(source); | |
14439 assertErrors(source, [ | |
14440 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER, | |
14441 StaticWarningCode.NON_VOID_RETURN_FOR_SETTER | |
14442 ]); | |
14443 verify([source]); | |
14444 } | |
14445 | |
14446 void test_ternaryOperator_null_left() { | |
14447 String code = r''' | |
14448 main() { | |
14449 var foo = (true) ? null : 3; | |
14450 } | |
14451 '''; | |
14452 _resolveTestUnit(code); | |
14453 _expectInitializerType('foo', 'int', isNull); | |
14454 } | |
14455 | |
14456 void test_ternaryOperator_null_right() { | |
14457 String code = r''' | |
14458 main() { | |
14459 var foo = (true) ? 3 : null; | |
14460 } | |
14461 '''; | |
14462 _resolveTestUnit(code); | |
14463 _expectInitializerType('foo', 'int', isNull); | |
14464 } | |
14465 } | |
14466 | |
14467 @reflectiveTest | |
14468 class StrongModeTypePropagationTest extends ResolverTestCase { | |
14469 @override | |
14470 void setUp() { | |
14471 super.setUp(); | |
14472 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); | |
14473 options.strongMode = true; | |
14474 resetWithOptions(options); | |
14475 } | |
14476 | |
14477 void test_foreachInference_dynamic_disabled() { | |
14478 String code = r''' | |
14479 main() { | |
14480 var list = <int>[]; | |
14481 for (dynamic v in list) { | |
14482 v; // marker | |
14483 } | |
14484 }'''; | |
14485 _assertPropagatedIterationType( | |
14486 code, typeProvider.dynamicType, typeProvider.intType); | |
14487 _assertTypeOfMarkedExpression( | |
14488 code, typeProvider.dynamicType, typeProvider.intType); | |
14489 } | |
14490 | |
14491 void test_foreachInference_reusedVar_disabled() { | |
14492 String code = r''' | |
14493 main() { | |
14494 var list = <int>[]; | |
14495 var v; | |
14496 for (v in list) { | |
14497 v; // marker | |
14498 } | |
14499 }'''; | |
14500 _assertPropagatedIterationType( | |
14501 code, typeProvider.dynamicType, typeProvider.intType); | |
14502 _assertTypeOfMarkedExpression( | |
14503 code, typeProvider.dynamicType, typeProvider.intType); | |
14504 } | |
14505 | |
14506 void test_foreachInference_var() { | |
14507 String code = r''' | |
14508 main() { | |
14509 var list = <int>[]; | |
14510 for (var v in list) { | |
14511 v; // marker | |
14512 } | |
14513 }'''; | |
14514 _assertPropagatedIterationType(code, typeProvider.intType, null); | |
14515 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14516 } | |
14517 | |
14518 void test_foreachInference_var_iterable() { | |
14519 String code = r''' | |
14520 main() { | |
14521 Iterable<int> list = <int>[]; | |
14522 for (var v in list) { | |
14523 v; // marker | |
14524 } | |
14525 }'''; | |
14526 _assertPropagatedIterationType(code, typeProvider.intType, null); | |
14527 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14528 } | |
14529 | |
14530 void test_foreachInference_var_stream() { | |
14531 String code = r''' | |
14532 import 'dart:async'; | |
14533 main() async { | |
14534 Stream<int> stream = null; | |
14535 await for (var v in stream) { | |
14536 v; // marker | |
14537 } | |
14538 }'''; | |
14539 _assertPropagatedIterationType(code, typeProvider.intType, null); | |
14540 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14541 } | |
14542 | |
14543 void test_localVariableInference_bottom_disabled() { | |
14544 String code = r''' | |
14545 main() { | |
14546 var v = null; | |
14547 v; // marker | |
14548 }'''; | |
14549 _assertPropagatedAssignedType(code, typeProvider.dynamicType, null); | |
14550 _assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null); | |
14551 } | |
14552 | |
14553 void test_localVariableInference_constant() { | |
14554 String code = r''' | |
14555 main() { | |
14556 var v = 3; | |
14557 v; // marker | |
14558 }'''; | |
14559 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14560 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14561 } | |
14562 | |
14563 void test_localVariableInference_declaredType_disabled() { | |
14564 String code = r''' | |
14565 main() { | |
14566 dynamic v = 3; | |
14567 v; // marker | |
14568 }'''; | |
14569 _assertPropagatedAssignedType( | |
14570 code, typeProvider.dynamicType, typeProvider.intType); | |
14571 _assertTypeOfMarkedExpression( | |
14572 code, typeProvider.dynamicType, typeProvider.intType); | |
14573 } | |
14574 | |
14575 void test_localVariableInference_noInitializer_disabled() { | |
14576 String code = r''' | |
14577 main() { | |
14578 var v; | |
14579 v = 3; | |
14580 v; // marker | |
14581 }'''; | |
14582 _assertPropagatedAssignedType( | |
14583 code, typeProvider.dynamicType, typeProvider.intType); | |
14584 _assertTypeOfMarkedExpression( | |
14585 code, typeProvider.dynamicType, typeProvider.intType); | |
14586 } | |
14587 | |
14588 void test_localVariableInference_transitive_field_inferred_lexical() { | |
14589 String code = r''' | |
14590 class A { | |
14591 final x = 3; | |
14592 f() { | |
14593 var v = x; | |
14594 return v; // marker | |
14595 } | |
14596 } | |
14597 main() { | |
14598 } | |
14599 '''; | |
14600 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14601 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14602 } | |
14603 | |
14604 void test_localVariableInference_transitive_field_inferred_reversed() { | |
14605 String code = r''' | |
14606 class A { | |
14607 f() { | |
14608 var v = x; | |
14609 return v; // marker | |
14610 } | |
14611 final x = 3; | |
14612 } | |
14613 main() { | |
14614 } | |
14615 '''; | |
14616 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14617 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14618 } | |
14619 | |
14620 void test_localVariableInference_transitive_field_lexical() { | |
14621 String code = r''' | |
14622 class A { | |
14623 int x = 3; | |
14624 f() { | |
14625 var v = x; | |
14626 return v; // marker | |
14627 } | |
14628 } | |
14629 main() { | |
14630 } | |
14631 '''; | |
14632 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14633 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14634 } | |
14635 | |
14636 void test_localVariableInference_transitive_field_reversed() { | |
14637 String code = r''' | |
14638 class A { | |
14639 f() { | |
14640 var v = x; | |
14641 return v; // marker | |
14642 } | |
14643 int x = 3; | |
14644 } | |
14645 main() { | |
14646 } | |
14647 '''; | |
14648 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14649 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14650 } | |
14651 | |
14652 void test_localVariableInference_transitive_list_local() { | |
14653 String code = r''' | |
14654 main() { | |
14655 var x = <int>[3]; | |
14656 var v = x[0]; | |
14657 v; // marker | |
14658 }'''; | |
14659 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14660 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14661 } | |
14662 | |
14663 void test_localVariableInference_transitive_local() { | |
14664 String code = r''' | |
14665 main() { | |
14666 var x = 3; | |
14667 var v = x; | |
14668 v; // marker | |
14669 }'''; | |
14670 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14671 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14672 } | |
14673 | |
14674 void test_localVariableInference_transitive_toplevel_inferred_lexical() { | |
14675 String code = r''' | |
14676 final x = 3; | |
14677 main() { | |
14678 var v = x; | |
14679 v; // marker | |
14680 } | |
14681 '''; | |
14682 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14683 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14684 } | |
14685 | |
14686 void test_localVariableInference_transitive_toplevel_inferred_reversed() { | |
14687 String code = r''' | |
14688 main() { | |
14689 var v = x; | |
14690 v; // marker | |
14691 } | |
14692 final x = 3; | |
14693 '''; | |
14694 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14695 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14696 } | |
14697 | |
14698 void test_localVariableInference_transitive_toplevel_lexical() { | |
14699 String code = r''' | |
14700 int x = 3; | |
14701 main() { | |
14702 var v = x; | |
14703 v; // marker | |
14704 } | |
14705 '''; | |
14706 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14707 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14708 } | |
14709 | |
14710 void test_localVariableInference_transitive_toplevel_reversed() { | |
14711 String code = r''' | |
14712 main() { | |
14713 var v = x; | |
14714 v; // marker | |
14715 } | |
14716 int x = 3; | |
14717 '''; | |
14718 _assertPropagatedAssignedType(code, typeProvider.intType, null); | |
14719 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); | |
14720 } | |
14721 } | |
14722 | |
14723 @reflectiveTest | 1042 @reflectiveTest |
14724 class SubtypeManagerTest { | 1043 class SubtypeManagerTest { |
14725 /** | 1044 /** |
14726 * The inheritance manager being tested. | 1045 * The inheritance manager being tested. |
14727 */ | 1046 */ |
14728 SubtypeManager _subtypeManager; | 1047 SubtypeManager _subtypeManager; |
14729 | 1048 |
14730 /** | 1049 /** |
14731 * The compilation unit element containing all of the types setup in each test
. | 1050 * The compilation unit element containing all of the types setup in each test
. |
14732 */ | 1051 */ |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14813 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); | 1132 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
14814 _definingCompilationUnit.types = <ClassElement>[classA, classB]; | 1133 _definingCompilationUnit.types = <ClassElement>[classA, classB]; |
14815 HashSet<ClassElement> subtypesOfA = | 1134 HashSet<ClassElement> subtypesOfA = |
14816 _subtypeManager.computeAllSubtypes(classA); | 1135 _subtypeManager.computeAllSubtypes(classA); |
14817 List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA); | 1136 List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA); |
14818 expect(subtypesOfA, hasLength(1)); | 1137 expect(subtypesOfA, hasLength(1)); |
14819 expect(arraySubtypesOfA, unorderedEquals([classB])); | 1138 expect(arraySubtypesOfA, unorderedEquals([classB])); |
14820 } | 1139 } |
14821 } | 1140 } |
14822 | 1141 |
14823 class TestPackageUriResolver extends UriResolver { | |
14824 Map<Uri, Source> sourceMap = new HashMap<Uri, Source>(); | |
14825 | |
14826 TestPackageUriResolver(Map<String, String> map) { | |
14827 map.forEach((String uri, String contents) { | |
14828 sourceMap[Uri.parse(uri)] = | |
14829 new StringSource(contents, '/test_pkg_source.dart'); | |
14830 }); | |
14831 } | |
14832 | |
14833 @override | |
14834 Source resolveAbsolute(Uri uri, [Uri actualUri]) => sourceMap[uri]; | |
14835 | |
14836 @override | |
14837 Uri restoreAbsolute(Source source) => throw new UnimplementedError(); | |
14838 } | |
14839 | |
14840 @reflectiveTest | 1142 @reflectiveTest |
14841 class TypeOverrideManagerTest extends EngineTestCase { | 1143 class TypeOverrideManagerTest extends EngineTestCase { |
14842 void test_exitScope_noScopes() { | 1144 void test_exitScope_noScopes() { |
14843 TypeOverrideManager manager = new TypeOverrideManager(); | 1145 TypeOverrideManager manager = new TypeOverrideManager(); |
14844 try { | 1146 try { |
14845 manager.exitScope(); | 1147 manager.exitScope(); |
14846 fail("Expected IllegalStateException"); | 1148 fail("Expected IllegalStateException"); |
14847 } on IllegalStateException { | 1149 } on IllegalStateException { |
14848 // Expected | 1150 // Expected |
14849 } | 1151 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14905 void test_getType_noScope() { | 1207 void test_getType_noScope() { |
14906 TypeOverrideManager manager = new TypeOverrideManager(); | 1208 TypeOverrideManager manager = new TypeOverrideManager(); |
14907 expect(manager.getType(ElementFactory.localVariableElement2("v")), isNull); | 1209 expect(manager.getType(ElementFactory.localVariableElement2("v")), isNull); |
14908 } | 1210 } |
14909 } | 1211 } |
14910 | 1212 |
14911 @reflectiveTest | 1213 @reflectiveTest |
14912 class TypePropagationTest extends ResolverTestCase { | 1214 class TypePropagationTest extends ResolverTestCase { |
14913 void fail_mergePropagatedTypesAtJoinPoint_1() { | 1215 void fail_mergePropagatedTypesAtJoinPoint_1() { |
14914 // https://code.google.com/p/dart/issues/detail?id=19929 | 1216 // https://code.google.com/p/dart/issues/detail?id=19929 |
14915 _assertTypeOfMarkedExpression( | 1217 assertTypeOfMarkedExpression( |
14916 r''' | 1218 r''' |
14917 f1(x) { | 1219 f1(x) { |
14918 var y = []; | 1220 var y = []; |
14919 if (x) { | 1221 if (x) { |
14920 y = 0; | 1222 y = 0; |
14921 } else { | 1223 } else { |
14922 y = ''; | 1224 y = ''; |
14923 } | 1225 } |
14924 // Propagated type is [List] here: incorrect. | 1226 // Propagated type is [List] here: incorrect. |
14925 // Best we can do is [Object]? | 1227 // Best we can do is [Object]? |
14926 return y; // marker | 1228 return y; // marker |
14927 }''', | 1229 }''', |
14928 null, | 1230 null, |
14929 typeProvider.dynamicType); | 1231 typeProvider.dynamicType); |
14930 } | 1232 } |
14931 | 1233 |
14932 void fail_mergePropagatedTypesAtJoinPoint_2() { | 1234 void fail_mergePropagatedTypesAtJoinPoint_2() { |
14933 // https://code.google.com/p/dart/issues/detail?id=19929 | 1235 // https://code.google.com/p/dart/issues/detail?id=19929 |
14934 _assertTypeOfMarkedExpression( | 1236 assertTypeOfMarkedExpression( |
14935 r''' | 1237 r''' |
14936 f2(x) { | 1238 f2(x) { |
14937 var y = []; | 1239 var y = []; |
14938 if (x) { | 1240 if (x) { |
14939 y = 0; | 1241 y = 0; |
14940 } else { | 1242 } else { |
14941 } | 1243 } |
14942 // Propagated type is [List] here: incorrect. | 1244 // Propagated type is [List] here: incorrect. |
14943 // Best we can do is [Object]? | 1245 // Best we can do is [Object]? |
14944 return y; // marker | 1246 return y; // marker |
14945 }''', | 1247 }''', |
14946 null, | 1248 null, |
14947 typeProvider.dynamicType); | 1249 typeProvider.dynamicType); |
14948 } | 1250 } |
14949 | 1251 |
14950 void fail_mergePropagatedTypesAtJoinPoint_3() { | 1252 void fail_mergePropagatedTypesAtJoinPoint_3() { |
14951 // https://code.google.com/p/dart/issues/detail?id=19929 | 1253 // https://code.google.com/p/dart/issues/detail?id=19929 |
14952 _assertTypeOfMarkedExpression( | 1254 assertTypeOfMarkedExpression( |
14953 r''' | 1255 r''' |
14954 f4(x) { | 1256 f4(x) { |
14955 var y = []; | 1257 var y = []; |
14956 if (x) { | 1258 if (x) { |
14957 y = 0; | 1259 y = 0; |
14958 } else { | 1260 } else { |
14959 y = 1.5; | 1261 y = 1.5; |
14960 } | 1262 } |
14961 // Propagated type is [List] here: incorrect. | 1263 // Propagated type is [List] here: incorrect. |
14962 // A correct answer is the least upper bound of [int] and [double], | 1264 // A correct answer is the least upper bound of [int] and [double], |
14963 // i.e. [num]. | 1265 // i.e. [num]. |
14964 return y; // marker | 1266 return y; // marker |
14965 }''', | 1267 }''', |
14966 null, | 1268 null, |
14967 typeProvider.numType); | 1269 typeProvider.numType); |
14968 } | 1270 } |
14969 | 1271 |
14970 void fail_mergePropagatedTypesAtJoinPoint_5() { | 1272 void fail_mergePropagatedTypesAtJoinPoint_5() { |
14971 // https://code.google.com/p/dart/issues/detail?id=19929 | 1273 // https://code.google.com/p/dart/issues/detail?id=19929 |
14972 _assertTypeOfMarkedExpression( | 1274 assertTypeOfMarkedExpression( |
14973 r''' | 1275 r''' |
14974 f6(x,y) { | 1276 f6(x,y) { |
14975 var z = []; | 1277 var z = []; |
14976 if (x || (z = y) < 0) { | 1278 if (x || (z = y) < 0) { |
14977 } else { | 1279 } else { |
14978 z = 0; | 1280 z = 0; |
14979 } | 1281 } |
14980 // Propagated type is [List] here: incorrect. | 1282 // Propagated type is [List] here: incorrect. |
14981 // Best we can do is [Object]? | 1283 // Best we can do is [Object]? |
14982 return z; // marker | 1284 return z; // marker |
(...skipping 19 matching lines...) Expand all Loading... |
15002 if (c) { | 1304 if (c) { |
15003 d = false; | 1305 d = false; |
15004 } else { | 1306 } else { |
15005 x = ''; | 1307 x = ''; |
15006 c = true; | 1308 c = true; |
15007 continue; | 1309 continue; |
15008 } | 1310 } |
15009 x; // marker | 1311 x; // marker |
15010 } | 1312 } |
15011 }'''; | 1313 }'''; |
15012 DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType; | 1314 DartType t = findMarkedIdentifier(code, "; // marker").propagatedType; |
15013 expect(typeProvider.intType.isSubtypeOf(t), isTrue); | 1315 expect(typeProvider.intType.isSubtypeOf(t), isTrue); |
15014 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); | 1316 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); |
15015 } | 1317 } |
15016 | 1318 |
15017 void fail_mergePropagatedTypesAtJoinPoint_8() { | 1319 void fail_mergePropagatedTypesAtJoinPoint_8() { |
15018 // https://code.google.com/p/dart/issues/detail?id=19929 | 1320 // https://code.google.com/p/dart/issues/detail?id=19929 |
15019 // | 1321 // |
15020 // In nested loops [breaks]s are unsafe for the purposes of | 1322 // In nested loops [breaks]s are unsafe for the purposes of |
15021 // [isAbruptTerminationStatement]. | 1323 // [isAbruptTerminationStatement]. |
15022 // | 1324 // |
(...skipping 11 matching lines...) Expand all Loading... |
15034 d = false; | 1336 d = false; |
15035 } else { | 1337 } else { |
15036 x = ''; | 1338 x = ''; |
15037 c = true; | 1339 c = true; |
15038 break; | 1340 break; |
15039 } | 1341 } |
15040 x; // marker | 1342 x; // marker |
15041 } | 1343 } |
15042 } | 1344 } |
15043 }'''; | 1345 }'''; |
15044 DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType; | 1346 DartType t = findMarkedIdentifier(code, "; // marker").propagatedType; |
15045 expect(typeProvider.intType.isSubtypeOf(t), isTrue); | 1347 expect(typeProvider.intType.isSubtypeOf(t), isTrue); |
15046 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); | 1348 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); |
15047 } | 1349 } |
15048 | 1350 |
15049 void fail_propagatedReturnType_functionExpression() { | 1351 void fail_propagatedReturnType_functionExpression() { |
15050 // TODO(scheglov) disabled because we don't resolve function expression | 1352 // TODO(scheglov) disabled because we don't resolve function expression |
15051 String code = r''' | 1353 String code = r''' |
15052 main() { | 1354 main() { |
15053 var v = (() {return 42;})(); | 1355 var v = (() {return 42;})(); |
15054 }'''; | 1356 }'''; |
15055 _assertPropagatedAssignedType( | 1357 assertPropagatedAssignedType( |
15056 code, typeProvider.dynamicType, typeProvider.intType); | 1358 code, typeProvider.dynamicType, typeProvider.intType); |
15057 } | 1359 } |
15058 | 1360 |
15059 void test_as() { | 1361 void test_as() { |
15060 Source source = addSource(r''' | 1362 Source source = addSource(r''' |
15061 class A { | 1363 class A { |
15062 bool get g => true; | 1364 bool get g => true; |
15063 } | 1365 } |
15064 A f(var p) { | 1366 A f(var p) { |
15065 if ((p as A).g) { | 1367 if ((p as A).g) { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15199 "/lib.dart", | 1501 "/lib.dart", |
15200 r''' | 1502 r''' |
15201 class A { | 1503 class A { |
15202 final v = 0; | 1504 final v = 0; |
15203 }'''); | 1505 }'''); |
15204 String code = r''' | 1506 String code = r''' |
15205 import 'lib.dart'; | 1507 import 'lib.dart'; |
15206 f(A a) { | 1508 f(A a) { |
15207 return a.v; // marker | 1509 return a.v; // marker |
15208 }'''; | 1510 }'''; |
15209 _assertTypeOfMarkedExpression( | 1511 assertTypeOfMarkedExpression( |
15210 code, typeProvider.dynamicType, typeProvider.intType); | 1512 code, typeProvider.dynamicType, typeProvider.intType); |
15211 } | 1513 } |
15212 | 1514 |
15213 void test_finalPropertyInducingVariable_classMember_instance_inherited() { | 1515 void test_finalPropertyInducingVariable_classMember_instance_inherited() { |
15214 addNamedSource( | 1516 addNamedSource( |
15215 "/lib.dart", | 1517 "/lib.dart", |
15216 r''' | 1518 r''' |
15217 class A { | 1519 class A { |
15218 final v = 0; | 1520 final v = 0; |
15219 }'''); | 1521 }'''); |
15220 String code = r''' | 1522 String code = r''' |
15221 import 'lib.dart'; | 1523 import 'lib.dart'; |
15222 class B extends A { | 1524 class B extends A { |
15223 m() { | 1525 m() { |
15224 return v; // marker | 1526 return v; // marker |
15225 } | 1527 } |
15226 }'''; | 1528 }'''; |
15227 _assertTypeOfMarkedExpression( | 1529 assertTypeOfMarkedExpression( |
15228 code, typeProvider.dynamicType, typeProvider.intType); | 1530 code, typeProvider.dynamicType, typeProvider.intType); |
15229 } | 1531 } |
15230 | 1532 |
15231 void | 1533 void |
15232 test_finalPropertyInducingVariable_classMember_instance_propagatedTarget()
{ | 1534 test_finalPropertyInducingVariable_classMember_instance_propagatedTarget()
{ |
15233 addNamedSource( | 1535 addNamedSource( |
15234 "/lib.dart", | 1536 "/lib.dart", |
15235 r''' | 1537 r''' |
15236 class A { | 1538 class A { |
15237 final v = 0; | 1539 final v = 0; |
15238 }'''); | 1540 }'''); |
15239 String code = r''' | 1541 String code = r''' |
15240 import 'lib.dart'; | 1542 import 'lib.dart'; |
15241 f(p) { | 1543 f(p) { |
15242 if (p is A) { | 1544 if (p is A) { |
15243 return p.v; // marker | 1545 return p.v; // marker |
15244 } | 1546 } |
15245 }'''; | 1547 }'''; |
15246 _assertTypeOfMarkedExpression( | 1548 assertTypeOfMarkedExpression( |
15247 code, typeProvider.dynamicType, typeProvider.intType); | 1549 code, typeProvider.dynamicType, typeProvider.intType); |
15248 } | 1550 } |
15249 | 1551 |
15250 void test_finalPropertyInducingVariable_classMember_instance_unprefixed() { | 1552 void test_finalPropertyInducingVariable_classMember_instance_unprefixed() { |
15251 String code = r''' | 1553 String code = r''' |
15252 class A { | 1554 class A { |
15253 final v = 0; | 1555 final v = 0; |
15254 m() { | 1556 m() { |
15255 v; // marker | 1557 v; // marker |
15256 } | 1558 } |
15257 }'''; | 1559 }'''; |
15258 _assertTypeOfMarkedExpression( | 1560 assertTypeOfMarkedExpression( |
15259 code, typeProvider.dynamicType, typeProvider.intType); | 1561 code, typeProvider.dynamicType, typeProvider.intType); |
15260 } | 1562 } |
15261 | 1563 |
15262 void test_finalPropertyInducingVariable_classMember_static() { | 1564 void test_finalPropertyInducingVariable_classMember_static() { |
15263 addNamedSource( | 1565 addNamedSource( |
15264 "/lib.dart", | 1566 "/lib.dart", |
15265 r''' | 1567 r''' |
15266 class A { | 1568 class A { |
15267 static final V = 0; | 1569 static final V = 0; |
15268 }'''); | 1570 }'''); |
15269 String code = r''' | 1571 String code = r''' |
15270 import 'lib.dart'; | 1572 import 'lib.dart'; |
15271 f() { | 1573 f() { |
15272 return A.V; // marker | 1574 return A.V; // marker |
15273 }'''; | 1575 }'''; |
15274 _assertTypeOfMarkedExpression( | 1576 assertTypeOfMarkedExpression( |
15275 code, typeProvider.dynamicType, typeProvider.intType); | 1577 code, typeProvider.dynamicType, typeProvider.intType); |
15276 } | 1578 } |
15277 | 1579 |
15278 void test_finalPropertyInducingVariable_topLevelVariable_prefixed() { | 1580 void test_finalPropertyInducingVariable_topLevelVariable_prefixed() { |
15279 addNamedSource("/lib.dart", "final V = 0;"); | 1581 addNamedSource("/lib.dart", "final V = 0;"); |
15280 String code = r''' | 1582 String code = r''' |
15281 import 'lib.dart' as p; | 1583 import 'lib.dart' as p; |
15282 f() { | 1584 f() { |
15283 var v2 = p.V; // marker prefixed | 1585 var v2 = p.V; // marker prefixed |
15284 }'''; | 1586 }'''; |
15285 _assertTypeOfMarkedExpression( | 1587 assertTypeOfMarkedExpression( |
15286 code, typeProvider.dynamicType, typeProvider.intType); | 1588 code, typeProvider.dynamicType, typeProvider.intType); |
15287 } | 1589 } |
15288 | 1590 |
15289 void test_finalPropertyInducingVariable_topLevelVariable_simple() { | 1591 void test_finalPropertyInducingVariable_topLevelVariable_simple() { |
15290 addNamedSource("/lib.dart", "final V = 0;"); | 1592 addNamedSource("/lib.dart", "final V = 0;"); |
15291 String code = r''' | 1593 String code = r''' |
15292 import 'lib.dart'; | 1594 import 'lib.dart'; |
15293 f() { | 1595 f() { |
15294 return V; // marker simple | 1596 return V; // marker simple |
15295 }'''; | 1597 }'''; |
15296 _assertTypeOfMarkedExpression( | 1598 assertTypeOfMarkedExpression( |
15297 code, typeProvider.dynamicType, typeProvider.intType); | 1599 code, typeProvider.dynamicType, typeProvider.intType); |
15298 } | 1600 } |
15299 | 1601 |
15300 void test_forEach() { | 1602 void test_forEach() { |
15301 String code = r''' | 1603 String code = r''' |
15302 main() { | 1604 main() { |
15303 var list = <String> []; | 1605 var list = <String> []; |
15304 for (var e in list) { | 1606 for (var e in list) { |
15305 e; | 1607 e; |
15306 } | 1608 } |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15723 ''' | 2025 ''' |
15724 library helper; | 2026 library helper; |
15725 int max(int x, int y) => 0; | 2027 int max(int x, int y) => 0; |
15726 '''); | 2028 '''); |
15727 String code = ''' | 2029 String code = ''' |
15728 import 'helper.dart' as helper; | 2030 import 'helper.dart' as helper; |
15729 main() { | 2031 main() { |
15730 helper.max(10, 10); // marker | 2032 helper.max(10, 10); // marker |
15731 }'''; | 2033 }'''; |
15732 SimpleIdentifier methodName = | 2034 SimpleIdentifier methodName = |
15733 _findMarkedIdentifier(code, "(10, 10); // marker"); | 2035 findMarkedIdentifier(code, "(10, 10); // marker"); |
15734 MethodInvocation methodInvoke = methodName.parent; | 2036 MethodInvocation methodInvoke = methodName.parent; |
15735 expect(methodInvoke.methodName.staticElement, isNotNull); | 2037 expect(methodInvoke.methodName.staticElement, isNotNull); |
15736 expect(methodInvoke.methodName.propagatedElement, isNull); | 2038 expect(methodInvoke.methodName.propagatedElement, isNull); |
15737 } | 2039 } |
15738 | 2040 |
15739 void test_is_conditional() { | 2041 void test_is_conditional() { |
15740 Source source = addSource(r''' | 2042 Source source = addSource(r''' |
15741 class A {} | 2043 class A {} |
15742 A f(var p) { | 2044 A f(var p) { |
15743 return (p is A) ? p : null; | 2045 return (p is A) ? p : null; |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16089 class A {} | 2391 class A {} |
16090 class B extends A {} | 2392 class B extends A {} |
16091 f() { | 2393 f() { |
16092 var a = new A(); | 2394 var a = new A(); |
16093 var b = new B(); | 2395 var b = new B(); |
16094 b; // B | 2396 b; // B |
16095 if (a is B) { | 2397 if (a is B) { |
16096 return a; // marker | 2398 return a; // marker |
16097 } | 2399 } |
16098 }'''; | 2400 }'''; |
16099 DartType tB = _findMarkedIdentifier(code, "; // B").propagatedType; | 2401 DartType tB = findMarkedIdentifier(code, "; // B").propagatedType; |
16100 _assertTypeOfMarkedExpression(code, null, tB); | 2402 assertTypeOfMarkedExpression(code, null, tB); |
16101 } | 2403 } |
16102 | 2404 |
16103 void test_issue20904BuggyTypePromotionAtIfJoin_6() { | 2405 void test_issue20904BuggyTypePromotionAtIfJoin_6() { |
16104 // https://code.google.com/p/dart/issues/detail?id=20904 | 2406 // https://code.google.com/p/dart/issues/detail?id=20904 |
16105 // | 2407 // |
16106 // The other half of the *_5() test. | 2408 // The other half of the *_5() test. |
16107 // | 2409 // |
16108 // Here the is-check loses precision, so we don't use it. | 2410 // Here the is-check loses precision, so we don't use it. |
16109 String code = r''' | 2411 String code = r''' |
16110 class A {} | 2412 class A {} |
16111 class B extends A {} | 2413 class B extends A {} |
16112 f() { | 2414 f() { |
16113 var b = new B(); | 2415 var b = new B(); |
16114 b; // B | 2416 b; // B |
16115 if (b is A) { | 2417 if (b is A) { |
16116 return b; // marker | 2418 return b; // marker |
16117 } | 2419 } |
16118 }'''; | 2420 }'''; |
16119 DartType tB = _findMarkedIdentifier(code, "; // B").propagatedType; | 2421 DartType tB = findMarkedIdentifier(code, "; // B").propagatedType; |
16120 _assertTypeOfMarkedExpression(code, null, tB); | 2422 assertTypeOfMarkedExpression(code, null, tB); |
16121 } | 2423 } |
16122 | 2424 |
16123 void test_listLiteral_different() { | 2425 void test_listLiteral_different() { |
16124 Source source = addSource(r''' | 2426 Source source = addSource(r''' |
16125 f() { | 2427 f() { |
16126 var v = [0, '1', 2]; | 2428 var v = [0, '1', 2]; |
16127 return v[2]; | 2429 return v[2]; |
16128 }'''); | 2430 }'''); |
16129 LibraryElement library = resolve2(source); | 2431 LibraryElement library = resolve2(source); |
16130 assertNoErrors(source); | 2432 assertNoErrors(source); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16211 void test_mergePropagatedTypes_afterIfThen_different() { | 2513 void test_mergePropagatedTypes_afterIfThen_different() { |
16212 String code = r''' | 2514 String code = r''' |
16213 main() { | 2515 main() { |
16214 var v = 0; | 2516 var v = 0; |
16215 if (v != null) { | 2517 if (v != null) { |
16216 v = ''; | 2518 v = ''; |
16217 } | 2519 } |
16218 return v; | 2520 return v; |
16219 }'''; | 2521 }'''; |
16220 { | 2522 { |
16221 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v;"); | 2523 SimpleIdentifier identifier = findMarkedIdentifier(code, "v;"); |
16222 expect(identifier.propagatedType, null); | 2524 expect(identifier.propagatedType, null); |
16223 } | 2525 } |
16224 { | 2526 { |
16225 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = '';"); | 2527 SimpleIdentifier identifier = findMarkedIdentifier(code, "v = '';"); |
16226 expect(identifier.propagatedType, typeProvider.stringType); | 2528 expect(identifier.propagatedType, typeProvider.stringType); |
16227 } | 2529 } |
16228 } | 2530 } |
16229 | 2531 |
16230 void test_mergePropagatedTypes_afterIfThen_same() { | 2532 void test_mergePropagatedTypes_afterIfThen_same() { |
16231 _assertTypeOfMarkedExpression( | 2533 assertTypeOfMarkedExpression( |
16232 r''' | 2534 r''' |
16233 main() { | 2535 main() { |
16234 var v = 1; | 2536 var v = 1; |
16235 if (v != null) { | 2537 if (v != null) { |
16236 v = 2; | 2538 v = 2; |
16237 } | 2539 } |
16238 return v; // marker | 2540 return v; // marker |
16239 }''', | 2541 }''', |
16240 null, | 2542 null, |
16241 typeProvider.intType); | 2543 typeProvider.intType); |
16242 } | 2544 } |
16243 | 2545 |
16244 void test_mergePropagatedTypes_afterIfThenElse_different() { | 2546 void test_mergePropagatedTypes_afterIfThenElse_different() { |
16245 _assertTypeOfMarkedExpression( | 2547 assertTypeOfMarkedExpression( |
16246 r''' | 2548 r''' |
16247 main() { | 2549 main() { |
16248 var v = 1; | 2550 var v = 1; |
16249 if (v != null) { | 2551 if (v != null) { |
16250 v = 2; | 2552 v = 2; |
16251 } else { | 2553 } else { |
16252 v = '3'; | 2554 v = '3'; |
16253 } | 2555 } |
16254 return v; // marker | 2556 return v; // marker |
16255 }''', | 2557 }''', |
16256 null, | 2558 null, |
16257 null); | 2559 null); |
16258 } | 2560 } |
16259 | 2561 |
16260 void test_mergePropagatedTypes_afterIfThenElse_same() { | 2562 void test_mergePropagatedTypes_afterIfThenElse_same() { |
16261 _assertTypeOfMarkedExpression( | 2563 assertTypeOfMarkedExpression( |
16262 r''' | 2564 r''' |
16263 main() { | 2565 main() { |
16264 var v = 1; | 2566 var v = 1; |
16265 if (v != null) { | 2567 if (v != null) { |
16266 v = 2; | 2568 v = 2; |
16267 } else { | 2569 } else { |
16268 v = 3; | 2570 v = 3; |
16269 } | 2571 } |
16270 return v; // marker | 2572 return v; // marker |
16271 }''', | 2573 }''', |
16272 null, | 2574 null, |
16273 typeProvider.intType); | 2575 typeProvider.intType); |
16274 } | 2576 } |
16275 | 2577 |
16276 void test_mergePropagatedTypesAtJoinPoint_4() { | 2578 void test_mergePropagatedTypesAtJoinPoint_4() { |
16277 // https://code.google.com/p/dart/issues/detail?id=19929 | 2579 // https://code.google.com/p/dart/issues/detail?id=19929 |
16278 _assertTypeOfMarkedExpression( | 2580 assertTypeOfMarkedExpression( |
16279 r''' | 2581 r''' |
16280 f5(x) { | 2582 f5(x) { |
16281 var y = []; | 2583 var y = []; |
16282 if (x) { | 2584 if (x) { |
16283 y = 0; | 2585 y = 0; |
16284 } else { | 2586 } else { |
16285 return y; | 2587 return y; |
16286 } | 2588 } |
16287 // Propagated type is [int] here: correct. | 2589 // Propagated type is [int] here: correct. |
16288 return y; // marker | 2590 return y; // marker |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16329 ''' | 2631 ''' |
16330 library helper; | 2632 library helper; |
16331 dynamic get $name => 42; | 2633 dynamic get $name => 42; |
16332 '''); | 2634 '''); |
16333 String code = ''' | 2635 String code = ''' |
16334 import 'helper.dart' as helper; | 2636 import 'helper.dart' as helper; |
16335 main() { | 2637 main() { |
16336 helper.$name; // marker | 2638 helper.$name; // marker |
16337 }'''; | 2639 }'''; |
16338 | 2640 |
16339 SimpleIdentifier id = _findMarkedIdentifier(code, "; // marker"); | 2641 SimpleIdentifier id = findMarkedIdentifier(code, "; // marker"); |
16340 PrefixedIdentifier prefixedId = id.parent; | 2642 PrefixedIdentifier prefixedId = id.parent; |
16341 expect(id.staticType, typeProvider.dynamicType); | 2643 expect(id.staticType, typeProvider.dynamicType); |
16342 expect(prefixedId.staticType, typeProvider.dynamicType); | 2644 expect(prefixedId.staticType, typeProvider.dynamicType); |
16343 } | 2645 } |
16344 | 2646 |
16345 void test_objectAccessInference_disabled_for_local_getter() { | 2647 void test_objectAccessInference_disabled_for_local_getter() { |
16346 String name = 'hashCode'; | 2648 String name = 'hashCode'; |
16347 String code = ''' | 2649 String code = ''' |
16348 dynamic get $name => null; | 2650 dynamic get $name => null; |
16349 main() { | 2651 main() { |
16350 $name; // marker | 2652 $name; // marker |
16351 }'''; | 2653 }'''; |
16352 | 2654 |
16353 SimpleIdentifier getter = _findMarkedIdentifier(code, "; // marker"); | 2655 SimpleIdentifier getter = findMarkedIdentifier(code, "; // marker"); |
16354 expect(getter.staticType, typeProvider.dynamicType); | 2656 expect(getter.staticType, typeProvider.dynamicType); |
16355 } | 2657 } |
16356 | 2658 |
16357 void test_objectAccessInference_enabled_for_cascades() { | 2659 void test_objectAccessInference_enabled_for_cascades() { |
16358 String name = 'hashCode'; | 2660 String name = 'hashCode'; |
16359 String code = ''' | 2661 String code = ''' |
16360 main() { | 2662 main() { |
16361 dynamic obj; | 2663 dynamic obj; |
16362 obj..$name..$name; // marker | 2664 obj..$name..$name; // marker |
16363 }'''; | 2665 }'''; |
16364 PropertyAccess access = _findMarkedIdentifier(code, "; // marker").parent; | 2666 PropertyAccess access = findMarkedIdentifier(code, "; // marker").parent; |
16365 expect(access.staticType, typeProvider.dynamicType); | 2667 expect(access.staticType, typeProvider.dynamicType); |
16366 expect(access.realTarget.staticType, typeProvider.dynamicType); | 2668 expect(access.realTarget.staticType, typeProvider.dynamicType); |
16367 } | 2669 } |
16368 | 2670 |
16369 void test_objectMethodInference_disabled_for_library_prefix() { | 2671 void test_objectMethodInference_disabled_for_library_prefix() { |
16370 String name = 'toString'; | 2672 String name = 'toString'; |
16371 addNamedSource( | 2673 addNamedSource( |
16372 '/helper.dart', | 2674 '/helper.dart', |
16373 ''' | 2675 ''' |
16374 library helper; | 2676 library helper; |
16375 dynamic $name = (int x) => x + 42'); | 2677 dynamic $name = (int x) => x + 42'); |
16376 '''); | 2678 '''); |
16377 String code = ''' | 2679 String code = ''' |
16378 import 'helper.dart' as helper; | 2680 import 'helper.dart' as helper; |
16379 main() { | 2681 main() { |
16380 helper.$name(); // marker | 2682 helper.$name(); // marker |
16381 }'''; | 2683 }'''; |
16382 SimpleIdentifier methodName = _findMarkedIdentifier(code, "(); // marker"); | 2684 SimpleIdentifier methodName = findMarkedIdentifier(code, "(); // marker"); |
16383 MethodInvocation methodInvoke = methodName.parent; | 2685 MethodInvocation methodInvoke = methodName.parent; |
16384 expect(methodName.staticType, typeProvider.dynamicType); | 2686 expect(methodName.staticType, typeProvider.dynamicType); |
16385 expect(methodInvoke.staticType, typeProvider.dynamicType); | 2687 expect(methodInvoke.staticType, typeProvider.dynamicType); |
16386 } | 2688 } |
16387 | 2689 |
16388 void test_objectMethodInference_disabled_for_local_function() { | 2690 void test_objectMethodInference_disabled_for_local_function() { |
16389 String name = 'toString'; | 2691 String name = 'toString'; |
16390 String code = ''' | 2692 String code = ''' |
16391 main() { | 2693 main() { |
16392 dynamic $name = () => null; | 2694 dynamic $name = () => null; |
16393 $name(); // marker | 2695 $name(); // marker |
16394 }'''; | 2696 }'''; |
16395 SimpleIdentifier identifier = _findMarkedIdentifier(code, "$name = "); | 2697 SimpleIdentifier identifier = findMarkedIdentifier(code, "$name = "); |
16396 expect(identifier.staticType, typeProvider.dynamicType); | 2698 expect(identifier.staticType, typeProvider.dynamicType); |
16397 | 2699 |
16398 SimpleIdentifier methodName = _findMarkedIdentifier(code, "(); // marker"); | 2700 SimpleIdentifier methodName = findMarkedIdentifier(code, "(); // marker"); |
16399 MethodInvocation methodInvoke = methodName.parent; | 2701 MethodInvocation methodInvoke = methodName.parent; |
16400 expect(methodName.staticType, typeProvider.dynamicType); | 2702 expect(methodName.staticType, typeProvider.dynamicType); |
16401 expect(methodInvoke.staticType, typeProvider.dynamicType); | 2703 expect(methodInvoke.staticType, typeProvider.dynamicType); |
16402 } | 2704 } |
16403 | 2705 |
16404 void test_objectMethodInference_enabled_for_cascades() { | 2706 void test_objectMethodInference_enabled_for_cascades() { |
16405 String name = 'toString'; | 2707 String name = 'toString'; |
16406 String code = ''' | 2708 String code = ''' |
16407 main() { | 2709 main() { |
16408 dynamic obj; | 2710 dynamic obj; |
16409 obj..$name()..$name(); // marker | 2711 obj..$name()..$name(); // marker |
16410 }'''; | 2712 }'''; |
16411 SimpleIdentifier methodName = _findMarkedIdentifier(code, "(); // marker"); | 2713 SimpleIdentifier methodName = findMarkedIdentifier(code, "(); // marker"); |
16412 MethodInvocation methodInvoke = methodName.parent; | 2714 MethodInvocation methodInvoke = methodName.parent; |
16413 | 2715 |
16414 expect(methodInvoke.staticType, typeProvider.dynamicType); | 2716 expect(methodInvoke.staticType, typeProvider.dynamicType); |
16415 expect(methodInvoke.realTarget.staticType, typeProvider.dynamicType); | 2717 expect(methodInvoke.realTarget.staticType, typeProvider.dynamicType); |
16416 } | 2718 } |
16417 | 2719 |
16418 void test_objectMethodOnDynamicExpression_doubleEquals() { | 2720 void test_objectMethodOnDynamicExpression_doubleEquals() { |
16419 // https://code.google.com/p/dart/issues/detail?id=20342 | 2721 // https://code.google.com/p/dart/issues/detail?id=20342 |
16420 // | 2722 // |
16421 // This was not actually part of Issue 20342, since the spec specifies a | 2723 // This was not actually part of Issue 20342, since the spec specifies a |
16422 // static type of [bool] for [==] comparison and the implementation | 2724 // static type of [bool] for [==] comparison and the implementation |
16423 // was already consistent with the spec there. But, it's another | 2725 // was already consistent with the spec there. But, it's another |
16424 // [Object] method, so it's included here. | 2726 // [Object] method, so it's included here. |
16425 _assertTypeOfMarkedExpression( | 2727 assertTypeOfMarkedExpression( |
16426 r''' | 2728 r''' |
16427 f1(x) { | 2729 f1(x) { |
16428 var v = (x == x); | 2730 var v = (x == x); |
16429 return v; // marker | 2731 return v; // marker |
16430 }''', | 2732 }''', |
16431 null, | 2733 null, |
16432 typeProvider.boolType); | 2734 typeProvider.boolType); |
16433 } | 2735 } |
16434 | 2736 |
16435 void test_objectMethodOnDynamicExpression_hashCode() { | 2737 void test_objectMethodOnDynamicExpression_hashCode() { |
16436 // https://code.google.com/p/dart/issues/detail?id=20342 | 2738 // https://code.google.com/p/dart/issues/detail?id=20342 |
16437 _assertTypeOfMarkedExpression( | 2739 assertTypeOfMarkedExpression( |
16438 r''' | 2740 r''' |
16439 f1(x) { | 2741 f1(x) { |
16440 var v = x.hashCode; | 2742 var v = x.hashCode; |
16441 return v; // marker | 2743 return v; // marker |
16442 }''', | 2744 }''', |
16443 null, | 2745 null, |
16444 typeProvider.intType); | 2746 typeProvider.intType); |
16445 } | 2747 } |
16446 | 2748 |
16447 void test_objectMethodOnDynamicExpression_runtimeType() { | 2749 void test_objectMethodOnDynamicExpression_runtimeType() { |
16448 // https://code.google.com/p/dart/issues/detail?id=20342 | 2750 // https://code.google.com/p/dart/issues/detail?id=20342 |
16449 _assertTypeOfMarkedExpression( | 2751 assertTypeOfMarkedExpression( |
16450 r''' | 2752 r''' |
16451 f1(x) { | 2753 f1(x) { |
16452 var v = x.runtimeType; | 2754 var v = x.runtimeType; |
16453 return v; // marker | 2755 return v; // marker |
16454 }''', | 2756 }''', |
16455 null, | 2757 null, |
16456 typeProvider.typeType); | 2758 typeProvider.typeType); |
16457 } | 2759 } |
16458 | 2760 |
16459 void test_objectMethodOnDynamicExpression_toString() { | 2761 void test_objectMethodOnDynamicExpression_toString() { |
16460 // https://code.google.com/p/dart/issues/detail?id=20342 | 2762 // https://code.google.com/p/dart/issues/detail?id=20342 |
16461 _assertTypeOfMarkedExpression( | 2763 assertTypeOfMarkedExpression( |
16462 r''' | 2764 r''' |
16463 f1(x) { | 2765 f1(x) { |
16464 var v = x.toString(); | 2766 var v = x.toString(); |
16465 return v; // marker | 2767 return v; // marker |
16466 }''', | 2768 }''', |
16467 null, | 2769 null, |
16468 typeProvider.stringType); | 2770 typeProvider.stringType); |
16469 } | 2771 } |
16470 | 2772 |
16471 void test_propagatedReturnType_localFunction() { | 2773 void test_propagatedReturnType_localFunction() { |
16472 String code = r''' | 2774 String code = r''' |
16473 main() { | 2775 main() { |
16474 f() => 42; | 2776 f() => 42; |
16475 var v = f(); | 2777 var v = f(); |
16476 }'''; | 2778 }'''; |
16477 _assertPropagatedAssignedType( | 2779 assertPropagatedAssignedType( |
16478 code, typeProvider.dynamicType, typeProvider.intType); | 2780 code, typeProvider.dynamicType, typeProvider.intType); |
16479 } | 2781 } |
16480 | 2782 |
16481 void test_query() { | 2783 void test_query() { |
16482 Source source = addSource(r''' | 2784 Source source = addSource(r''' |
16483 import 'dart:html'; | 2785 import 'dart:html'; |
16484 | 2786 |
16485 main() { | 2787 main() { |
16486 var v1 = query('a'); | 2788 var v1 = query('a'); |
16487 var v2 = query('A'); | 2789 var v2 = query('A'); |
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17331 void _resolveNode(AstNode node, [List<Element> definedElements]) { | 3633 void _resolveNode(AstNode node, [List<Element> definedElements]) { |
17332 if (definedElements != null) { | 3634 if (definedElements != null) { |
17333 for (Element element in definedElements) { | 3635 for (Element element in definedElements) { |
17334 libraryScope.define(element); | 3636 libraryScope.define(element); |
17335 } | 3637 } |
17336 } | 3638 } |
17337 node.accept(_visitor); | 3639 node.accept(_visitor); |
17338 } | 3640 } |
17339 } | 3641 } |
17340 | 3642 |
17341 class _AnalysisContextFactory_initContextWithCore | |
17342 extends DirectoryBasedDartSdk { | |
17343 final bool enableAsync; | |
17344 _AnalysisContextFactory_initContextWithCore(JavaFile arg0, | |
17345 {this.enableAsync: true}) | |
17346 : super(arg0); | |
17347 | |
17348 @override | |
17349 LibraryMap initialLibraryMap(bool useDart2jsPaths) { | |
17350 LibraryMap map = new LibraryMap(); | |
17351 if (enableAsync) { | |
17352 _addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart"); | |
17353 } | |
17354 _addLibrary(map, DartSdk.DART_CORE, false, "core.dart"); | |
17355 _addLibrary(map, DartSdk.DART_HTML, false, "html_dartium.dart"); | |
17356 _addLibrary(map, AnalysisContextFactory._DART_MATH, false, "math.dart"); | |
17357 _addLibrary(map, AnalysisContextFactory._DART_INTERCEPTORS, true, | |
17358 "_interceptors.dart"); | |
17359 _addLibrary( | |
17360 map, AnalysisContextFactory._DART_JS_HELPER, true, "_js_helper.dart"); | |
17361 return map; | |
17362 } | |
17363 | |
17364 void _addLibrary(LibraryMap map, String uri, bool isInternal, String path) { | |
17365 SdkLibraryImpl library = new SdkLibraryImpl(uri); | |
17366 if (isInternal) { | |
17367 library.category = "Internal"; | |
17368 } | |
17369 library.path = path; | |
17370 map.setLibrary(uri, library); | |
17371 } | |
17372 } | |
17373 | |
17374 class _SimpleResolverTest_localVariable_types_invoked | |
17375 extends RecursiveAstVisitor<Object> { | |
17376 final SimpleResolverTest test; | |
17377 | |
17378 List<bool> found; | |
17379 | |
17380 List<CaughtException> thrownException; | |
17381 | |
17382 _SimpleResolverTest_localVariable_types_invoked( | |
17383 this.test, this.found, this.thrownException) | |
17384 : super(); | |
17385 | |
17386 @override | |
17387 Object visitSimpleIdentifier(SimpleIdentifier node) { | |
17388 if (node.name == "myVar" && node.parent is MethodInvocation) { | |
17389 try { | |
17390 found[0] = true; | |
17391 // check static type | |
17392 DartType staticType = node.staticType; | |
17393 expect(staticType, same(test.typeProvider.dynamicType)); | |
17394 // check propagated type | |
17395 FunctionType propagatedType = node.propagatedType as FunctionType; | |
17396 expect(propagatedType.returnType, test.typeProvider.stringType); | |
17397 } on AnalysisException catch (e, stackTrace) { | |
17398 thrownException[0] = new CaughtException(e, stackTrace); | |
17399 } | |
17400 } | |
17401 return null; | |
17402 } | |
17403 } | |
17404 | |
17405 /** | 3643 /** |
17406 * Represents an element left over from a previous resolver run. | 3644 * Represents an element left over from a previous resolver run. |
17407 * | 3645 * |
17408 * A _StaleElement should always be replaced with either null or a new Element. | 3646 * A _StaleElement should always be replaced with either null or a new Element. |
17409 */ | 3647 */ |
17410 class _StaleElement extends ElementImpl { | 3648 class _StaleElement extends ElementImpl { |
17411 _StaleElement() : super("_StaleElement", -1); | 3649 _StaleElement() : super("_StaleElement", -1); |
17412 | 3650 |
17413 @override | 3651 @override |
17414 get kind => throw "_StaleElement's kind shouldn't be accessed"; | 3652 get kind => throw "_StaleElement's kind shouldn't be accessed"; |
17415 | 3653 |
17416 @override | 3654 @override |
17417 accept(_) => throw "_StaleElement shouldn't be visited"; | 3655 accept(_) => throw "_StaleElement shouldn't be visited"; |
17418 } | 3656 } |
17419 | |
17420 /** | |
17421 * Shared infrastructure for [StaticTypeAnalyzer2Test] and | |
17422 * [StrongModeStaticTypeAnalyzer2Test]. | |
17423 */ | |
17424 class _StaticTypeAnalyzer2TestShared extends ResolverTestCase { | |
17425 String testCode; | |
17426 Source testSource; | |
17427 CompilationUnit testUnit; | |
17428 | |
17429 /** | |
17430 * Looks up the identifier with [name] and validates that its type type | |
17431 * stringifies to [type] and that its generics match the given stringified | |
17432 * output. | |
17433 */ | |
17434 _expectFunctionType(String name, String type, | |
17435 {String elementTypeParams: '[]', | |
17436 String typeParams: '[]', | |
17437 String typeArgs: '[]', | |
17438 String typeFormals: '[]'}) { | |
17439 SimpleIdentifier identifier = _findIdentifier(name); | |
17440 // Element is either ExecutableElement or ParameterElement. | |
17441 var element = identifier.staticElement; | |
17442 FunctionTypeImpl functionType = identifier.staticType; | |
17443 expect(functionType.toString(), type); | |
17444 expect(element.typeParameters.toString(), elementTypeParams); | |
17445 expect(functionType.typeParameters.toString(), typeParams); | |
17446 expect(functionType.typeArguments.toString(), typeArgs); | |
17447 expect(functionType.typeFormals.toString(), typeFormals); | |
17448 } | |
17449 | |
17450 /** | |
17451 * Looks up the identifier with [name] and validates its static [type]. | |
17452 * | |
17453 * If [type] is a string, validates that the identifier's static type | |
17454 * stringifies to that text. Otherwise, [type] is used directly a [Matcher] | |
17455 * to match the type. | |
17456 * | |
17457 * If [propagatedType] is given, also validate's the identifier's propagated | |
17458 * type. | |
17459 */ | |
17460 void _expectIdentifierType(String name, type, [propagatedType]) { | |
17461 SimpleIdentifier identifier = _findIdentifier(name); | |
17462 _expectType(identifier.staticType, type); | |
17463 if (propagatedType != null) { | |
17464 _expectType(identifier.propagatedType, propagatedType); | |
17465 } | |
17466 } | |
17467 | |
17468 /** | |
17469 * Looks up the initializer for the declaration containing [identifier] and | |
17470 * validates its static [type]. | |
17471 * | |
17472 * If [type] is a string, validates that the identifier's static type | |
17473 * stringifies to that text. Otherwise, [type] is used directly a [Matcher] | |
17474 * to match the type. | |
17475 * | |
17476 * If [propagatedType] is given, also validate's the identifier's propagated | |
17477 * type. | |
17478 */ | |
17479 void _expectInitializerType(String name, type, [propagatedType]) { | |
17480 SimpleIdentifier identifier = _findIdentifier(name); | |
17481 VariableDeclaration declaration = | |
17482 identifier.getAncestor((node) => node is VariableDeclaration); | |
17483 Expression initializer = declaration.initializer; | |
17484 _expectType(initializer.staticType, type); | |
17485 if (propagatedType != null) { | |
17486 _expectType(initializer.propagatedType, propagatedType); | |
17487 } | |
17488 } | |
17489 | |
17490 /** | |
17491 * Validates that [type] matches [expected]. | |
17492 * | |
17493 * If [expected] is a string, validates that the type stringifies to that | |
17494 * text. Otherwise, [expected] is used directly a [Matcher] to match the type. | |
17495 */ | |
17496 _expectType(DartType type, expected) { | |
17497 if (expected is String) { | |
17498 expect(type.toString(), expected); | |
17499 } else { | |
17500 expect(type, expected); | |
17501 } | |
17502 } | |
17503 | |
17504 SimpleIdentifier _findIdentifier(String search) { | |
17505 SimpleIdentifier identifier = EngineTestCase.findNode( | |
17506 testUnit, testCode, search, (node) => node is SimpleIdentifier); | |
17507 return identifier; | |
17508 } | |
17509 | |
17510 void _resolveTestUnit(String code) { | |
17511 testCode = code; | |
17512 testSource = addSource(testCode); | |
17513 LibraryElement library = resolve2(testSource); | |
17514 assertNoErrors(testSource); | |
17515 verify([testSource]); | |
17516 testUnit = resolveCompilationUnit(testSource, library); | |
17517 } | |
17518 } | |
OLD | NEW |