OLD | NEW |
(Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library engine.resolver_test; |
| 6 |
| 7 import 'dart:collection'; |
| 8 |
| 9 import 'package:analyzer/src/context/context.dart' as newContext; |
| 10 import 'package:analyzer/src/generated/ast.dart'; |
| 11 import 'package:analyzer/src/generated/element.dart'; |
| 12 import 'package:analyzer/src/generated/element_resolver.dart'; |
| 13 import 'package:analyzer/src/generated/engine.dart'; |
| 14 import 'package:analyzer/src/generated/error.dart'; |
| 15 import 'package:analyzer/src/generated/java_core.dart'; |
| 16 import 'package:analyzer/src/generated/java_engine.dart'; |
| 17 import 'package:analyzer/src/generated/java_engine_io.dart'; |
| 18 import 'package:analyzer/src/generated/java_io.dart'; |
| 19 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode; |
| 20 import 'package:analyzer/src/generated/resolver.dart'; |
| 21 import 'package:analyzer/src/generated/scanner.dart'; |
| 22 import 'package:analyzer/src/generated/sdk.dart'; |
| 23 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk; |
| 24 import 'package:analyzer/src/generated/source_io.dart'; |
| 25 import 'package:analyzer/src/generated/static_type_analyzer.dart'; |
| 26 import 'package:analyzer/src/generated/testing/ast_factory.dart'; |
| 27 import 'package:analyzer/src/generated/testing/element_factory.dart'; |
| 28 import 'package:analyzer/src/generated/testing/test_type_provider.dart'; |
| 29 import 'package:analyzer/src/generated/testing/token_factory.dart'; |
| 30 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 31 import 'package:unittest/unittest.dart'; |
| 32 |
| 33 import '../reflective_tests.dart'; |
| 34 import '../utils.dart'; |
| 35 import 'test_support.dart'; |
| 36 |
| 37 main() { |
| 38 initializeTestEnvironment(); |
| 39 runReflectiveTests(AnalysisDeltaTest); |
| 40 runReflectiveTests(ChangeSetTest); |
| 41 runReflectiveTests(EnclosedScopeTest); |
| 42 runReflectiveTests(LibraryImportScopeTest); |
| 43 runReflectiveTests(LibraryScopeTest); |
| 44 runReflectiveTests(ScopeTest); |
| 45 runReflectiveTests(ElementResolverTest); |
| 46 runReflectiveTests(InheritanceManagerTest); |
| 47 if (!AnalysisEngine.instance.useTaskModel) { |
| 48 runReflectiveTests(LibraryElementBuilderTest); |
| 49 } |
| 50 if (!AnalysisEngine.instance.useTaskModel) { |
| 51 runReflectiveTests(LibraryResolver2Test); |
| 52 } |
| 53 if (!AnalysisEngine.instance.useTaskModel) { |
| 54 runReflectiveTests(LibraryResolverTest); |
| 55 } |
| 56 runReflectiveTests(LibraryTest); |
| 57 runReflectiveTests(StaticTypeAnalyzerTest); |
| 58 runReflectiveTests(StaticTypeAnalyzer2Test); |
| 59 runReflectiveTests(SubtypeManagerTest); |
| 60 runReflectiveTests(TypeOverrideManagerTest); |
| 61 runReflectiveTests(TypeProviderImplTest); |
| 62 runReflectiveTests(TypeResolverVisitorTest); |
| 63 runReflectiveTests(CheckedModeCompileTimeErrorCodeTest); |
| 64 runReflectiveTests(ErrorResolverTest); |
| 65 runReflectiveTests(HintCodeTest); |
| 66 runReflectiveTests(MemberMapTest); |
| 67 runReflectiveTests(NonHintCodeTest); |
| 68 runReflectiveTests(SimpleResolverTest); |
| 69 runReflectiveTests(StrictModeTest); |
| 70 runReflectiveTests(TypePropagationTest); |
| 71 runReflectiveTests(StrongModeStaticTypeAnalyzer2Test); |
| 72 runReflectiveTests(StrongModeTypePropagationTest); |
| 73 } |
| 74 |
| 75 /** |
| 76 * The class `AnalysisContextFactory` defines utility methods used to create ana
lysis contexts |
| 77 * for testing purposes. |
| 78 */ |
| 79 class AnalysisContextFactory { |
| 80 static String _DART_MATH = "dart:math"; |
| 81 |
| 82 static String _DART_INTERCEPTORS = "dart:_interceptors"; |
| 83 |
| 84 static String _DART_JS_HELPER = "dart:_js_helper"; |
| 85 |
| 86 /** |
| 87 * Create an analysis context that has a fake core library already resolved. |
| 88 * Return the context that was created. |
| 89 */ |
| 90 static InternalAnalysisContext contextWithCore() { |
| 91 if (AnalysisEngine.instance.useTaskModel) { |
| 92 NewAnalysisContextForTests context = new NewAnalysisContextForTests(); |
| 93 return initContextWithCore(context); |
| 94 } |
| 95 AnalysisContextForTests context = new AnalysisContextForTests(); |
| 96 return initContextWithCore(context); |
| 97 } |
| 98 |
| 99 /** |
| 100 * Create an analysis context that uses the given [options] and has a fake |
| 101 * core library already resolved. Return the context that was created. |
| 102 */ |
| 103 static InternalAnalysisContext contextWithCoreAndOptions( |
| 104 AnalysisOptions options) { |
| 105 if (AnalysisEngine.instance.useTaskModel) { |
| 106 NewAnalysisContextForTests context = new NewAnalysisContextForTests(); |
| 107 context._internalSetAnalysisOptions(options); |
| 108 return initContextWithCore(context); |
| 109 } |
| 110 AnalysisContextForTests context = new AnalysisContextForTests(); |
| 111 context._internalSetAnalysisOptions(options); |
| 112 return initContextWithCore(context); |
| 113 } |
| 114 |
| 115 /** |
| 116 * Initialize the given analysis context with a fake core library already reso
lved. |
| 117 * |
| 118 * @param context the context to be initialized (not `null`) |
| 119 * @return the analysis context that was created |
| 120 */ |
| 121 static InternalAnalysisContext initContextWithCore( |
| 122 InternalAnalysisContext context) { |
| 123 DirectoryBasedDartSdk sdk = new _AnalysisContextFactory_initContextWithCore( |
| 124 new JavaFile("/fake/sdk")); |
| 125 SourceFactory sourceFactory = |
| 126 new SourceFactory([new DartUriResolver(sdk), new FileUriResolver()]); |
| 127 context.sourceFactory = sourceFactory; |
| 128 AnalysisContext coreContext = sdk.context; |
| 129 // |
| 130 // dart:core |
| 131 // |
| 132 TestTypeProvider provider = new TestTypeProvider(); |
| 133 CompilationUnitElementImpl coreUnit = |
| 134 new CompilationUnitElementImpl("core.dart"); |
| 135 Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE); |
| 136 coreContext.setContents(coreSource, ""); |
| 137 coreUnit.librarySource = coreUnit.source = coreSource; |
| 138 ClassElementImpl proxyClassElement = ElementFactory.classElement2("_Proxy"); |
| 139 ClassElement objectClassElement = provider.objectType.element; |
| 140 coreUnit.types = <ClassElement>[ |
| 141 provider.boolType.element, |
| 142 provider.deprecatedType.element, |
| 143 provider.doubleType.element, |
| 144 provider.functionType.element, |
| 145 provider.intType.element, |
| 146 provider.iterableType.element, |
| 147 provider.iteratorType.element, |
| 148 provider.listType.element, |
| 149 provider.mapType.element, |
| 150 provider.nullType.element, |
| 151 provider.numType.element, |
| 152 objectClassElement, |
| 153 proxyClassElement, |
| 154 provider.stackTraceType.element, |
| 155 provider.stringType.element, |
| 156 provider.symbolType.element, |
| 157 provider.typeType.element |
| 158 ]; |
| 159 coreUnit.functions = <FunctionElement>[ |
| 160 ElementFactory.functionElement3("identical", provider.boolType.element, |
| 161 <ClassElement>[objectClassElement, objectClassElement], null), |
| 162 ElementFactory.functionElement3("print", VoidTypeImpl.instance.element, |
| 163 <ClassElement>[objectClassElement], null) |
| 164 ]; |
| 165 TopLevelVariableElement proxyTopLevelVariableElt = ElementFactory |
| 166 .topLevelVariableElement3("proxy", true, false, proxyClassElement.type); |
| 167 ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt = |
| 168 ElementFactory.topLevelVariableElement3( |
| 169 "deprecated", true, false, provider.deprecatedType); |
| 170 deprecatedTopLevelVariableElt.constantInitializer = AstFactory |
| 171 .instanceCreationExpression2( |
| 172 Keyword.CONST, |
| 173 AstFactory.typeName(provider.deprecatedType.element), |
| 174 [AstFactory.string2('next release')]); |
| 175 coreUnit.accessors = <PropertyAccessorElement>[ |
| 176 proxyTopLevelVariableElt.getter, |
| 177 deprecatedTopLevelVariableElt.getter |
| 178 ]; |
| 179 coreUnit.topLevelVariables = <TopLevelVariableElement>[ |
| 180 proxyTopLevelVariableElt, |
| 181 deprecatedTopLevelVariableElt |
| 182 ]; |
| 183 LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode( |
| 184 coreContext, AstFactory.libraryIdentifier2(["dart", "core"])); |
| 185 coreLibrary.definingCompilationUnit = coreUnit; |
| 186 // |
| 187 // dart:async |
| 188 // |
| 189 CompilationUnitElementImpl asyncUnit = |
| 190 new CompilationUnitElementImpl("async.dart"); |
| 191 Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC); |
| 192 coreContext.setContents(asyncSource, ""); |
| 193 asyncUnit.librarySource = asyncUnit.source = asyncSource; |
| 194 // Future |
| 195 ClassElementImpl futureElement = |
| 196 ElementFactory.classElement2("Future", ["T"]); |
| 197 // factory Future.value([value]) |
| 198 ConstructorElementImpl futureConstructor = |
| 199 ElementFactory.constructorElement2(futureElement, "value"); |
| 200 futureConstructor.parameters = <ParameterElement>[ |
| 201 ElementFactory.positionalParameter2("value", provider.dynamicType) |
| 202 ]; |
| 203 futureConstructor.factory = true; |
| 204 (futureConstructor.type as FunctionTypeImpl).typeArguments = |
| 205 futureElement.type.typeArguments; |
| 206 futureElement.constructors = <ConstructorElement>[futureConstructor]; |
| 207 // Future then(onValue(T value), { Function onError }); |
| 208 List<ParameterElement> parameters = <ParameterElement>[ |
| 209 ElementFactory.requiredParameter2( |
| 210 "value", futureElement.typeParameters[0].type) |
| 211 ]; |
| 212 FunctionTypeAliasElementImpl aliasElement = |
| 213 new FunctionTypeAliasElementImpl.forNode(null); |
| 214 aliasElement.synthetic = true; |
| 215 aliasElement.parameters = parameters; |
| 216 aliasElement.returnType = provider.dynamicType; |
| 217 aliasElement.enclosingElement = asyncUnit; |
| 218 FunctionTypeImpl aliasType = new FunctionTypeImpl.forTypedef(aliasElement); |
| 219 aliasElement.shareTypeParameters(futureElement.typeParameters); |
| 220 aliasType.typeArguments = futureElement.type.typeArguments; |
| 221 DartType futureDynamicType = |
| 222 futureElement.type.substitute4([provider.dynamicType]); |
| 223 MethodElement thenMethod = ElementFactory.methodElementWithParameters( |
| 224 "then", futureElement.type.typeArguments, futureDynamicType, [ |
| 225 ElementFactory.requiredParameter2("onValue", aliasType), |
| 226 ElementFactory.namedParameter2("onError", provider.functionType) |
| 227 ]); |
| 228 futureElement.methods = <MethodElement>[thenMethod]; |
| 229 // Completer |
| 230 ClassElementImpl completerElement = |
| 231 ElementFactory.classElement2("Completer", ["T"]); |
| 232 ConstructorElementImpl completerConstructor = |
| 233 ElementFactory.constructorElement2(completerElement, null); |
| 234 (completerConstructor.type as FunctionTypeImpl).typeArguments = |
| 235 completerElement.type.typeArguments; |
| 236 completerElement.constructors = <ConstructorElement>[completerConstructor]; |
| 237 // StreamSubscription |
| 238 ClassElementImpl streamSubscriptionElement = |
| 239 ElementFactory.classElement2("StreamSubscription", ["T"]); |
| 240 // Stream |
| 241 ClassElementImpl streamElement = |
| 242 ElementFactory.classElement2("Stream", ["T"]); |
| 243 streamElement.constructors = <ConstructorElement>[ |
| 244 ElementFactory.constructorElement2(streamElement, null) |
| 245 ]; |
| 246 DartType returnType = streamSubscriptionElement.type |
| 247 .substitute4(streamElement.type.typeArguments); |
| 248 List<DartType> parameterTypes = <DartType>[ |
| 249 ElementFactory |
| 250 .functionElement3('onData', VoidTypeImpl.instance.element, |
| 251 <TypeDefiningElement>[streamElement.typeParameters[0]], null) |
| 252 .type, |
| 253 ]; |
| 254 // TODO(brianwilkerson) This is missing the optional parameters. |
| 255 MethodElementImpl listenMethod = |
| 256 ElementFactory.methodElement('listen', returnType, parameterTypes); |
| 257 streamElement.methods = <MethodElement>[listenMethod]; |
| 258 |
| 259 asyncUnit.types = <ClassElement>[ |
| 260 completerElement, |
| 261 futureElement, |
| 262 streamElement |
| 263 ]; |
| 264 LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode( |
| 265 coreContext, AstFactory.libraryIdentifier2(["dart", "async"])); |
| 266 asyncLibrary.definingCompilationUnit = asyncUnit; |
| 267 // |
| 268 // dart:html |
| 269 // |
| 270 CompilationUnitElementImpl htmlUnit = |
| 271 new CompilationUnitElementImpl("html_dartium.dart"); |
| 272 Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML); |
| 273 coreContext.setContents(htmlSource, ""); |
| 274 htmlUnit.librarySource = htmlUnit.source = htmlSource; |
| 275 ClassElementImpl elementElement = ElementFactory.classElement2("Element"); |
| 276 InterfaceType elementType = elementElement.type; |
| 277 ClassElementImpl canvasElement = |
| 278 ElementFactory.classElement("CanvasElement", elementType); |
| 279 ClassElementImpl contextElement = |
| 280 ElementFactory.classElement2("CanvasRenderingContext"); |
| 281 InterfaceType contextElementType = contextElement.type; |
| 282 ClassElementImpl context2dElement = ElementFactory.classElement( |
| 283 "CanvasRenderingContext2D", contextElementType); |
| 284 canvasElement.methods = <MethodElement>[ |
| 285 ElementFactory.methodElement( |
| 286 "getContext", contextElementType, [provider.stringType]) |
| 287 ]; |
| 288 canvasElement.accessors = <PropertyAccessorElement>[ |
| 289 ElementFactory.getterElement("context2D", false, context2dElement.type) |
| 290 ]; |
| 291 canvasElement.fields = canvasElement.accessors |
| 292 .map((PropertyAccessorElement accessor) => accessor.variable) |
| 293 .toList(); |
| 294 ClassElementImpl documentElement = |
| 295 ElementFactory.classElement("Document", elementType); |
| 296 ClassElementImpl htmlDocumentElement = |
| 297 ElementFactory.classElement("HtmlDocument", documentElement.type); |
| 298 htmlDocumentElement.methods = <MethodElement>[ |
| 299 ElementFactory.methodElement( |
| 300 "query", elementType, <DartType>[provider.stringType]) |
| 301 ]; |
| 302 htmlUnit.types = <ClassElement>[ |
| 303 ElementFactory.classElement("AnchorElement", elementType), |
| 304 ElementFactory.classElement("BodyElement", elementType), |
| 305 ElementFactory.classElement("ButtonElement", elementType), |
| 306 canvasElement, |
| 307 contextElement, |
| 308 context2dElement, |
| 309 ElementFactory.classElement("DivElement", elementType), |
| 310 documentElement, |
| 311 elementElement, |
| 312 htmlDocumentElement, |
| 313 ElementFactory.classElement("InputElement", elementType), |
| 314 ElementFactory.classElement("SelectElement", elementType) |
| 315 ]; |
| 316 htmlUnit.functions = <FunctionElement>[ |
| 317 ElementFactory.functionElement3("query", elementElement, |
| 318 <ClassElement>[provider.stringType.element], ClassElement.EMPTY_LIST) |
| 319 ]; |
| 320 TopLevelVariableElementImpl document = ElementFactory |
| 321 .topLevelVariableElement3( |
| 322 "document", false, true, htmlDocumentElement.type); |
| 323 htmlUnit.topLevelVariables = <TopLevelVariableElement>[document]; |
| 324 htmlUnit.accessors = <PropertyAccessorElement>[document.getter]; |
| 325 LibraryElementImpl htmlLibrary = new LibraryElementImpl.forNode( |
| 326 coreContext, AstFactory.libraryIdentifier2(["dart", "dom", "html"])); |
| 327 htmlLibrary.definingCompilationUnit = htmlUnit; |
| 328 // |
| 329 // dart:math |
| 330 // |
| 331 CompilationUnitElementImpl mathUnit = |
| 332 new CompilationUnitElementImpl("math.dart"); |
| 333 Source mathSource = sourceFactory.forUri(_DART_MATH); |
| 334 coreContext.setContents(mathSource, ""); |
| 335 mathUnit.librarySource = mathUnit.source = mathSource; |
| 336 FunctionElement cosElement = ElementFactory.functionElement3( |
| 337 "cos", |
| 338 provider.doubleType.element, |
| 339 <ClassElement>[provider.numType.element], |
| 340 ClassElement.EMPTY_LIST); |
| 341 TopLevelVariableElement ln10Element = ElementFactory |
| 342 .topLevelVariableElement3("LN10", true, false, provider.doubleType); |
| 343 FunctionElement maxElement = ElementFactory.functionElement3( |
| 344 "max", |
| 345 provider.numType.element, |
| 346 <ClassElement>[provider.numType.element, provider.numType.element], |
| 347 ClassElement.EMPTY_LIST); |
| 348 TopLevelVariableElement piElement = ElementFactory.topLevelVariableElement3( |
| 349 "PI", true, false, provider.doubleType); |
| 350 ClassElementImpl randomElement = ElementFactory.classElement2("Random"); |
| 351 randomElement.abstract = true; |
| 352 ConstructorElementImpl randomConstructor = |
| 353 ElementFactory.constructorElement2(randomElement, null); |
| 354 randomConstructor.factory = true; |
| 355 ParameterElementImpl seedParam = new ParameterElementImpl("seed", 0); |
| 356 seedParam.parameterKind = ParameterKind.POSITIONAL; |
| 357 seedParam.type = provider.intType; |
| 358 randomConstructor.parameters = <ParameterElement>[seedParam]; |
| 359 randomElement.constructors = <ConstructorElement>[randomConstructor]; |
| 360 FunctionElement sinElement = ElementFactory.functionElement3( |
| 361 "sin", |
| 362 provider.doubleType.element, |
| 363 <ClassElement>[provider.numType.element], |
| 364 ClassElement.EMPTY_LIST); |
| 365 FunctionElement sqrtElement = ElementFactory.functionElement3( |
| 366 "sqrt", |
| 367 provider.doubleType.element, |
| 368 <ClassElement>[provider.numType.element], |
| 369 ClassElement.EMPTY_LIST); |
| 370 mathUnit.accessors = <PropertyAccessorElement>[ |
| 371 ln10Element.getter, |
| 372 piElement.getter |
| 373 ]; |
| 374 mathUnit.functions = <FunctionElement>[ |
| 375 cosElement, |
| 376 maxElement, |
| 377 sinElement, |
| 378 sqrtElement |
| 379 ]; |
| 380 mathUnit.topLevelVariables = <TopLevelVariableElement>[ |
| 381 ln10Element, |
| 382 piElement |
| 383 ]; |
| 384 mathUnit.types = <ClassElement>[randomElement]; |
| 385 LibraryElementImpl mathLibrary = new LibraryElementImpl.forNode( |
| 386 coreContext, AstFactory.libraryIdentifier2(["dart", "math"])); |
| 387 mathLibrary.definingCompilationUnit = mathUnit; |
| 388 // |
| 389 // Set empty sources for the rest of the libraries. |
| 390 // |
| 391 Source source = sourceFactory.forUri(_DART_INTERCEPTORS); |
| 392 coreContext.setContents(source, ""); |
| 393 source = sourceFactory.forUri(_DART_JS_HELPER); |
| 394 coreContext.setContents(source, ""); |
| 395 // |
| 396 // Record the elements. |
| 397 // |
| 398 HashMap<Source, LibraryElement> elementMap = |
| 399 new HashMap<Source, LibraryElement>(); |
| 400 elementMap[coreSource] = coreLibrary; |
| 401 elementMap[asyncSource] = asyncLibrary; |
| 402 elementMap[htmlSource] = htmlLibrary; |
| 403 elementMap[mathSource] = mathLibrary; |
| 404 context.recordLibraryElements(elementMap); |
| 405 return context; |
| 406 } |
| 407 |
| 408 /** |
| 409 * Create an analysis context that has a fake core library already resolved. |
| 410 * Return the context that was created. |
| 411 */ |
| 412 static AnalysisContextImpl oldContextWithCore() { |
| 413 AnalysisContextForTests context = new AnalysisContextForTests(); |
| 414 return initContextWithCore(context); |
| 415 } |
| 416 |
| 417 /** |
| 418 * Create an analysis context that uses the given [options] and has a fake |
| 419 * core library already resolved. Return the context that was created. |
| 420 */ |
| 421 static AnalysisContextImpl oldContextWithCoreAndOptions( |
| 422 AnalysisOptions options) { |
| 423 AnalysisContextForTests context = new AnalysisContextForTests(); |
| 424 context._internalSetAnalysisOptions(options); |
| 425 return initContextWithCore(context); |
| 426 } |
| 427 } |
| 428 |
| 429 /** |
| 430 * Instances of the class `AnalysisContextForTests` implement an analysis contex
t that has a |
| 431 * fake SDK that is much smaller and faster for testing purposes. |
| 432 */ |
| 433 class AnalysisContextForTests extends AnalysisContextImpl { |
| 434 @override |
| 435 void set analysisOptions(AnalysisOptions options) { |
| 436 AnalysisOptions currentOptions = analysisOptions; |
| 437 bool needsRecompute = currentOptions.analyzeFunctionBodiesPredicate != |
| 438 options.analyzeFunctionBodiesPredicate || |
| 439 currentOptions.generateImplicitErrors != |
| 440 options.generateImplicitErrors || |
| 441 currentOptions.generateSdkErrors != options.generateSdkErrors || |
| 442 currentOptions.dart2jsHint != options.dart2jsHint || |
| 443 (currentOptions.hint && !options.hint) || |
| 444 currentOptions.preserveComments != options.preserveComments || |
| 445 currentOptions.enableStrictCallChecks != options.enableStrictCallChecks; |
| 446 if (needsRecompute) { |
| 447 fail( |
| 448 "Cannot set options that cause the sources to be reanalyzed in a test
context"); |
| 449 } |
| 450 super.analysisOptions = options; |
| 451 } |
| 452 |
| 453 @override |
| 454 bool exists(Source source) => |
| 455 super.exists(source) || sourceFactory.dartSdk.context.exists(source); |
| 456 |
| 457 @override |
| 458 TimestampedData<String> getContents(Source source) { |
| 459 if (source.isInSystemLibrary) { |
| 460 return sourceFactory.dartSdk.context.getContents(source); |
| 461 } |
| 462 return super.getContents(source); |
| 463 } |
| 464 |
| 465 @override |
| 466 int getModificationStamp(Source source) { |
| 467 if (source.isInSystemLibrary) { |
| 468 return sourceFactory.dartSdk.context.getModificationStamp(source); |
| 469 } |
| 470 return super.getModificationStamp(source); |
| 471 } |
| 472 |
| 473 /** |
| 474 * Set the analysis options, even if they would force re-analysis. This method
should only be |
| 475 * invoked before the fake SDK is initialized. |
| 476 * |
| 477 * @param options the analysis options to be set |
| 478 */ |
| 479 void _internalSetAnalysisOptions(AnalysisOptions options) { |
| 480 super.analysisOptions = options; |
| 481 } |
| 482 } |
| 483 |
| 484 /** |
| 485 * Helper for creating and managing single [AnalysisContext]. |
| 486 */ |
| 487 class AnalysisContextHelper { |
| 488 AnalysisContext context; |
| 489 |
| 490 /** |
| 491 * Creates new [AnalysisContext] using [AnalysisContextFactory]. |
| 492 */ |
| 493 AnalysisContextHelper([AnalysisOptionsImpl options]) { |
| 494 if (options == null) { |
| 495 options = new AnalysisOptionsImpl(); |
| 496 } |
| 497 options.cacheSize = 256; |
| 498 context = AnalysisContextFactory.contextWithCoreAndOptions(options); |
| 499 } |
| 500 |
| 501 Source addSource(String path, String code) { |
| 502 Source source = new FileBasedSource(FileUtilities2.createFile(path)); |
| 503 if (path.endsWith(".dart") || path.endsWith(".html")) { |
| 504 ChangeSet changeSet = new ChangeSet(); |
| 505 changeSet.addedSource(source); |
| 506 context.applyChanges(changeSet); |
| 507 } |
| 508 context.setContents(source, code); |
| 509 return source; |
| 510 } |
| 511 |
| 512 CompilationUnitElement getDefiningUnitElement(Source source) => |
| 513 context.getCompilationUnitElement(source, source); |
| 514 |
| 515 CompilationUnit resolveDefiningUnit(Source source) { |
| 516 LibraryElement libraryElement = context.computeLibraryElement(source); |
| 517 return context.resolveCompilationUnit(source, libraryElement); |
| 518 } |
| 519 |
| 520 void runTasks() { |
| 521 AnalysisResult result = context.performAnalysisTask(); |
| 522 while (result.changeNotices != null) { |
| 523 result = context.performAnalysisTask(); |
| 524 } |
| 525 } |
| 526 } |
| 527 |
| 528 @reflectiveTest |
| 529 class AnalysisDeltaTest extends EngineTestCase { |
| 530 TestSource source1 = new TestSource('/1.dart'); |
| 531 TestSource source2 = new TestSource('/2.dart'); |
| 532 TestSource source3 = new TestSource('/3.dart'); |
| 533 |
| 534 void test_getAddedSources() { |
| 535 AnalysisDelta delta = new AnalysisDelta(); |
| 536 delta.setAnalysisLevel(source1, AnalysisLevel.ALL); |
| 537 delta.setAnalysisLevel(source2, AnalysisLevel.ERRORS); |
| 538 delta.setAnalysisLevel(source3, AnalysisLevel.NONE); |
| 539 List<Source> addedSources = delta.addedSources; |
| 540 expect(addedSources, hasLength(2)); |
| 541 expect(addedSources, unorderedEquals([source1, source2])); |
| 542 } |
| 543 |
| 544 void test_getAnalysisLevels() { |
| 545 AnalysisDelta delta = new AnalysisDelta(); |
| 546 expect(delta.analysisLevels.length, 0); |
| 547 } |
| 548 |
| 549 void test_setAnalysisLevel() { |
| 550 AnalysisDelta delta = new AnalysisDelta(); |
| 551 delta.setAnalysisLevel(source1, AnalysisLevel.ALL); |
| 552 delta.setAnalysisLevel(source2, AnalysisLevel.ERRORS); |
| 553 Map<Source, AnalysisLevel> levels = delta.analysisLevels; |
| 554 expect(levels.length, 2); |
| 555 expect(levels[source1], AnalysisLevel.ALL); |
| 556 expect(levels[source2], AnalysisLevel.ERRORS); |
| 557 } |
| 558 |
| 559 void test_toString() { |
| 560 AnalysisDelta delta = new AnalysisDelta(); |
| 561 delta.setAnalysisLevel(new TestSource(), AnalysisLevel.ALL); |
| 562 String result = delta.toString(); |
| 563 expect(result, isNotNull); |
| 564 expect(result.length > 0, isTrue); |
| 565 } |
| 566 } |
| 567 |
| 568 @reflectiveTest |
| 569 class ChangeSetTest extends EngineTestCase { |
| 570 void test_changedContent() { |
| 571 TestSource source = new TestSource(); |
| 572 String content = ""; |
| 573 ChangeSet changeSet = new ChangeSet(); |
| 574 changeSet.changedContent(source, content); |
| 575 expect(changeSet.addedSources, hasLength(0)); |
| 576 expect(changeSet.changedSources, hasLength(0)); |
| 577 Map<Source, String> map = changeSet.changedContents; |
| 578 expect(map, hasLength(1)); |
| 579 expect(map[source], same(content)); |
| 580 expect(changeSet.changedRanges, hasLength(0)); |
| 581 expect(changeSet.deletedSources, hasLength(0)); |
| 582 expect(changeSet.removedSources, hasLength(0)); |
| 583 expect(changeSet.removedContainers, hasLength(0)); |
| 584 } |
| 585 |
| 586 void test_changedRange() { |
| 587 TestSource source = new TestSource(); |
| 588 String content = ""; |
| 589 ChangeSet changeSet = new ChangeSet(); |
| 590 changeSet.changedRange(source, content, 1, 2, 3); |
| 591 expect(changeSet.addedSources, hasLength(0)); |
| 592 expect(changeSet.changedSources, hasLength(0)); |
| 593 expect(changeSet.changedContents, hasLength(0)); |
| 594 Map<Source, ChangeSet_ContentChange> map = changeSet.changedRanges; |
| 595 expect(map, hasLength(1)); |
| 596 ChangeSet_ContentChange change = map[source]; |
| 597 expect(change, isNotNull); |
| 598 expect(change.contents, content); |
| 599 expect(change.offset, 1); |
| 600 expect(change.oldLength, 2); |
| 601 expect(change.newLength, 3); |
| 602 expect(changeSet.deletedSources, hasLength(0)); |
| 603 expect(changeSet.removedSources, hasLength(0)); |
| 604 expect(changeSet.removedContainers, hasLength(0)); |
| 605 } |
| 606 |
| 607 void test_toString() { |
| 608 ChangeSet changeSet = new ChangeSet(); |
| 609 changeSet.addedSource(new TestSource()); |
| 610 changeSet.changedSource(new TestSource()); |
| 611 changeSet.changedContent(new TestSource(), ""); |
| 612 changeSet.changedRange(new TestSource(), "", 0, 0, 0); |
| 613 changeSet.deletedSource(new TestSource()); |
| 614 changeSet.removedSource(new TestSource()); |
| 615 changeSet |
| 616 .removedContainer(new SourceContainer_ChangeSetTest_test_toString()); |
| 617 expect(changeSet.toString(), isNotNull); |
| 618 } |
| 619 } |
| 620 |
| 621 @reflectiveTest |
| 622 class CheckedModeCompileTimeErrorCodeTest extends ResolverTestCase { |
| 623 void test_fieldFormalParameterAssignableToField_extends() { |
| 624 // According to checked-mode type checking rules, a value of type B is |
| 625 // assignable to a field of type A, because B extends A (and hence is a |
| 626 // subtype of A). |
| 627 Source source = addSource(r''' |
| 628 class A { |
| 629 const A(); |
| 630 } |
| 631 class B extends A { |
| 632 const B(); |
| 633 } |
| 634 class C { |
| 635 final A a; |
| 636 const C(this.a); |
| 637 } |
| 638 var v = const C(const B());'''); |
| 639 computeLibrarySourceErrors(source); |
| 640 assertNoErrors(source); |
| 641 verify([source]); |
| 642 } |
| 643 |
| 644 void test_fieldFormalParameterAssignableToField_fieldType_unresolved_null() { |
| 645 // Null always passes runtime type checks, even when the type is |
| 646 // unresolved. |
| 647 Source source = addSource(r''' |
| 648 class A { |
| 649 final Unresolved x; |
| 650 const A(String this.x); |
| 651 } |
| 652 var v = const A(null);'''); |
| 653 computeLibrarySourceErrors(source); |
| 654 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); |
| 655 verify([source]); |
| 656 } |
| 657 |
| 658 void test_fieldFormalParameterAssignableToField_implements() { |
| 659 // According to checked-mode type checking rules, a value of type B is |
| 660 // assignable to a field of type A, because B implements A (and hence is a |
| 661 // subtype of A). |
| 662 Source source = addSource(r''' |
| 663 class A {} |
| 664 class B implements A { |
| 665 const B(); |
| 666 } |
| 667 class C { |
| 668 final A a; |
| 669 const C(this.a); |
| 670 } |
| 671 var v = const C(const B());'''); |
| 672 computeLibrarySourceErrors(source); |
| 673 assertNoErrors(source); |
| 674 verify([source]); |
| 675 } |
| 676 |
| 677 void test_fieldFormalParameterAssignableToField_list_dynamic() { |
| 678 // [1, 2, 3] has type List<dynamic>, which is a subtype of List<int>. |
| 679 Source source = addSource(r''' |
| 680 class A { |
| 681 const A(List<int> x); |
| 682 } |
| 683 var x = const A(const [1, 2, 3]);'''); |
| 684 computeLibrarySourceErrors(source); |
| 685 assertNoErrors(source); |
| 686 verify([source]); |
| 687 } |
| 688 |
| 689 void test_fieldFormalParameterAssignableToField_list_nonDynamic() { |
| 690 // <int>[1, 2, 3] has type List<int>, which is a subtype of List<num>. |
| 691 Source source = addSource(r''' |
| 692 class A { |
| 693 const A(List<num> x); |
| 694 } |
| 695 var x = const A(const <int>[1, 2, 3]);'''); |
| 696 computeLibrarySourceErrors(source); |
| 697 assertNoErrors(source); |
| 698 verify([source]); |
| 699 } |
| 700 |
| 701 void test_fieldFormalParameterAssignableToField_map_dynamic() { |
| 702 // {1: 2} has type Map<dynamic, dynamic>, which is a subtype of |
| 703 // Map<int, int>. |
| 704 Source source = addSource(r''' |
| 705 class A { |
| 706 const A(Map<int, int> x); |
| 707 } |
| 708 var x = const A(const {1: 2});'''); |
| 709 computeLibrarySourceErrors(source); |
| 710 assertNoErrors(source); |
| 711 verify([source]); |
| 712 } |
| 713 |
| 714 void test_fieldFormalParameterAssignableToField_map_keyDifferent() { |
| 715 // <int, int>{1: 2} has type Map<int, int>, which is a subtype of |
| 716 // Map<num, int>. |
| 717 Source source = addSource(r''' |
| 718 class A { |
| 719 const A(Map<num, int> x); |
| 720 } |
| 721 var x = const A(const <int, int>{1: 2});'''); |
| 722 computeLibrarySourceErrors(source); |
| 723 assertNoErrors(source); |
| 724 verify([source]); |
| 725 } |
| 726 |
| 727 void test_fieldFormalParameterAssignableToField_map_valueDifferent() { |
| 728 // <int, int>{1: 2} has type Map<int, int>, which is a subtype of |
| 729 // Map<int, num>. |
| 730 Source source = addSource(r''' |
| 731 class A { |
| 732 const A(Map<int, num> x); |
| 733 } |
| 734 var x = const A(const <int, int>{1: 2});'''); |
| 735 computeLibrarySourceErrors(source); |
| 736 assertNoErrors(source); |
| 737 verify([source]); |
| 738 } |
| 739 |
| 740 void test_fieldFormalParameterAssignableToField_notype() { |
| 741 // If a field is declared without a type, then any value may be assigned to |
| 742 // it. |
| 743 Source source = addSource(r''' |
| 744 class A { |
| 745 final x; |
| 746 const A(this.x); |
| 747 } |
| 748 var v = const A(5);'''); |
| 749 computeLibrarySourceErrors(source); |
| 750 assertNoErrors(source); |
| 751 verify([source]); |
| 752 } |
| 753 |
| 754 void test_fieldFormalParameterAssignableToField_null() { |
| 755 // Null is assignable to anything. |
| 756 Source source = addSource(r''' |
| 757 class A { |
| 758 final int x; |
| 759 const A(this.x); |
| 760 } |
| 761 var v = const A(null);'''); |
| 762 computeLibrarySourceErrors(source); |
| 763 assertNoErrors(source); |
| 764 verify([source]); |
| 765 } |
| 766 |
| 767 void test_fieldFormalParameterAssignableToField_typedef() { |
| 768 // foo has the runtime type dynamic -> dynamic, so it should be assignable |
| 769 // to A.f. |
| 770 Source source = addSource(r''' |
| 771 typedef String Int2String(int x); |
| 772 class A { |
| 773 final Int2String f; |
| 774 const A(this.f); |
| 775 } |
| 776 foo(x) => 1; |
| 777 var v = const A(foo);'''); |
| 778 computeLibrarySourceErrors(source); |
| 779 assertNoErrors(source); |
| 780 verify([source]); |
| 781 } |
| 782 |
| 783 void test_fieldFormalParameterAssignableToField_typeSubstitution() { |
| 784 // foo has the runtime type dynamic -> dynamic, so it should be assignable |
| 785 // to A.f. |
| 786 Source source = addSource(r''' |
| 787 class A<T> { |
| 788 final T x; |
| 789 const A(this.x); |
| 790 } |
| 791 var v = const A<int>(3);'''); |
| 792 computeLibrarySourceErrors(source); |
| 793 assertNoErrors(source); |
| 794 verify([source]); |
| 795 } |
| 796 |
| 797 void test_fieldFormalParameterNotAssignableToField() { |
| 798 Source source = addSource(r''' |
| 799 class A { |
| 800 final int x; |
| 801 const A(this.x); |
| 802 } |
| 803 var v = const A('foo');'''); |
| 804 computeLibrarySourceErrors(source); |
| 805 assertErrors(source, [ |
| 806 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 807 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE |
| 808 ]); |
| 809 verify([source]); |
| 810 } |
| 811 |
| 812 void test_fieldFormalParameterNotAssignableToField_extends() { |
| 813 // According to checked-mode type checking rules, a value of type A is not |
| 814 // assignable to a field of type B, because B extends A (the subtyping |
| 815 // relationship is in the wrong direction). |
| 816 Source source = addSource(r''' |
| 817 class A { |
| 818 const A(); |
| 819 } |
| 820 class B extends A { |
| 821 const B(); |
| 822 } |
| 823 class C { |
| 824 final B b; |
| 825 const C(this.b); |
| 826 } |
| 827 var v = const C(const A());'''); |
| 828 computeLibrarySourceErrors(source); |
| 829 assertErrors(source, [ |
| 830 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 831 ]); |
| 832 verify([source]); |
| 833 } |
| 834 |
| 835 void test_fieldFormalParameterNotAssignableToField_fieldType() { |
| 836 Source source = addSource(r''' |
| 837 class A { |
| 838 final int x; |
| 839 const A(String this.x); |
| 840 } |
| 841 var v = const A('foo');'''); |
| 842 computeLibrarySourceErrors(source); |
| 843 assertErrors(source, [ |
| 844 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 845 StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE |
| 846 ]); |
| 847 verify([source]); |
| 848 } |
| 849 |
| 850 void test_fieldFormalParameterNotAssignableToField_fieldType_unresolved() { |
| 851 Source source = addSource(r''' |
| 852 class A { |
| 853 final Unresolved x; |
| 854 const A(String this.x); |
| 855 } |
| 856 var v = const A('foo');'''); |
| 857 computeLibrarySourceErrors(source); |
| 858 assertErrors(source, [ |
| 859 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 860 StaticWarningCode.UNDEFINED_CLASS |
| 861 ]); |
| 862 verify([source]); |
| 863 } |
| 864 |
| 865 void test_fieldFormalParameterNotAssignableToField_implements() { |
| 866 // According to checked-mode type checking rules, a value of type A is not |
| 867 // assignable to a field of type B, because B implements A (the subtyping |
| 868 // relationship is in the wrong direction). |
| 869 Source source = addSource(r''' |
| 870 class A { |
| 871 const A(); |
| 872 } |
| 873 class B implements A {} |
| 874 class C { |
| 875 final B b; |
| 876 const C(this.b); |
| 877 } |
| 878 var v = const C(const A());'''); |
| 879 computeLibrarySourceErrors(source); |
| 880 assertErrors(source, [ |
| 881 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 882 ]); |
| 883 verify([source]); |
| 884 } |
| 885 |
| 886 void test_fieldFormalParameterNotAssignableToField_list() { |
| 887 // <num>[1, 2, 3] has type List<num>, which is not a subtype of List<int>. |
| 888 Source source = addSource(r''' |
| 889 class A { |
| 890 const A(List<int> x); |
| 891 } |
| 892 var x = const A(const <num>[1, 2, 3]);'''); |
| 893 computeLibrarySourceErrors(source); |
| 894 assertErrors(source, [ |
| 895 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 896 ]); |
| 897 verify([source]); |
| 898 } |
| 899 |
| 900 void test_fieldFormalParameterNotAssignableToField_map_keyMismatch() { |
| 901 // <num, int>{1: 2} has type Map<num, int>, which is not a subtype of |
| 902 // Map<int, int>. |
| 903 Source source = addSource(r''' |
| 904 class A { |
| 905 const A(Map<int, int> x); |
| 906 } |
| 907 var x = const A(const <num, int>{1: 2});'''); |
| 908 computeLibrarySourceErrors(source); |
| 909 assertErrors(source, [ |
| 910 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 911 ]); |
| 912 verify([source]); |
| 913 } |
| 914 |
| 915 void test_fieldFormalParameterNotAssignableToField_map_valueMismatch() { |
| 916 // <int, num>{1: 2} has type Map<int, num>, which is not a subtype of |
| 917 // Map<int, int>. |
| 918 Source source = addSource(r''' |
| 919 class A { |
| 920 const A(Map<int, int> x); |
| 921 } |
| 922 var x = const A(const <int, num>{1: 2});'''); |
| 923 computeLibrarySourceErrors(source); |
| 924 assertErrors(source, [ |
| 925 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 926 ]); |
| 927 verify([source]); |
| 928 } |
| 929 |
| 930 void test_fieldFormalParameterNotAssignableToField_optional() { |
| 931 Source source = addSource(r''' |
| 932 class A { |
| 933 final int x; |
| 934 const A([this.x = 'foo']); |
| 935 } |
| 936 var v = const A();'''); |
| 937 computeLibrarySourceErrors(source); |
| 938 assertErrors(source, [ |
| 939 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 940 StaticTypeWarningCode.INVALID_ASSIGNMENT |
| 941 ]); |
| 942 verify([source]); |
| 943 } |
| 944 |
| 945 void test_fieldFormalParameterNotAssignableToField_typedef() { |
| 946 // foo has the runtime type String -> int, so it should not be assignable |
| 947 // to A.f (A.f requires it to be int -> String). |
| 948 Source source = addSource(r''' |
| 949 typedef String Int2String(int x); |
| 950 class A { |
| 951 final Int2String f; |
| 952 const A(this.f); |
| 953 } |
| 954 int foo(String x) => 1; |
| 955 var v = const A(foo);'''); |
| 956 computeLibrarySourceErrors(source); |
| 957 assertErrors(source, [ |
| 958 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 959 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE |
| 960 ]); |
| 961 verify([source]); |
| 962 } |
| 963 |
| 964 void test_fieldInitializerNotAssignable() { |
| 965 Source source = addSource(r''' |
| 966 class A { |
| 967 final int x; |
| 968 const A() : x = ''; |
| 969 }'''); |
| 970 computeLibrarySourceErrors(source); |
| 971 assertErrors(source, [ |
| 972 CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE, |
| 973 StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE |
| 974 ]); |
| 975 verify([source]); |
| 976 } |
| 977 |
| 978 void test_fieldTypeMismatch() { |
| 979 Source source = addSource(r''' |
| 980 class A { |
| 981 const A(x) : y = x; |
| 982 final int y; |
| 983 } |
| 984 var v = const A('foo');'''); |
| 985 computeLibrarySourceErrors(source); |
| 986 assertErrors(source, [ |
| 987 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH |
| 988 ]); |
| 989 verify([source]); |
| 990 } |
| 991 |
| 992 void test_fieldTypeMismatch_generic() { |
| 993 Source source = addSource(r''' |
| 994 class C<T> { |
| 995 final T x = y; |
| 996 const C(); |
| 997 } |
| 998 const int y = 1; |
| 999 var v = const C<String>(); |
| 1000 '''); |
| 1001 computeLibrarySourceErrors(source); |
| 1002 assertErrors(source, [ |
| 1003 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, |
| 1004 StaticTypeWarningCode.INVALID_ASSIGNMENT |
| 1005 ]); |
| 1006 verify([source]); |
| 1007 } |
| 1008 |
| 1009 void test_fieldTypeMismatch_unresolved() { |
| 1010 Source source = addSource(r''' |
| 1011 class A { |
| 1012 const A(x) : y = x; |
| 1013 final Unresolved y; |
| 1014 } |
| 1015 var v = const A('foo');'''); |
| 1016 computeLibrarySourceErrors(source); |
| 1017 assertErrors(source, [ |
| 1018 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, |
| 1019 StaticWarningCode.UNDEFINED_CLASS |
| 1020 ]); |
| 1021 verify([source]); |
| 1022 } |
| 1023 |
| 1024 void test_fieldTypeOk_generic() { |
| 1025 Source source = addSource(r''' |
| 1026 class C<T> { |
| 1027 final T x = y; |
| 1028 const C(); |
| 1029 } |
| 1030 const int y = 1; |
| 1031 var v = const C<int>(); |
| 1032 '''); |
| 1033 computeLibrarySourceErrors(source); |
| 1034 assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); |
| 1035 verify([source]); |
| 1036 } |
| 1037 |
| 1038 void test_fieldTypeOk_null() { |
| 1039 Source source = addSource(r''' |
| 1040 class A { |
| 1041 const A(x) : y = x; |
| 1042 final int y; |
| 1043 } |
| 1044 var v = const A(null);'''); |
| 1045 computeLibrarySourceErrors(source); |
| 1046 assertNoErrors(source); |
| 1047 verify([source]); |
| 1048 } |
| 1049 |
| 1050 void test_fieldTypeOk_unresolved_null() { |
| 1051 // Null always passes runtime type checks, even when the type is |
| 1052 // unresolved. |
| 1053 Source source = addSource(r''' |
| 1054 class A { |
| 1055 const A(x) : y = x; |
| 1056 final Unresolved y; |
| 1057 } |
| 1058 var v = const A(null);'''); |
| 1059 computeLibrarySourceErrors(source); |
| 1060 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); |
| 1061 verify([source]); |
| 1062 } |
| 1063 |
| 1064 void test_listElementTypeNotAssignable() { |
| 1065 Source source = addSource("var v = const <String> [42];"); |
| 1066 computeLibrarySourceErrors(source); |
| 1067 assertErrors(source, [ |
| 1068 CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, |
| 1069 StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE |
| 1070 ]); |
| 1071 verify([source]); |
| 1072 } |
| 1073 |
| 1074 void test_mapKeyTypeNotAssignable() { |
| 1075 Source source = addSource("var v = const <String, int > {1 : 2};"); |
| 1076 computeLibrarySourceErrors(source); |
| 1077 assertErrors(source, [ |
| 1078 CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, |
| 1079 StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE |
| 1080 ]); |
| 1081 verify([source]); |
| 1082 } |
| 1083 |
| 1084 void test_mapValueTypeNotAssignable() { |
| 1085 Source source = addSource("var v = const <String, String> {'a' : 2};"); |
| 1086 computeLibrarySourceErrors(source); |
| 1087 assertErrors(source, [ |
| 1088 CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, |
| 1089 StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE |
| 1090 ]); |
| 1091 verify([source]); |
| 1092 } |
| 1093 |
| 1094 void test_parameterAssignable_null() { |
| 1095 // Null is assignable to anything. |
| 1096 Source source = addSource(r''' |
| 1097 class A { |
| 1098 const A(int x); |
| 1099 } |
| 1100 var v = const A(null);'''); |
| 1101 computeLibrarySourceErrors(source); |
| 1102 assertNoErrors(source); |
| 1103 verify([source]); |
| 1104 } |
| 1105 |
| 1106 void test_parameterAssignable_typeSubstitution() { |
| 1107 Source source = addSource(r''' |
| 1108 class A<T> { |
| 1109 const A(T x); |
| 1110 } |
| 1111 var v = const A<int>(3);'''); |
| 1112 computeLibrarySourceErrors(source); |
| 1113 assertNoErrors(source); |
| 1114 verify([source]); |
| 1115 } |
| 1116 |
| 1117 void test_parameterAssignable_undefined_null() { |
| 1118 // Null always passes runtime type checks, even when the type is |
| 1119 // unresolved. |
| 1120 Source source = addSource(r''' |
| 1121 class A { |
| 1122 const A(Unresolved x); |
| 1123 } |
| 1124 var v = const A(null);'''); |
| 1125 computeLibrarySourceErrors(source); |
| 1126 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); |
| 1127 verify([source]); |
| 1128 } |
| 1129 |
| 1130 void test_parameterNotAssignable() { |
| 1131 Source source = addSource(r''' |
| 1132 class A { |
| 1133 const A(int x); |
| 1134 } |
| 1135 var v = const A('foo');'''); |
| 1136 computeLibrarySourceErrors(source); |
| 1137 assertErrors(source, [ |
| 1138 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 1139 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE |
| 1140 ]); |
| 1141 verify([source]); |
| 1142 } |
| 1143 |
| 1144 void test_parameterNotAssignable_typeSubstitution() { |
| 1145 Source source = addSource(r''' |
| 1146 class A<T> { |
| 1147 const A(T x); |
| 1148 } |
| 1149 var v = const A<int>('foo');'''); |
| 1150 computeLibrarySourceErrors(source); |
| 1151 assertErrors(source, [ |
| 1152 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 1153 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE |
| 1154 ]); |
| 1155 verify([source]); |
| 1156 } |
| 1157 |
| 1158 void test_parameterNotAssignable_undefined() { |
| 1159 Source source = addSource(r''' |
| 1160 class A { |
| 1161 const A(Unresolved x); |
| 1162 } |
| 1163 var v = const A('foo');'''); |
| 1164 computeLibrarySourceErrors(source); |
| 1165 assertErrors(source, [ |
| 1166 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 1167 StaticWarningCode.UNDEFINED_CLASS |
| 1168 ]); |
| 1169 verify([source]); |
| 1170 } |
| 1171 |
| 1172 void test_redirectingConstructor_paramTypeMismatch() { |
| 1173 Source source = addSource(r''' |
| 1174 class A { |
| 1175 const A.a1(x) : this.a2(x); |
| 1176 const A.a2(String x); |
| 1177 } |
| 1178 var v = const A.a1(0);'''); |
| 1179 computeLibrarySourceErrors(source); |
| 1180 assertErrors(source, [ |
| 1181 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 1182 ]); |
| 1183 verify([source]); |
| 1184 } |
| 1185 |
| 1186 void test_topLevelVarAssignable_null() { |
| 1187 Source source = addSource("const int x = null;"); |
| 1188 computeLibrarySourceErrors(source); |
| 1189 assertNoErrors(source); |
| 1190 verify([source]); |
| 1191 } |
| 1192 |
| 1193 void test_topLevelVarAssignable_undefined_null() { |
| 1194 // Null always passes runtime type checks, even when the type is |
| 1195 // unresolved. |
| 1196 Source source = addSource("const Unresolved x = null;"); |
| 1197 computeLibrarySourceErrors(source); |
| 1198 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); |
| 1199 verify([source]); |
| 1200 } |
| 1201 |
| 1202 void test_topLevelVarNotAssignable() { |
| 1203 Source source = addSource("const int x = 'foo';"); |
| 1204 computeLibrarySourceErrors(source); |
| 1205 assertErrors(source, [ |
| 1206 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, |
| 1207 StaticTypeWarningCode.INVALID_ASSIGNMENT |
| 1208 ]); |
| 1209 verify([source]); |
| 1210 } |
| 1211 |
| 1212 void test_topLevelVarNotAssignable_undefined() { |
| 1213 Source source = addSource("const Unresolved x = 'foo';"); |
| 1214 computeLibrarySourceErrors(source); |
| 1215 assertErrors(source, [ |
| 1216 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, |
| 1217 StaticWarningCode.UNDEFINED_CLASS |
| 1218 ]); |
| 1219 verify([source]); |
| 1220 } |
| 1221 } |
| 1222 |
| 1223 @reflectiveTest |
| 1224 class ElementResolverTest extends EngineTestCase { |
| 1225 /** |
| 1226 * The error listener to which errors will be reported. |
| 1227 */ |
| 1228 GatheringErrorListener _listener; |
| 1229 |
| 1230 /** |
| 1231 * The type provider used to access the types. |
| 1232 */ |
| 1233 TestTypeProvider _typeProvider; |
| 1234 |
| 1235 /** |
| 1236 * The library containing the code being resolved. |
| 1237 */ |
| 1238 LibraryElementImpl _definingLibrary; |
| 1239 |
| 1240 /** |
| 1241 * The resolver visitor that maintains the state for the resolver. |
| 1242 */ |
| 1243 ResolverVisitor _visitor; |
| 1244 |
| 1245 /** |
| 1246 * The resolver being used to resolve the test cases. |
| 1247 */ |
| 1248 ElementResolver _resolver; |
| 1249 |
| 1250 void fail_visitExportDirective_combinators() { |
| 1251 fail("Not yet tested"); |
| 1252 // Need to set up the exported library so that the identifier can be |
| 1253 // resolved. |
| 1254 ExportDirective directive = AstFactory.exportDirective2(null, [ |
| 1255 AstFactory.hideCombinator2(["A"]) |
| 1256 ]); |
| 1257 _resolveNode(directive); |
| 1258 _listener.assertNoErrors(); |
| 1259 } |
| 1260 |
| 1261 void fail_visitFunctionExpressionInvocation() { |
| 1262 fail("Not yet tested"); |
| 1263 _listener.assertNoErrors(); |
| 1264 } |
| 1265 |
| 1266 void fail_visitImportDirective_combinators_noPrefix() { |
| 1267 fail("Not yet tested"); |
| 1268 // Need to set up the imported library so that the identifier can be |
| 1269 // resolved. |
| 1270 ImportDirective directive = AstFactory.importDirective3(null, null, [ |
| 1271 AstFactory.showCombinator2(["A"]) |
| 1272 ]); |
| 1273 _resolveNode(directive); |
| 1274 _listener.assertNoErrors(); |
| 1275 } |
| 1276 |
| 1277 void fail_visitImportDirective_combinators_prefix() { |
| 1278 fail("Not yet tested"); |
| 1279 // Need to set up the imported library so that the identifiers can be |
| 1280 // resolved. |
| 1281 String prefixName = "p"; |
| 1282 _definingLibrary.imports = <ImportElement>[ |
| 1283 ElementFactory.importFor(null, ElementFactory.prefix(prefixName)) |
| 1284 ]; |
| 1285 ImportDirective directive = AstFactory.importDirective3(null, prefixName, [ |
| 1286 AstFactory.showCombinator2(["A"]), |
| 1287 AstFactory.hideCombinator2(["B"]) |
| 1288 ]); |
| 1289 _resolveNode(directive); |
| 1290 _listener.assertNoErrors(); |
| 1291 } |
| 1292 |
| 1293 void fail_visitRedirectingConstructorInvocation() { |
| 1294 fail("Not yet tested"); |
| 1295 _listener.assertNoErrors(); |
| 1296 } |
| 1297 |
| 1298 @override |
| 1299 void setUp() { |
| 1300 _listener = new GatheringErrorListener(); |
| 1301 _typeProvider = new TestTypeProvider(); |
| 1302 _resolver = _createResolver(); |
| 1303 } |
| 1304 |
| 1305 void test_lookUpMethodInInterfaces() { |
| 1306 InterfaceType intType = _typeProvider.intType; |
| 1307 // |
| 1308 // abstract class A { int operator[](int index); } |
| 1309 // |
| 1310 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1311 MethodElement operator = |
| 1312 ElementFactory.methodElement("[]", intType, [intType]); |
| 1313 classA.methods = <MethodElement>[operator]; |
| 1314 // |
| 1315 // class B implements A {} |
| 1316 // |
| 1317 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 1318 classB.interfaces = <InterfaceType>[classA.type]; |
| 1319 // |
| 1320 // class C extends Object with B {} |
| 1321 // |
| 1322 ClassElementImpl classC = ElementFactory.classElement2("C"); |
| 1323 classC.mixins = <InterfaceType>[classB.type]; |
| 1324 // |
| 1325 // class D extends C {} |
| 1326 // |
| 1327 ClassElementImpl classD = ElementFactory.classElement("D", classC.type); |
| 1328 // |
| 1329 // D a; |
| 1330 // a[i]; |
| 1331 // |
| 1332 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 1333 array.staticType = classD.type; |
| 1334 IndexExpression expression = |
| 1335 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 1336 expect(_resolveIndexExpression(expression), same(operator)); |
| 1337 _listener.assertNoErrors(); |
| 1338 } |
| 1339 |
| 1340 void test_visitAssignmentExpression_compound() { |
| 1341 InterfaceType intType = _typeProvider.intType; |
| 1342 SimpleIdentifier leftHandSide = AstFactory.identifier3("a"); |
| 1343 leftHandSide.staticType = intType; |
| 1344 AssignmentExpression assignment = AstFactory.assignmentExpression( |
| 1345 leftHandSide, TokenType.PLUS_EQ, AstFactory.integer(1)); |
| 1346 _resolveNode(assignment); |
| 1347 expect( |
| 1348 assignment.staticElement, same(getMethod(_typeProvider.numType, "+"))); |
| 1349 _listener.assertNoErrors(); |
| 1350 } |
| 1351 |
| 1352 void test_visitAssignmentExpression_simple() { |
| 1353 AssignmentExpression expression = AstFactory.assignmentExpression( |
| 1354 AstFactory.identifier3("x"), TokenType.EQ, AstFactory.integer(0)); |
| 1355 _resolveNode(expression); |
| 1356 expect(expression.staticElement, isNull); |
| 1357 _listener.assertNoErrors(); |
| 1358 } |
| 1359 |
| 1360 void test_visitBinaryExpression_bangEq() { |
| 1361 // String i; |
| 1362 // var j; |
| 1363 // i == j |
| 1364 InterfaceType stringType = _typeProvider.stringType; |
| 1365 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1366 left.staticType = stringType; |
| 1367 BinaryExpression expression = AstFactory.binaryExpression( |
| 1368 left, TokenType.BANG_EQ, AstFactory.identifier3("j")); |
| 1369 _resolveNode(expression); |
| 1370 var stringElement = stringType.element; |
| 1371 expect(expression.staticElement, isNotNull); |
| 1372 expect( |
| 1373 expression.staticElement, |
| 1374 stringElement.lookUpMethod( |
| 1375 TokenType.EQ_EQ.lexeme, stringElement.library)); |
| 1376 expect(expression.propagatedElement, isNull); |
| 1377 _listener.assertNoErrors(); |
| 1378 } |
| 1379 |
| 1380 void test_visitBinaryExpression_eq() { |
| 1381 // String i; |
| 1382 // var j; |
| 1383 // i == j |
| 1384 InterfaceType stringType = _typeProvider.stringType; |
| 1385 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1386 left.staticType = stringType; |
| 1387 BinaryExpression expression = AstFactory.binaryExpression( |
| 1388 left, TokenType.EQ_EQ, AstFactory.identifier3("j")); |
| 1389 _resolveNode(expression); |
| 1390 var stringElement = stringType.element; |
| 1391 expect( |
| 1392 expression.staticElement, |
| 1393 stringElement.lookUpMethod( |
| 1394 TokenType.EQ_EQ.lexeme, stringElement.library)); |
| 1395 expect(expression.propagatedElement, isNull); |
| 1396 _listener.assertNoErrors(); |
| 1397 } |
| 1398 |
| 1399 void test_visitBinaryExpression_plus() { |
| 1400 // num i; |
| 1401 // var j; |
| 1402 // i + j |
| 1403 InterfaceType numType = _typeProvider.numType; |
| 1404 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1405 left.staticType = numType; |
| 1406 BinaryExpression expression = AstFactory.binaryExpression( |
| 1407 left, TokenType.PLUS, AstFactory.identifier3("j")); |
| 1408 _resolveNode(expression); |
| 1409 expect(expression.staticElement, getMethod(numType, "+")); |
| 1410 expect(expression.propagatedElement, isNull); |
| 1411 _listener.assertNoErrors(); |
| 1412 } |
| 1413 |
| 1414 void test_visitBinaryExpression_plus_propagatedElement() { |
| 1415 // var i = 1; |
| 1416 // var j; |
| 1417 // i + j |
| 1418 InterfaceType numType = _typeProvider.numType; |
| 1419 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1420 left.propagatedType = numType; |
| 1421 BinaryExpression expression = AstFactory.binaryExpression( |
| 1422 left, TokenType.PLUS, AstFactory.identifier3("j")); |
| 1423 _resolveNode(expression); |
| 1424 expect(expression.staticElement, isNull); |
| 1425 expect(expression.propagatedElement, getMethod(numType, "+")); |
| 1426 _listener.assertNoErrors(); |
| 1427 } |
| 1428 |
| 1429 void test_visitBreakStatement_withLabel() { |
| 1430 // loop: while (true) { |
| 1431 // break loop; |
| 1432 // } |
| 1433 String label = "loop"; |
| 1434 LabelElementImpl labelElement = |
| 1435 new LabelElementImpl(AstFactory.identifier3(label), false, false); |
| 1436 BreakStatement breakStatement = AstFactory.breakStatement2(label); |
| 1437 Expression condition = AstFactory.booleanLiteral(true); |
| 1438 WhileStatement whileStatement = |
| 1439 AstFactory.whileStatement(condition, breakStatement); |
| 1440 expect(_resolveBreak(breakStatement, labelElement, whileStatement), |
| 1441 same(labelElement)); |
| 1442 expect(breakStatement.target, same(whileStatement)); |
| 1443 _listener.assertNoErrors(); |
| 1444 } |
| 1445 |
| 1446 void test_visitBreakStatement_withoutLabel() { |
| 1447 BreakStatement statement = AstFactory.breakStatement(); |
| 1448 _resolveStatement(statement, null, null); |
| 1449 _listener.assertNoErrors(); |
| 1450 } |
| 1451 |
| 1452 void test_visitConstructorName_named() { |
| 1453 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1454 String constructorName = "a"; |
| 1455 ConstructorElement constructor = |
| 1456 ElementFactory.constructorElement2(classA, constructorName); |
| 1457 classA.constructors = <ConstructorElement>[constructor]; |
| 1458 ConstructorName name = AstFactory.constructorName( |
| 1459 AstFactory.typeName(classA), constructorName); |
| 1460 _resolveNode(name); |
| 1461 expect(name.staticElement, same(constructor)); |
| 1462 _listener.assertNoErrors(); |
| 1463 } |
| 1464 |
| 1465 void test_visitConstructorName_unnamed() { |
| 1466 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1467 String constructorName = null; |
| 1468 ConstructorElement constructor = |
| 1469 ElementFactory.constructorElement2(classA, constructorName); |
| 1470 classA.constructors = <ConstructorElement>[constructor]; |
| 1471 ConstructorName name = AstFactory.constructorName( |
| 1472 AstFactory.typeName(classA), constructorName); |
| 1473 _resolveNode(name); |
| 1474 expect(name.staticElement, same(constructor)); |
| 1475 _listener.assertNoErrors(); |
| 1476 } |
| 1477 |
| 1478 void test_visitContinueStatement_withLabel() { |
| 1479 // loop: while (true) { |
| 1480 // continue loop; |
| 1481 // } |
| 1482 String label = "loop"; |
| 1483 LabelElementImpl labelElement = |
| 1484 new LabelElementImpl(AstFactory.identifier3(label), false, false); |
| 1485 ContinueStatement continueStatement = AstFactory.continueStatement(label); |
| 1486 Expression condition = AstFactory.booleanLiteral(true); |
| 1487 WhileStatement whileStatement = |
| 1488 AstFactory.whileStatement(condition, continueStatement); |
| 1489 expect(_resolveContinue(continueStatement, labelElement, whileStatement), |
| 1490 same(labelElement)); |
| 1491 expect(continueStatement.target, same(whileStatement)); |
| 1492 _listener.assertNoErrors(); |
| 1493 } |
| 1494 |
| 1495 void test_visitContinueStatement_withoutLabel() { |
| 1496 ContinueStatement statement = AstFactory.continueStatement(); |
| 1497 _resolveStatement(statement, null, null); |
| 1498 _listener.assertNoErrors(); |
| 1499 } |
| 1500 |
| 1501 void test_visitEnumDeclaration() { |
| 1502 ClassElementImpl enumElement = |
| 1503 ElementFactory.enumElement(_typeProvider, ('E')); |
| 1504 EnumDeclaration enumNode = AstFactory.enumDeclaration2('E', []); |
| 1505 Annotation annotationNode = |
| 1506 AstFactory.annotation(AstFactory.identifier3('a')); |
| 1507 annotationNode.element = ElementFactory.classElement2('A'); |
| 1508 enumNode.metadata.add(annotationNode); |
| 1509 enumNode.name.staticElement = enumElement; |
| 1510 _resolveNode(enumNode); |
| 1511 List<ElementAnnotation> metadata = enumElement.metadata; |
| 1512 expect(metadata, hasLength(1)); |
| 1513 } |
| 1514 |
| 1515 void test_visitExportDirective_noCombinators() { |
| 1516 ExportDirective directive = AstFactory.exportDirective2(null); |
| 1517 directive.element = ElementFactory |
| 1518 .exportFor(ElementFactory.library(_definingLibrary.context, "lib")); |
| 1519 _resolveNode(directive); |
| 1520 _listener.assertNoErrors(); |
| 1521 } |
| 1522 |
| 1523 void test_visitFieldFormalParameter() { |
| 1524 String fieldName = "f"; |
| 1525 InterfaceType intType = _typeProvider.intType; |
| 1526 FieldElementImpl fieldElement = |
| 1527 ElementFactory.fieldElement(fieldName, false, false, false, intType); |
| 1528 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1529 classA.fields = <FieldElement>[fieldElement]; |
| 1530 FieldFormalParameter parameter = |
| 1531 AstFactory.fieldFormalParameter2(fieldName); |
| 1532 FieldFormalParameterElementImpl parameterElement = |
| 1533 ElementFactory.fieldFormalParameter(parameter.identifier); |
| 1534 parameterElement.field = fieldElement; |
| 1535 parameterElement.type = intType; |
| 1536 parameter.identifier.staticElement = parameterElement; |
| 1537 _resolveInClass(parameter, classA); |
| 1538 expect(parameter.element.type, same(intType)); |
| 1539 } |
| 1540 |
| 1541 void test_visitImportDirective_noCombinators_noPrefix() { |
| 1542 ImportDirective directive = AstFactory.importDirective3(null, null); |
| 1543 directive.element = ElementFactory.importFor( |
| 1544 ElementFactory.library(_definingLibrary.context, "lib"), null); |
| 1545 _resolveNode(directive); |
| 1546 _listener.assertNoErrors(); |
| 1547 } |
| 1548 |
| 1549 void test_visitImportDirective_noCombinators_prefix() { |
| 1550 String prefixName = "p"; |
| 1551 ImportElement importElement = ElementFactory.importFor( |
| 1552 ElementFactory.library(_definingLibrary.context, "lib"), |
| 1553 ElementFactory.prefix(prefixName)); |
| 1554 _definingLibrary.imports = <ImportElement>[importElement]; |
| 1555 ImportDirective directive = AstFactory.importDirective3(null, prefixName); |
| 1556 directive.element = importElement; |
| 1557 _resolveNode(directive); |
| 1558 _listener.assertNoErrors(); |
| 1559 } |
| 1560 |
| 1561 void test_visitImportDirective_withCombinators() { |
| 1562 ShowCombinator combinator = AstFactory.showCombinator2(["A", "B", "C"]); |
| 1563 ImportDirective directive = |
| 1564 AstFactory.importDirective3(null, null, [combinator]); |
| 1565 LibraryElementImpl library = |
| 1566 ElementFactory.library(_definingLibrary.context, "lib"); |
| 1567 TopLevelVariableElementImpl varA = |
| 1568 ElementFactory.topLevelVariableElement2("A"); |
| 1569 TopLevelVariableElementImpl varB = |
| 1570 ElementFactory.topLevelVariableElement2("B"); |
| 1571 TopLevelVariableElementImpl varC = |
| 1572 ElementFactory.topLevelVariableElement2("C"); |
| 1573 CompilationUnitElementImpl unit = |
| 1574 library.definingCompilationUnit as CompilationUnitElementImpl; |
| 1575 unit.accessors = <PropertyAccessorElement>[ |
| 1576 varA.getter, |
| 1577 varA.setter, |
| 1578 varB.getter, |
| 1579 varC.setter |
| 1580 ]; |
| 1581 unit.topLevelVariables = <TopLevelVariableElement>[varA, varB, varC]; |
| 1582 directive.element = ElementFactory.importFor(library, null); |
| 1583 _resolveNode(directive); |
| 1584 expect(combinator.shownNames[0].staticElement, same(varA)); |
| 1585 expect(combinator.shownNames[1].staticElement, same(varB)); |
| 1586 expect(combinator.shownNames[2].staticElement, same(varC)); |
| 1587 _listener.assertNoErrors(); |
| 1588 } |
| 1589 |
| 1590 void test_visitIndexExpression_get() { |
| 1591 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1592 InterfaceType intType = _typeProvider.intType; |
| 1593 MethodElement getter = |
| 1594 ElementFactory.methodElement("[]", intType, [intType]); |
| 1595 classA.methods = <MethodElement>[getter]; |
| 1596 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 1597 array.staticType = classA.type; |
| 1598 IndexExpression expression = |
| 1599 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 1600 expect(_resolveIndexExpression(expression), same(getter)); |
| 1601 _listener.assertNoErrors(); |
| 1602 } |
| 1603 |
| 1604 void test_visitIndexExpression_set() { |
| 1605 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1606 InterfaceType intType = _typeProvider.intType; |
| 1607 MethodElement setter = |
| 1608 ElementFactory.methodElement("[]=", intType, [intType]); |
| 1609 classA.methods = <MethodElement>[setter]; |
| 1610 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 1611 array.staticType = classA.type; |
| 1612 IndexExpression expression = |
| 1613 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 1614 AstFactory.assignmentExpression( |
| 1615 expression, TokenType.EQ, AstFactory.integer(0)); |
| 1616 expect(_resolveIndexExpression(expression), same(setter)); |
| 1617 _listener.assertNoErrors(); |
| 1618 } |
| 1619 |
| 1620 void test_visitInstanceCreationExpression_named() { |
| 1621 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1622 String constructorName = "a"; |
| 1623 ConstructorElement constructor = |
| 1624 ElementFactory.constructorElement2(classA, constructorName); |
| 1625 classA.constructors = <ConstructorElement>[constructor]; |
| 1626 ConstructorName name = AstFactory.constructorName( |
| 1627 AstFactory.typeName(classA), constructorName); |
| 1628 name.staticElement = constructor; |
| 1629 InstanceCreationExpression creation = |
| 1630 AstFactory.instanceCreationExpression(Keyword.NEW, name); |
| 1631 _resolveNode(creation); |
| 1632 expect(creation.staticElement, same(constructor)); |
| 1633 _listener.assertNoErrors(); |
| 1634 } |
| 1635 |
| 1636 void test_visitInstanceCreationExpression_unnamed() { |
| 1637 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1638 String constructorName = null; |
| 1639 ConstructorElement constructor = |
| 1640 ElementFactory.constructorElement2(classA, constructorName); |
| 1641 classA.constructors = <ConstructorElement>[constructor]; |
| 1642 ConstructorName name = AstFactory.constructorName( |
| 1643 AstFactory.typeName(classA), constructorName); |
| 1644 name.staticElement = constructor; |
| 1645 InstanceCreationExpression creation = |
| 1646 AstFactory.instanceCreationExpression(Keyword.NEW, name); |
| 1647 _resolveNode(creation); |
| 1648 expect(creation.staticElement, same(constructor)); |
| 1649 _listener.assertNoErrors(); |
| 1650 } |
| 1651 |
| 1652 void test_visitInstanceCreationExpression_unnamed_namedParameter() { |
| 1653 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1654 String constructorName = null; |
| 1655 ConstructorElementImpl constructor = |
| 1656 ElementFactory.constructorElement2(classA, constructorName); |
| 1657 String parameterName = "a"; |
| 1658 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 1659 constructor.parameters = <ParameterElement>[parameter]; |
| 1660 classA.constructors = <ConstructorElement>[constructor]; |
| 1661 ConstructorName name = AstFactory.constructorName( |
| 1662 AstFactory.typeName(classA), constructorName); |
| 1663 name.staticElement = constructor; |
| 1664 InstanceCreationExpression creation = AstFactory.instanceCreationExpression( |
| 1665 Keyword.NEW, |
| 1666 name, |
| 1667 [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]); |
| 1668 _resolveNode(creation); |
| 1669 expect(creation.staticElement, same(constructor)); |
| 1670 expect( |
| 1671 (creation.argumentList.arguments[0] as NamedExpression) |
| 1672 .name |
| 1673 .label |
| 1674 .staticElement, |
| 1675 same(parameter)); |
| 1676 _listener.assertNoErrors(); |
| 1677 } |
| 1678 |
| 1679 void test_visitMethodInvocation() { |
| 1680 InterfaceType numType = _typeProvider.numType; |
| 1681 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1682 left.staticType = numType; |
| 1683 String methodName = "abs"; |
| 1684 MethodInvocation invocation = AstFactory.methodInvocation(left, methodName); |
| 1685 _resolveNode(invocation); |
| 1686 expect(invocation.methodName.staticElement, |
| 1687 same(getMethod(numType, methodName))); |
| 1688 _listener.assertNoErrors(); |
| 1689 } |
| 1690 |
| 1691 void test_visitMethodInvocation_namedParameter() { |
| 1692 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1693 String methodName = "m"; |
| 1694 String parameterName = "p"; |
| 1695 MethodElementImpl method = ElementFactory.methodElement(methodName, null); |
| 1696 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 1697 method.parameters = <ParameterElement>[parameter]; |
| 1698 classA.methods = <MethodElement>[method]; |
| 1699 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1700 left.staticType = classA.type; |
| 1701 MethodInvocation invocation = AstFactory.methodInvocation(left, methodName, |
| 1702 [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]); |
| 1703 _resolveNode(invocation); |
| 1704 expect(invocation.methodName.staticElement, same(method)); |
| 1705 expect( |
| 1706 (invocation.argumentList.arguments[0] as NamedExpression) |
| 1707 .name |
| 1708 .label |
| 1709 .staticElement, |
| 1710 same(parameter)); |
| 1711 _listener.assertNoErrors(); |
| 1712 } |
| 1713 |
| 1714 void test_visitPostfixExpression() { |
| 1715 InterfaceType numType = _typeProvider.numType; |
| 1716 SimpleIdentifier operand = AstFactory.identifier3("i"); |
| 1717 operand.staticType = numType; |
| 1718 PostfixExpression expression = |
| 1719 AstFactory.postfixExpression(operand, TokenType.PLUS_PLUS); |
| 1720 _resolveNode(expression); |
| 1721 expect(expression.staticElement, getMethod(numType, "+")); |
| 1722 _listener.assertNoErrors(); |
| 1723 } |
| 1724 |
| 1725 void test_visitPrefixedIdentifier_dynamic() { |
| 1726 DartType dynamicType = _typeProvider.dynamicType; |
| 1727 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 1728 VariableElementImpl variable = ElementFactory.localVariableElement(target); |
| 1729 variable.type = dynamicType; |
| 1730 target.staticElement = variable; |
| 1731 target.staticType = dynamicType; |
| 1732 PrefixedIdentifier identifier = |
| 1733 AstFactory.identifier(target, AstFactory.identifier3("b")); |
| 1734 _resolveNode(identifier); |
| 1735 expect(identifier.staticElement, isNull); |
| 1736 expect(identifier.identifier.staticElement, isNull); |
| 1737 _listener.assertNoErrors(); |
| 1738 } |
| 1739 |
| 1740 void test_visitPrefixedIdentifier_nonDynamic() { |
| 1741 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1742 String getterName = "b"; |
| 1743 PropertyAccessorElement getter = |
| 1744 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 1745 classA.accessors = <PropertyAccessorElement>[getter]; |
| 1746 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 1747 VariableElementImpl variable = ElementFactory.localVariableElement(target); |
| 1748 variable.type = classA.type; |
| 1749 target.staticElement = variable; |
| 1750 target.staticType = classA.type; |
| 1751 PrefixedIdentifier identifier = |
| 1752 AstFactory.identifier(target, AstFactory.identifier3(getterName)); |
| 1753 _resolveNode(identifier); |
| 1754 expect(identifier.staticElement, same(getter)); |
| 1755 expect(identifier.identifier.staticElement, same(getter)); |
| 1756 _listener.assertNoErrors(); |
| 1757 } |
| 1758 |
| 1759 void test_visitPrefixedIdentifier_staticClassMember_getter() { |
| 1760 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1761 // set accessors |
| 1762 String propName = "b"; |
| 1763 PropertyAccessorElement getter = |
| 1764 ElementFactory.getterElement(propName, false, _typeProvider.intType); |
| 1765 PropertyAccessorElement setter = |
| 1766 ElementFactory.setterElement(propName, false, _typeProvider.intType); |
| 1767 classA.accessors = <PropertyAccessorElement>[getter, setter]; |
| 1768 // prepare "A.m" |
| 1769 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 1770 target.staticElement = classA; |
| 1771 target.staticType = classA.type; |
| 1772 PrefixedIdentifier identifier = |
| 1773 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 1774 // resolve |
| 1775 _resolveNode(identifier); |
| 1776 expect(identifier.staticElement, same(getter)); |
| 1777 expect(identifier.identifier.staticElement, same(getter)); |
| 1778 _listener.assertNoErrors(); |
| 1779 } |
| 1780 |
| 1781 void test_visitPrefixedIdentifier_staticClassMember_method() { |
| 1782 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1783 // set methods |
| 1784 String propName = "m"; |
| 1785 MethodElement method = |
| 1786 ElementFactory.methodElement("m", _typeProvider.intType); |
| 1787 classA.methods = <MethodElement>[method]; |
| 1788 // prepare "A.m" |
| 1789 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 1790 target.staticElement = classA; |
| 1791 target.staticType = classA.type; |
| 1792 PrefixedIdentifier identifier = |
| 1793 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 1794 AstFactory.assignmentExpression( |
| 1795 identifier, TokenType.EQ, AstFactory.nullLiteral()); |
| 1796 // resolve |
| 1797 _resolveNode(identifier); |
| 1798 expect(identifier.staticElement, same(method)); |
| 1799 expect(identifier.identifier.staticElement, same(method)); |
| 1800 _listener.assertNoErrors(); |
| 1801 } |
| 1802 |
| 1803 void test_visitPrefixedIdentifier_staticClassMember_setter() { |
| 1804 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1805 // set accessors |
| 1806 String propName = "b"; |
| 1807 PropertyAccessorElement getter = |
| 1808 ElementFactory.getterElement(propName, false, _typeProvider.intType); |
| 1809 PropertyAccessorElement setter = |
| 1810 ElementFactory.setterElement(propName, false, _typeProvider.intType); |
| 1811 classA.accessors = <PropertyAccessorElement>[getter, setter]; |
| 1812 // prepare "A.b = null" |
| 1813 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 1814 target.staticElement = classA; |
| 1815 target.staticType = classA.type; |
| 1816 PrefixedIdentifier identifier = |
| 1817 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 1818 AstFactory.assignmentExpression( |
| 1819 identifier, TokenType.EQ, AstFactory.nullLiteral()); |
| 1820 // resolve |
| 1821 _resolveNode(identifier); |
| 1822 expect(identifier.staticElement, same(setter)); |
| 1823 expect(identifier.identifier.staticElement, same(setter)); |
| 1824 _listener.assertNoErrors(); |
| 1825 } |
| 1826 |
| 1827 void test_visitPrefixExpression() { |
| 1828 InterfaceType numType = _typeProvider.numType; |
| 1829 SimpleIdentifier operand = AstFactory.identifier3("i"); |
| 1830 operand.staticType = numType; |
| 1831 PrefixExpression expression = |
| 1832 AstFactory.prefixExpression(TokenType.PLUS_PLUS, operand); |
| 1833 _resolveNode(expression); |
| 1834 expect(expression.staticElement, getMethod(numType, "+")); |
| 1835 _listener.assertNoErrors(); |
| 1836 } |
| 1837 |
| 1838 void test_visitPropertyAccess_getter_identifier() { |
| 1839 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1840 String getterName = "b"; |
| 1841 PropertyAccessorElement getter = |
| 1842 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 1843 classA.accessors = <PropertyAccessorElement>[getter]; |
| 1844 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 1845 target.staticType = classA.type; |
| 1846 PropertyAccess access = AstFactory.propertyAccess2(target, getterName); |
| 1847 _resolveNode(access); |
| 1848 expect(access.propertyName.staticElement, same(getter)); |
| 1849 _listener.assertNoErrors(); |
| 1850 } |
| 1851 |
| 1852 void test_visitPropertyAccess_getter_super() { |
| 1853 // |
| 1854 // class A { |
| 1855 // int get b; |
| 1856 // } |
| 1857 // class B { |
| 1858 // ... super.m ... |
| 1859 // } |
| 1860 // |
| 1861 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1862 String getterName = "b"; |
| 1863 PropertyAccessorElement getter = |
| 1864 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 1865 classA.accessors = <PropertyAccessorElement>[getter]; |
| 1866 SuperExpression target = AstFactory.superExpression(); |
| 1867 target.staticType = ElementFactory.classElement("B", classA.type).type; |
| 1868 PropertyAccess access = AstFactory.propertyAccess2(target, getterName); |
| 1869 AstFactory.methodDeclaration2( |
| 1870 null, |
| 1871 null, |
| 1872 null, |
| 1873 null, |
| 1874 AstFactory.identifier3("m"), |
| 1875 AstFactory.formalParameterList(), |
| 1876 AstFactory.expressionFunctionBody(access)); |
| 1877 _resolveNode(access); |
| 1878 expect(access.propertyName.staticElement, same(getter)); |
| 1879 _listener.assertNoErrors(); |
| 1880 } |
| 1881 |
| 1882 void test_visitPropertyAccess_setter_this() { |
| 1883 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1884 String setterName = "b"; |
| 1885 PropertyAccessorElement setter = |
| 1886 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 1887 classA.accessors = <PropertyAccessorElement>[setter]; |
| 1888 ThisExpression target = AstFactory.thisExpression(); |
| 1889 target.staticType = classA.type; |
| 1890 PropertyAccess access = AstFactory.propertyAccess2(target, setterName); |
| 1891 AstFactory.assignmentExpression( |
| 1892 access, TokenType.EQ, AstFactory.integer(0)); |
| 1893 _resolveNode(access); |
| 1894 expect(access.propertyName.staticElement, same(setter)); |
| 1895 _listener.assertNoErrors(); |
| 1896 } |
| 1897 |
| 1898 void test_visitSimpleIdentifier_classScope() { |
| 1899 InterfaceType doubleType = _typeProvider.doubleType; |
| 1900 String fieldName = "NAN"; |
| 1901 SimpleIdentifier node = AstFactory.identifier3(fieldName); |
| 1902 _resolveInClass(node, doubleType.element); |
| 1903 expect(node.staticElement, getGetter(doubleType, fieldName)); |
| 1904 _listener.assertNoErrors(); |
| 1905 } |
| 1906 |
| 1907 void test_visitSimpleIdentifier_dynamic() { |
| 1908 SimpleIdentifier node = AstFactory.identifier3("dynamic"); |
| 1909 _resolveIdentifier(node); |
| 1910 expect(node.staticElement, same(_typeProvider.dynamicType.element)); |
| 1911 expect(node.staticType, same(_typeProvider.typeType)); |
| 1912 _listener.assertNoErrors(); |
| 1913 } |
| 1914 |
| 1915 void test_visitSimpleIdentifier_lexicalScope() { |
| 1916 SimpleIdentifier node = AstFactory.identifier3("i"); |
| 1917 VariableElementImpl element = ElementFactory.localVariableElement(node); |
| 1918 expect(_resolveIdentifier(node, [element]), same(element)); |
| 1919 _listener.assertNoErrors(); |
| 1920 } |
| 1921 |
| 1922 void test_visitSimpleIdentifier_lexicalScope_field_setter() { |
| 1923 InterfaceType intType = _typeProvider.intType; |
| 1924 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1925 String fieldName = "a"; |
| 1926 FieldElement field = |
| 1927 ElementFactory.fieldElement(fieldName, false, false, false, intType); |
| 1928 classA.fields = <FieldElement>[field]; |
| 1929 classA.accessors = <PropertyAccessorElement>[field.getter, field.setter]; |
| 1930 SimpleIdentifier node = AstFactory.identifier3(fieldName); |
| 1931 AstFactory.assignmentExpression(node, TokenType.EQ, AstFactory.integer(0)); |
| 1932 _resolveInClass(node, classA); |
| 1933 Element element = node.staticElement; |
| 1934 EngineTestCase.assertInstanceOf((obj) => obj is PropertyAccessorElement, |
| 1935 PropertyAccessorElement, element); |
| 1936 expect((element as PropertyAccessorElement).isSetter, isTrue); |
| 1937 _listener.assertNoErrors(); |
| 1938 } |
| 1939 |
| 1940 void test_visitSuperConstructorInvocation() { |
| 1941 ClassElementImpl superclass = ElementFactory.classElement2("A"); |
| 1942 ConstructorElementImpl superConstructor = |
| 1943 ElementFactory.constructorElement2(superclass, null); |
| 1944 superclass.constructors = <ConstructorElement>[superConstructor]; |
| 1945 ClassElementImpl subclass = |
| 1946 ElementFactory.classElement("B", superclass.type); |
| 1947 ConstructorElementImpl subConstructor = |
| 1948 ElementFactory.constructorElement2(subclass, null); |
| 1949 subclass.constructors = <ConstructorElement>[subConstructor]; |
| 1950 SuperConstructorInvocation invocation = |
| 1951 AstFactory.superConstructorInvocation(); |
| 1952 _resolveInClass(invocation, subclass); |
| 1953 expect(invocation.staticElement, superConstructor); |
| 1954 _listener.assertNoErrors(); |
| 1955 } |
| 1956 |
| 1957 void test_visitSuperConstructorInvocation_namedParameter() { |
| 1958 ClassElementImpl superclass = ElementFactory.classElement2("A"); |
| 1959 ConstructorElementImpl superConstructor = |
| 1960 ElementFactory.constructorElement2(superclass, null); |
| 1961 String parameterName = "p"; |
| 1962 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 1963 superConstructor.parameters = <ParameterElement>[parameter]; |
| 1964 superclass.constructors = <ConstructorElement>[superConstructor]; |
| 1965 ClassElementImpl subclass = |
| 1966 ElementFactory.classElement("B", superclass.type); |
| 1967 ConstructorElementImpl subConstructor = |
| 1968 ElementFactory.constructorElement2(subclass, null); |
| 1969 subclass.constructors = <ConstructorElement>[subConstructor]; |
| 1970 SuperConstructorInvocation invocation = AstFactory |
| 1971 .superConstructorInvocation([ |
| 1972 AstFactory.namedExpression2(parameterName, AstFactory.integer(0)) |
| 1973 ]); |
| 1974 _resolveInClass(invocation, subclass); |
| 1975 expect(invocation.staticElement, superConstructor); |
| 1976 expect( |
| 1977 (invocation.argumentList.arguments[0] as NamedExpression) |
| 1978 .name |
| 1979 .label |
| 1980 .staticElement, |
| 1981 same(parameter)); |
| 1982 _listener.assertNoErrors(); |
| 1983 } |
| 1984 |
| 1985 /** |
| 1986 * Create the resolver used by the tests. |
| 1987 * |
| 1988 * @return the resolver that was created |
| 1989 */ |
| 1990 ElementResolver _createResolver() { |
| 1991 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 1992 FileBasedSource source = |
| 1993 new FileBasedSource(FileUtilities2.createFile("/test.dart")); |
| 1994 CompilationUnitElementImpl definingCompilationUnit = |
| 1995 new CompilationUnitElementImpl("test.dart"); |
| 1996 definingCompilationUnit.librarySource = |
| 1997 definingCompilationUnit.source = source; |
| 1998 _definingLibrary = ElementFactory.library(context, "test"); |
| 1999 _definingLibrary.definingCompilationUnit = definingCompilationUnit; |
| 2000 Library library = new Library(context, _listener, source); |
| 2001 library.libraryElement = _definingLibrary; |
| 2002 _visitor = new ResolverVisitor( |
| 2003 library.libraryElement, source, _typeProvider, library.errorListener, |
| 2004 nameScope: library.libraryScope, |
| 2005 inheritanceManager: library.inheritanceManager); |
| 2006 try { |
| 2007 return _visitor.elementResolver; |
| 2008 } catch (exception) { |
| 2009 throw new IllegalArgumentException( |
| 2010 "Could not create resolver", exception); |
| 2011 } |
| 2012 } |
| 2013 |
| 2014 /** |
| 2015 * Return the element associated with the label of [statement] after the |
| 2016 * resolver has resolved it. [labelElement] is the label element to be |
| 2017 * defined in the statement's label scope, and [labelTarget] is the statement |
| 2018 * the label resolves to. |
| 2019 */ |
| 2020 Element _resolveBreak(BreakStatement statement, LabelElementImpl labelElement, |
| 2021 Statement labelTarget) { |
| 2022 _resolveStatement(statement, labelElement, labelTarget); |
| 2023 return statement.label.staticElement; |
| 2024 } |
| 2025 |
| 2026 /** |
| 2027 * Return the element associated with the label [statement] after the |
| 2028 * resolver has resolved it. [labelElement] is the label element to be |
| 2029 * defined in the statement's label scope, and [labelTarget] is the AST node |
| 2030 * the label resolves to. |
| 2031 * |
| 2032 * @param statement the statement to be resolved |
| 2033 * @param labelElement the label element to be defined in the statement's labe
l scope |
| 2034 * @return the element to which the statement's label was resolved |
| 2035 */ |
| 2036 Element _resolveContinue(ContinueStatement statement, |
| 2037 LabelElementImpl labelElement, AstNode labelTarget) { |
| 2038 _resolveStatement(statement, labelElement, labelTarget); |
| 2039 return statement.label.staticElement; |
| 2040 } |
| 2041 |
| 2042 /** |
| 2043 * Return the element associated with the given identifier after the resolver
has resolved the |
| 2044 * identifier. |
| 2045 * |
| 2046 * @param node the expression to be resolved |
| 2047 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 2048 * being resolved |
| 2049 * @return the element to which the expression was resolved |
| 2050 */ |
| 2051 Element _resolveIdentifier(Identifier node, [List<Element> definedElements]) { |
| 2052 _resolveNode(node, definedElements); |
| 2053 return node.staticElement; |
| 2054 } |
| 2055 |
| 2056 /** |
| 2057 * Return the element associated with the given identifier after the resolver
has resolved the |
| 2058 * identifier. |
| 2059 * |
| 2060 * @param node the expression to be resolved |
| 2061 * @param enclosingClass the element representing the class enclosing the iden
tifier |
| 2062 * @return the element to which the expression was resolved |
| 2063 */ |
| 2064 void _resolveInClass(AstNode node, ClassElement enclosingClass) { |
| 2065 try { |
| 2066 Scope outerScope = _visitor.nameScope; |
| 2067 try { |
| 2068 _visitor.enclosingClass = enclosingClass; |
| 2069 EnclosedScope innerScope = new ClassScope( |
| 2070 new TypeParameterScope(outerScope, enclosingClass), enclosingClass); |
| 2071 _visitor.nameScope = innerScope; |
| 2072 node.accept(_resolver); |
| 2073 } finally { |
| 2074 _visitor.enclosingClass = null; |
| 2075 _visitor.nameScope = outerScope; |
| 2076 } |
| 2077 } catch (exception) { |
| 2078 throw new IllegalArgumentException("Could not resolve node", exception); |
| 2079 } |
| 2080 } |
| 2081 |
| 2082 /** |
| 2083 * Return the element associated with the given expression after the resolver
has resolved the |
| 2084 * expression. |
| 2085 * |
| 2086 * @param node the expression to be resolved |
| 2087 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 2088 * being resolved |
| 2089 * @return the element to which the expression was resolved |
| 2090 */ |
| 2091 Element _resolveIndexExpression(IndexExpression node, |
| 2092 [List<Element> definedElements]) { |
| 2093 _resolveNode(node, definedElements); |
| 2094 return node.staticElement; |
| 2095 } |
| 2096 |
| 2097 /** |
| 2098 * Return the element associated with the given identifier after the resolver
has resolved the |
| 2099 * identifier. |
| 2100 * |
| 2101 * @param node the expression to be resolved |
| 2102 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 2103 * being resolved |
| 2104 * @return the element to which the expression was resolved |
| 2105 */ |
| 2106 void _resolveNode(AstNode node, [List<Element> definedElements]) { |
| 2107 try { |
| 2108 Scope outerScope = _visitor.nameScope; |
| 2109 try { |
| 2110 EnclosedScope innerScope = new EnclosedScope(outerScope); |
| 2111 if (definedElements != null) { |
| 2112 for (Element element in definedElements) { |
| 2113 innerScope.define(element); |
| 2114 } |
| 2115 } |
| 2116 _visitor.nameScope = innerScope; |
| 2117 node.accept(_resolver); |
| 2118 } finally { |
| 2119 _visitor.nameScope = outerScope; |
| 2120 } |
| 2121 } catch (exception) { |
| 2122 throw new IllegalArgumentException("Could not resolve node", exception); |
| 2123 } |
| 2124 } |
| 2125 |
| 2126 /** |
| 2127 * Return the element associated with the label of the given statement after t
he resolver has |
| 2128 * resolved the statement. |
| 2129 * |
| 2130 * @param statement the statement to be resolved |
| 2131 * @param labelElement the label element to be defined in the statement's labe
l scope |
| 2132 * @return the element to which the statement's label was resolved |
| 2133 */ |
| 2134 void _resolveStatement( |
| 2135 Statement statement, LabelElementImpl labelElement, AstNode labelTarget) { |
| 2136 try { |
| 2137 LabelScope outerScope = _visitor.labelScope; |
| 2138 try { |
| 2139 LabelScope innerScope; |
| 2140 if (labelElement == null) { |
| 2141 innerScope = outerScope; |
| 2142 } else { |
| 2143 innerScope = new LabelScope( |
| 2144 outerScope, labelElement.name, labelTarget, labelElement); |
| 2145 } |
| 2146 _visitor.labelScope = innerScope; |
| 2147 statement.accept(_resolver); |
| 2148 } finally { |
| 2149 _visitor.labelScope = outerScope; |
| 2150 } |
| 2151 } catch (exception) { |
| 2152 throw new IllegalArgumentException("Could not resolve node", exception); |
| 2153 } |
| 2154 } |
| 2155 } |
| 2156 |
| 2157 @reflectiveTest |
| 2158 class EnclosedScopeTest extends ResolverTestCase { |
| 2159 void test_define_duplicate() { |
| 2160 GatheringErrorListener listener = new GatheringErrorListener(); |
| 2161 Scope rootScope = |
| 2162 new Scope_EnclosedScopeTest_test_define_duplicate(listener); |
| 2163 EnclosedScope scope = new EnclosedScope(rootScope); |
| 2164 VariableElement element1 = |
| 2165 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 2166 VariableElement element2 = |
| 2167 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 2168 scope.define(element1); |
| 2169 scope.define(element2); |
| 2170 listener.assertErrorsWithSeverities([ErrorSeverity.ERROR]); |
| 2171 } |
| 2172 |
| 2173 void test_define_normal() { |
| 2174 GatheringErrorListener listener = new GatheringErrorListener(); |
| 2175 Scope rootScope = new Scope_EnclosedScopeTest_test_define_normal(listener); |
| 2176 EnclosedScope outerScope = new EnclosedScope(rootScope); |
| 2177 EnclosedScope innerScope = new EnclosedScope(outerScope); |
| 2178 VariableElement element1 = |
| 2179 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 2180 VariableElement element2 = |
| 2181 ElementFactory.localVariableElement(AstFactory.identifier3("v2")); |
| 2182 outerScope.define(element1); |
| 2183 innerScope.define(element2); |
| 2184 listener.assertNoErrors(); |
| 2185 } |
| 2186 } |
| 2187 |
| 2188 @reflectiveTest |
| 2189 class ErrorResolverTest extends ResolverTestCase { |
| 2190 void test_breakLabelOnSwitchMember() { |
| 2191 Source source = addSource(r''' |
| 2192 class A { |
| 2193 void m(int i) { |
| 2194 switch (i) { |
| 2195 l: case 0: |
| 2196 break; |
| 2197 case 1: |
| 2198 break l; |
| 2199 } |
| 2200 } |
| 2201 }'''); |
| 2202 computeLibrarySourceErrors(source); |
| 2203 assertErrors(source, [ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER]); |
| 2204 verify([source]); |
| 2205 } |
| 2206 |
| 2207 void test_continueLabelOnSwitch() { |
| 2208 Source source = addSource(r''' |
| 2209 class A { |
| 2210 void m(int i) { |
| 2211 l: switch (i) { |
| 2212 case 0: |
| 2213 continue l; |
| 2214 } |
| 2215 } |
| 2216 }'''); |
| 2217 computeLibrarySourceErrors(source); |
| 2218 assertErrors(source, [ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH]); |
| 2219 verify([source]); |
| 2220 } |
| 2221 |
| 2222 void test_enclosingElement_invalidLocalFunction() { |
| 2223 Source source = addSource(r''' |
| 2224 class C { |
| 2225 C() { |
| 2226 int get x => 0; |
| 2227 } |
| 2228 }'''); |
| 2229 LibraryElement library = resolve2(source); |
| 2230 expect(library, isNotNull); |
| 2231 var unit = library.definingCompilationUnit; |
| 2232 expect(unit, isNotNull); |
| 2233 var types = unit.types; |
| 2234 expect(types, isNotNull); |
| 2235 expect(types, hasLength(1)); |
| 2236 var type = types[0]; |
| 2237 expect(type, isNotNull); |
| 2238 var constructors = type.constructors; |
| 2239 expect(constructors, isNotNull); |
| 2240 expect(constructors, hasLength(1)); |
| 2241 ConstructorElement constructor = constructors[0]; |
| 2242 expect(constructor, isNotNull); |
| 2243 List<FunctionElement> functions = constructor.functions; |
| 2244 expect(functions, isNotNull); |
| 2245 expect(functions, hasLength(1)); |
| 2246 expect(functions[0].enclosingElement, constructor); |
| 2247 assertErrors(source, [ParserErrorCode.GETTER_IN_FUNCTION]); |
| 2248 } |
| 2249 } |
| 2250 |
| 2251 @reflectiveTest |
| 2252 class HintCodeTest extends ResolverTestCase { |
| 2253 void fail_deadCode_statementAfterRehrow() { |
| 2254 Source source = addSource(r''' |
| 2255 f() { |
| 2256 try { |
| 2257 var one = 1; |
| 2258 } catch (e) { |
| 2259 rethrow; |
| 2260 var two = 2; |
| 2261 } |
| 2262 }'''); |
| 2263 computeLibrarySourceErrors(source); |
| 2264 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2265 verify([source]); |
| 2266 } |
| 2267 |
| 2268 void fail_deadCode_statementAfterThrow() { |
| 2269 Source source = addSource(r''' |
| 2270 f() { |
| 2271 var one = 1; |
| 2272 throw 'Stop here'; |
| 2273 var two = 2; |
| 2274 }'''); |
| 2275 computeLibrarySourceErrors(source); |
| 2276 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2277 verify([source]); |
| 2278 } |
| 2279 |
| 2280 void fail_isInt() { |
| 2281 Source source = addSource("var v = 1 is int;"); |
| 2282 computeLibrarySourceErrors(source); |
| 2283 assertErrors(source, [HintCode.IS_INT]); |
| 2284 verify([source]); |
| 2285 } |
| 2286 |
| 2287 void fail_isNotInt() { |
| 2288 Source source = addSource("var v = 1 is! int;"); |
| 2289 computeLibrarySourceErrors(source); |
| 2290 assertErrors(source, [HintCode.IS_NOT_INT]); |
| 2291 verify([source]); |
| 2292 } |
| 2293 |
| 2294 void fail_overrideEqualsButNotHashCode() { |
| 2295 Source source = addSource(r''' |
| 2296 class A { |
| 2297 bool operator ==(x) {} |
| 2298 }'''); |
| 2299 computeLibrarySourceErrors(source); |
| 2300 assertErrors(source, [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]); |
| 2301 verify([source]); |
| 2302 } |
| 2303 |
| 2304 void fail_unusedImport_as_equalPrefixes() { |
| 2305 // See todo at ImportsVerifier.prefixElementMap. |
| 2306 Source source = addSource(r''' |
| 2307 library L; |
| 2308 import 'lib1.dart' as one; |
| 2309 import 'lib2.dart' as one; |
| 2310 one.A a;'''); |
| 2311 Source source2 = addNamedSource( |
| 2312 "/lib1.dart", |
| 2313 r''' |
| 2314 library lib1; |
| 2315 class A {}'''); |
| 2316 Source source3 = addNamedSource( |
| 2317 "/lib2.dart", |
| 2318 r''' |
| 2319 library lib2; |
| 2320 class B {}'''); |
| 2321 computeLibrarySourceErrors(source); |
| 2322 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 2323 assertNoErrors(source2); |
| 2324 assertNoErrors(source3); |
| 2325 verify([source, source2, source3]); |
| 2326 } |
| 2327 |
| 2328 void test_argumentTypeNotAssignable_functionType() { |
| 2329 Source source = addSource(r''' |
| 2330 m() { |
| 2331 var a = new A(); |
| 2332 a.n(() => 0); |
| 2333 } |
| 2334 class A { |
| 2335 n(void f(int i)) {} |
| 2336 }'''); |
| 2337 computeLibrarySourceErrors(source); |
| 2338 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); |
| 2339 verify([source]); |
| 2340 } |
| 2341 |
| 2342 void test_argumentTypeNotAssignable_message() { |
| 2343 // The implementation of HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE assumes that |
| 2344 // StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE has the same message. |
| 2345 expect(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE.message, |
| 2346 HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE.message); |
| 2347 } |
| 2348 |
| 2349 void test_argumentTypeNotAssignable_type() { |
| 2350 Source source = addSource(r''' |
| 2351 m() { |
| 2352 var i = ''; |
| 2353 n(i); |
| 2354 } |
| 2355 n(int i) {}'''); |
| 2356 computeLibrarySourceErrors(source); |
| 2357 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); |
| 2358 verify([source]); |
| 2359 } |
| 2360 |
| 2361 void test_deadCode_deadBlock_conditionalElse() { |
| 2362 Source source = addSource(r''' |
| 2363 f() { |
| 2364 true ? 1 : 2; |
| 2365 }'''); |
| 2366 computeLibrarySourceErrors(source); |
| 2367 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2368 verify([source]); |
| 2369 } |
| 2370 |
| 2371 void test_deadCode_deadBlock_conditionalElse_nested() { |
| 2372 // test that a dead else-statement can't generate additional violations |
| 2373 Source source = addSource(r''' |
| 2374 f() { |
| 2375 true ? true : false && false; |
| 2376 }'''); |
| 2377 computeLibrarySourceErrors(source); |
| 2378 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2379 verify([source]); |
| 2380 } |
| 2381 |
| 2382 void test_deadCode_deadBlock_conditionalIf() { |
| 2383 Source source = addSource(r''' |
| 2384 f() { |
| 2385 false ? 1 : 2; |
| 2386 }'''); |
| 2387 computeLibrarySourceErrors(source); |
| 2388 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2389 verify([source]); |
| 2390 } |
| 2391 |
| 2392 void test_deadCode_deadBlock_conditionalIf_nested() { |
| 2393 // test that a dead then-statement can't generate additional violations |
| 2394 Source source = addSource(r''' |
| 2395 f() { |
| 2396 false ? false && false : true; |
| 2397 }'''); |
| 2398 computeLibrarySourceErrors(source); |
| 2399 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2400 verify([source]); |
| 2401 } |
| 2402 |
| 2403 void test_deadCode_deadBlock_else() { |
| 2404 Source source = addSource(r''' |
| 2405 f() { |
| 2406 if(true) {} else {} |
| 2407 }'''); |
| 2408 computeLibrarySourceErrors(source); |
| 2409 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2410 verify([source]); |
| 2411 } |
| 2412 |
| 2413 void test_deadCode_deadBlock_else_nested() { |
| 2414 // test that a dead else-statement can't generate additional violations |
| 2415 Source source = addSource(r''' |
| 2416 f() { |
| 2417 if(true) {} else {if (false) {}} |
| 2418 }'''); |
| 2419 computeLibrarySourceErrors(source); |
| 2420 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2421 verify([source]); |
| 2422 } |
| 2423 |
| 2424 void test_deadCode_deadBlock_if() { |
| 2425 Source source = addSource(r''' |
| 2426 f() { |
| 2427 if(false) {} |
| 2428 }'''); |
| 2429 computeLibrarySourceErrors(source); |
| 2430 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2431 verify([source]); |
| 2432 } |
| 2433 |
| 2434 void test_deadCode_deadBlock_if_nested() { |
| 2435 // test that a dead then-statement can't generate additional violations |
| 2436 Source source = addSource(r''' |
| 2437 f() { |
| 2438 if(false) {if(false) {}} |
| 2439 }'''); |
| 2440 computeLibrarySourceErrors(source); |
| 2441 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2442 verify([source]); |
| 2443 } |
| 2444 |
| 2445 void test_deadCode_deadBlock_while() { |
| 2446 Source source = addSource(r''' |
| 2447 f() { |
| 2448 while(false) {} |
| 2449 }'''); |
| 2450 computeLibrarySourceErrors(source); |
| 2451 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2452 verify([source]); |
| 2453 } |
| 2454 |
| 2455 void test_deadCode_deadBlock_while_nested() { |
| 2456 // test that a dead while body can't generate additional violations |
| 2457 Source source = addSource(r''' |
| 2458 f() { |
| 2459 while(false) {if(false) {}} |
| 2460 }'''); |
| 2461 computeLibrarySourceErrors(source); |
| 2462 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2463 verify([source]); |
| 2464 } |
| 2465 |
| 2466 void test_deadCode_deadCatch_catchFollowingCatch() { |
| 2467 Source source = addSource(r''' |
| 2468 class A {} |
| 2469 f() { |
| 2470 try {} catch (e) {} catch (e) {} |
| 2471 }'''); |
| 2472 computeLibrarySourceErrors(source); |
| 2473 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); |
| 2474 verify([source]); |
| 2475 } |
| 2476 |
| 2477 void test_deadCode_deadCatch_catchFollowingCatch_nested() { |
| 2478 // test that a dead catch clause can't generate additional violations |
| 2479 Source source = addSource(r''' |
| 2480 class A {} |
| 2481 f() { |
| 2482 try {} catch (e) {} catch (e) {if(false) {}} |
| 2483 }'''); |
| 2484 computeLibrarySourceErrors(source); |
| 2485 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); |
| 2486 verify([source]); |
| 2487 } |
| 2488 |
| 2489 void test_deadCode_deadCatch_catchFollowingCatch_object() { |
| 2490 Source source = addSource(r''' |
| 2491 f() { |
| 2492 try {} on Object catch (e) {} catch (e) {} |
| 2493 }'''); |
| 2494 computeLibrarySourceErrors(source); |
| 2495 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); |
| 2496 verify([source]); |
| 2497 } |
| 2498 |
| 2499 void test_deadCode_deadCatch_catchFollowingCatch_object_nested() { |
| 2500 // test that a dead catch clause can't generate additional violations |
| 2501 Source source = addSource(r''' |
| 2502 f() { |
| 2503 try {} on Object catch (e) {} catch (e) {if(false) {}} |
| 2504 }'''); |
| 2505 computeLibrarySourceErrors(source); |
| 2506 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); |
| 2507 verify([source]); |
| 2508 } |
| 2509 |
| 2510 void test_deadCode_deadCatch_onCatchSubtype() { |
| 2511 Source source = addSource(r''' |
| 2512 class A {} |
| 2513 class B extends A {} |
| 2514 f() { |
| 2515 try {} on A catch (e) {} on B catch (e) {} |
| 2516 }'''); |
| 2517 computeLibrarySourceErrors(source); |
| 2518 assertErrors(source, [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]); |
| 2519 verify([source]); |
| 2520 } |
| 2521 |
| 2522 void test_deadCode_deadCatch_onCatchSubtype_nested() { |
| 2523 // test that a dead catch clause can't generate additional violations |
| 2524 Source source = addSource(r''' |
| 2525 class A {} |
| 2526 class B extends A {} |
| 2527 f() { |
| 2528 try {} on A catch (e) {} on B catch (e) {if(false) {}} |
| 2529 }'''); |
| 2530 computeLibrarySourceErrors(source); |
| 2531 assertErrors(source, [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]); |
| 2532 verify([source]); |
| 2533 } |
| 2534 |
| 2535 void test_deadCode_deadOperandLHS_and() { |
| 2536 Source source = addSource(r''' |
| 2537 f() { |
| 2538 bool b = false && false; |
| 2539 }'''); |
| 2540 computeLibrarySourceErrors(source); |
| 2541 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2542 verify([source]); |
| 2543 } |
| 2544 |
| 2545 void test_deadCode_deadOperandLHS_and_nested() { |
| 2546 Source source = addSource(r''' |
| 2547 f() { |
| 2548 bool b = false && (false && false); |
| 2549 }'''); |
| 2550 computeLibrarySourceErrors(source); |
| 2551 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2552 verify([source]); |
| 2553 } |
| 2554 |
| 2555 void test_deadCode_deadOperandLHS_or() { |
| 2556 Source source = addSource(r''' |
| 2557 f() { |
| 2558 bool b = true || true; |
| 2559 }'''); |
| 2560 computeLibrarySourceErrors(source); |
| 2561 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2562 verify([source]); |
| 2563 } |
| 2564 |
| 2565 void test_deadCode_deadOperandLHS_or_nested() { |
| 2566 Source source = addSource(r''' |
| 2567 f() { |
| 2568 bool b = true || (false && false); |
| 2569 }'''); |
| 2570 computeLibrarySourceErrors(source); |
| 2571 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2572 verify([source]); |
| 2573 } |
| 2574 |
| 2575 void test_deadCode_statementAfterBreak_inDefaultCase() { |
| 2576 Source source = addSource(r''' |
| 2577 f(v) { |
| 2578 switch(v) { |
| 2579 case 1: |
| 2580 default: |
| 2581 break; |
| 2582 var a; |
| 2583 } |
| 2584 }'''); |
| 2585 computeLibrarySourceErrors(source); |
| 2586 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2587 verify([source]); |
| 2588 } |
| 2589 |
| 2590 void test_deadCode_statementAfterBreak_inForEachStatement() { |
| 2591 Source source = addSource(r''' |
| 2592 f() { |
| 2593 var list; |
| 2594 for(var l in list) { |
| 2595 break; |
| 2596 var a; |
| 2597 } |
| 2598 }'''); |
| 2599 computeLibrarySourceErrors(source); |
| 2600 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2601 verify([source]); |
| 2602 } |
| 2603 |
| 2604 void test_deadCode_statementAfterBreak_inForStatement() { |
| 2605 Source source = addSource(r''' |
| 2606 f() { |
| 2607 for(;;) { |
| 2608 break; |
| 2609 var a; |
| 2610 } |
| 2611 }'''); |
| 2612 computeLibrarySourceErrors(source); |
| 2613 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2614 verify([source]); |
| 2615 } |
| 2616 |
| 2617 void test_deadCode_statementAfterBreak_inSwitchCase() { |
| 2618 Source source = addSource(r''' |
| 2619 f(v) { |
| 2620 switch(v) { |
| 2621 case 1: |
| 2622 break; |
| 2623 var a; |
| 2624 } |
| 2625 }'''); |
| 2626 computeLibrarySourceErrors(source); |
| 2627 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2628 verify([source]); |
| 2629 } |
| 2630 |
| 2631 void test_deadCode_statementAfterBreak_inWhileStatement() { |
| 2632 Source source = addSource(r''' |
| 2633 f(v) { |
| 2634 while(v) { |
| 2635 break; |
| 2636 var a; |
| 2637 } |
| 2638 }'''); |
| 2639 computeLibrarySourceErrors(source); |
| 2640 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2641 verify([source]); |
| 2642 } |
| 2643 |
| 2644 void test_deadCode_statementAfterContinue_inForEachStatement() { |
| 2645 Source source = addSource(r''' |
| 2646 f() { |
| 2647 var list; |
| 2648 for(var l in list) { |
| 2649 continue; |
| 2650 var a; |
| 2651 } |
| 2652 }'''); |
| 2653 computeLibrarySourceErrors(source); |
| 2654 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2655 verify([source]); |
| 2656 } |
| 2657 |
| 2658 void test_deadCode_statementAfterContinue_inForStatement() { |
| 2659 Source source = addSource(r''' |
| 2660 f() { |
| 2661 for(;;) { |
| 2662 continue; |
| 2663 var a; |
| 2664 } |
| 2665 }'''); |
| 2666 computeLibrarySourceErrors(source); |
| 2667 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2668 verify([source]); |
| 2669 } |
| 2670 |
| 2671 void test_deadCode_statementAfterContinue_inWhileStatement() { |
| 2672 Source source = addSource(r''' |
| 2673 f(v) { |
| 2674 while(v) { |
| 2675 continue; |
| 2676 var a; |
| 2677 } |
| 2678 }'''); |
| 2679 computeLibrarySourceErrors(source); |
| 2680 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2681 verify([source]); |
| 2682 } |
| 2683 |
| 2684 void test_deadCode_statementAfterReturn_function() { |
| 2685 Source source = addSource(r''' |
| 2686 f() { |
| 2687 var one = 1; |
| 2688 return; |
| 2689 var two = 2; |
| 2690 }'''); |
| 2691 computeLibrarySourceErrors(source); |
| 2692 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2693 verify([source]); |
| 2694 } |
| 2695 |
| 2696 void test_deadCode_statementAfterReturn_ifStatement() { |
| 2697 Source source = addSource(r''' |
| 2698 f(bool b) { |
| 2699 if(b) { |
| 2700 var one = 1; |
| 2701 return; |
| 2702 var two = 2; |
| 2703 } |
| 2704 }'''); |
| 2705 computeLibrarySourceErrors(source); |
| 2706 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2707 verify([source]); |
| 2708 } |
| 2709 |
| 2710 void test_deadCode_statementAfterReturn_method() { |
| 2711 Source source = addSource(r''' |
| 2712 class A { |
| 2713 m() { |
| 2714 var one = 1; |
| 2715 return; |
| 2716 var two = 2; |
| 2717 } |
| 2718 }'''); |
| 2719 computeLibrarySourceErrors(source); |
| 2720 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2721 verify([source]); |
| 2722 } |
| 2723 |
| 2724 void test_deadCode_statementAfterReturn_nested() { |
| 2725 Source source = addSource(r''' |
| 2726 f() { |
| 2727 var one = 1; |
| 2728 return; |
| 2729 if(false) {} |
| 2730 }'''); |
| 2731 computeLibrarySourceErrors(source); |
| 2732 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2733 verify([source]); |
| 2734 } |
| 2735 |
| 2736 void test_deadCode_statementAfterReturn_twoReturns() { |
| 2737 Source source = addSource(r''' |
| 2738 f() { |
| 2739 var one = 1; |
| 2740 return; |
| 2741 var two = 2; |
| 2742 return; |
| 2743 var three = 3; |
| 2744 }'''); |
| 2745 computeLibrarySourceErrors(source); |
| 2746 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2747 verify([source]); |
| 2748 } |
| 2749 |
| 2750 void test_deprecatedAnnotationUse_assignment() { |
| 2751 Source source = addSource(r''' |
| 2752 class A { |
| 2753 @deprecated |
| 2754 A operator+(A a) { return a; } |
| 2755 } |
| 2756 f(A a) { |
| 2757 A b; |
| 2758 a += b; |
| 2759 }'''); |
| 2760 computeLibrarySourceErrors(source); |
| 2761 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2762 verify([source]); |
| 2763 } |
| 2764 |
| 2765 void test_deprecatedAnnotationUse_Deprecated() { |
| 2766 Source source = addSource(r''' |
| 2767 class A { |
| 2768 @Deprecated('0.9') |
| 2769 m() {} |
| 2770 n() {m();} |
| 2771 }'''); |
| 2772 computeLibrarySourceErrors(source); |
| 2773 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2774 verify([source]); |
| 2775 } |
| 2776 |
| 2777 void test_deprecatedAnnotationUse_deprecated() { |
| 2778 Source source = addSource(r''' |
| 2779 class A { |
| 2780 @deprecated |
| 2781 m() {} |
| 2782 n() {m();} |
| 2783 }'''); |
| 2784 computeLibrarySourceErrors(source); |
| 2785 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2786 verify([source]); |
| 2787 } |
| 2788 |
| 2789 void test_deprecatedAnnotationUse_export() { |
| 2790 Source source = addSource("export 'deprecated_library.dart';"); |
| 2791 addNamedSource( |
| 2792 "/deprecated_library.dart", |
| 2793 r''' |
| 2794 @deprecated |
| 2795 library deprecated_library; |
| 2796 class A {}'''); |
| 2797 computeLibrarySourceErrors(source); |
| 2798 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2799 verify([source]); |
| 2800 } |
| 2801 |
| 2802 void test_deprecatedAnnotationUse_getter() { |
| 2803 Source source = addSource(r''' |
| 2804 class A { |
| 2805 @deprecated |
| 2806 get m => 1; |
| 2807 } |
| 2808 f(A a) { |
| 2809 return a.m; |
| 2810 }'''); |
| 2811 computeLibrarySourceErrors(source); |
| 2812 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2813 verify([source]); |
| 2814 } |
| 2815 |
| 2816 void test_deprecatedAnnotationUse_import() { |
| 2817 Source source = addSource(r''' |
| 2818 import 'deprecated_library.dart'; |
| 2819 f(A a) {}'''); |
| 2820 addNamedSource( |
| 2821 "/deprecated_library.dart", |
| 2822 r''' |
| 2823 @deprecated |
| 2824 library deprecated_library; |
| 2825 class A {}'''); |
| 2826 computeLibrarySourceErrors(source); |
| 2827 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2828 verify([source]); |
| 2829 } |
| 2830 |
| 2831 void test_deprecatedAnnotationUse_indexExpression() { |
| 2832 Source source = addSource(r''' |
| 2833 class A { |
| 2834 @deprecated |
| 2835 operator[](int i) {} |
| 2836 } |
| 2837 f(A a) { |
| 2838 return a[1]; |
| 2839 }'''); |
| 2840 computeLibrarySourceErrors(source); |
| 2841 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2842 verify([source]); |
| 2843 } |
| 2844 |
| 2845 void test_deprecatedAnnotationUse_instanceCreation() { |
| 2846 Source source = addSource(r''' |
| 2847 class A { |
| 2848 @deprecated |
| 2849 A(int i) {} |
| 2850 } |
| 2851 f() { |
| 2852 A a = new A(1); |
| 2853 }'''); |
| 2854 computeLibrarySourceErrors(source); |
| 2855 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2856 verify([source]); |
| 2857 } |
| 2858 |
| 2859 void test_deprecatedAnnotationUse_instanceCreation_namedConstructor() { |
| 2860 Source source = addSource(r''' |
| 2861 class A { |
| 2862 @deprecated |
| 2863 A.named(int i) {} |
| 2864 } |
| 2865 f() { |
| 2866 A a = new A.named(1); |
| 2867 }'''); |
| 2868 computeLibrarySourceErrors(source); |
| 2869 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2870 verify([source]); |
| 2871 } |
| 2872 |
| 2873 void test_deprecatedAnnotationUse_operator() { |
| 2874 Source source = addSource(r''' |
| 2875 class A { |
| 2876 @deprecated |
| 2877 operator+(A a) {} |
| 2878 } |
| 2879 f(A a) { |
| 2880 A b; |
| 2881 return a + b; |
| 2882 }'''); |
| 2883 computeLibrarySourceErrors(source); |
| 2884 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2885 verify([source]); |
| 2886 } |
| 2887 |
| 2888 void test_deprecatedAnnotationUse_setter() { |
| 2889 Source source = addSource(r''' |
| 2890 class A { |
| 2891 @deprecated |
| 2892 set s(v) {} |
| 2893 } |
| 2894 f(A a) { |
| 2895 return a.s = 1; |
| 2896 }'''); |
| 2897 computeLibrarySourceErrors(source); |
| 2898 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2899 verify([source]); |
| 2900 } |
| 2901 |
| 2902 void test_deprecatedAnnotationUse_superConstructor() { |
| 2903 Source source = addSource(r''' |
| 2904 class A { |
| 2905 @deprecated |
| 2906 A() {} |
| 2907 } |
| 2908 class B extends A { |
| 2909 B() : super() {} |
| 2910 }'''); |
| 2911 computeLibrarySourceErrors(source); |
| 2912 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2913 verify([source]); |
| 2914 } |
| 2915 |
| 2916 void test_deprecatedAnnotationUse_superConstructor_namedConstructor() { |
| 2917 Source source = addSource(r''' |
| 2918 class A { |
| 2919 @deprecated |
| 2920 A.named() {} |
| 2921 } |
| 2922 class B extends A { |
| 2923 B() : super.named() {} |
| 2924 }'''); |
| 2925 computeLibrarySourceErrors(source); |
| 2926 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2927 verify([source]); |
| 2928 } |
| 2929 |
| 2930 void test_divisionOptimization_double() { |
| 2931 Source source = addSource(r''' |
| 2932 f(double x, double y) { |
| 2933 var v = (x / y).toInt(); |
| 2934 }'''); |
| 2935 computeLibrarySourceErrors(source); |
| 2936 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); |
| 2937 verify([source]); |
| 2938 } |
| 2939 |
| 2940 void test_divisionOptimization_int() { |
| 2941 Source source = addSource(r''' |
| 2942 f(int x, int y) { |
| 2943 var v = (x / y).toInt(); |
| 2944 }'''); |
| 2945 computeLibrarySourceErrors(source); |
| 2946 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); |
| 2947 verify([source]); |
| 2948 } |
| 2949 |
| 2950 void test_divisionOptimization_propagatedType() { |
| 2951 // Tests the propagated type information of the '/' method |
| 2952 Source source = addSource(r''' |
| 2953 f(x, y) { |
| 2954 x = 1; |
| 2955 y = 1; |
| 2956 var v = (x / y).toInt(); |
| 2957 }'''); |
| 2958 computeLibrarySourceErrors(source); |
| 2959 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); |
| 2960 verify([source]); |
| 2961 } |
| 2962 |
| 2963 void test_divisionOptimization_wrappedBinaryExpression() { |
| 2964 Source source = addSource(r''' |
| 2965 f(int x, int y) { |
| 2966 var v = (((x / y))).toInt(); |
| 2967 }'''); |
| 2968 computeLibrarySourceErrors(source); |
| 2969 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); |
| 2970 verify([source]); |
| 2971 } |
| 2972 |
| 2973 void test_duplicateImport() { |
| 2974 Source source = addSource(r''' |
| 2975 library L; |
| 2976 import 'lib1.dart'; |
| 2977 import 'lib1.dart'; |
| 2978 A a;'''); |
| 2979 addNamedSource( |
| 2980 "/lib1.dart", |
| 2981 r''' |
| 2982 library lib1; |
| 2983 class A {}'''); |
| 2984 computeLibrarySourceErrors(source); |
| 2985 assertErrors(source, [HintCode.DUPLICATE_IMPORT]); |
| 2986 verify([source]); |
| 2987 } |
| 2988 |
| 2989 void test_duplicateImport2() { |
| 2990 Source source = addSource(r''' |
| 2991 library L; |
| 2992 import 'lib1.dart'; |
| 2993 import 'lib1.dart'; |
| 2994 import 'lib1.dart'; |
| 2995 A a;'''); |
| 2996 addNamedSource( |
| 2997 "/lib1.dart", |
| 2998 r''' |
| 2999 library lib1; |
| 3000 class A {}'''); |
| 3001 computeLibrarySourceErrors(source); |
| 3002 assertErrors( |
| 3003 source, [HintCode.DUPLICATE_IMPORT, HintCode.DUPLICATE_IMPORT]); |
| 3004 verify([source]); |
| 3005 } |
| 3006 |
| 3007 void test_duplicateImport3() { |
| 3008 Source source = addSource(r''' |
| 3009 library L; |
| 3010 import 'lib1.dart' as M show A hide B; |
| 3011 import 'lib1.dart' as M show A hide B; |
| 3012 M.A a;'''); |
| 3013 addNamedSource( |
| 3014 "/lib1.dart", |
| 3015 r''' |
| 3016 library lib1; |
| 3017 class A {} |
| 3018 class B {}'''); |
| 3019 computeLibrarySourceErrors(source); |
| 3020 assertErrors(source, [HintCode.DUPLICATE_IMPORT]); |
| 3021 verify([source]); |
| 3022 } |
| 3023 |
| 3024 void test_importDeferredLibraryWithLoadFunction() { |
| 3025 resolveWithErrors(<String>[ |
| 3026 r''' |
| 3027 library lib1; |
| 3028 loadLibrary() {} |
| 3029 f() {}''', |
| 3030 r''' |
| 3031 library root; |
| 3032 import 'lib1.dart' deferred as lib1; |
| 3033 main() { lib1.f(); }''' |
| 3034 ], <ErrorCode>[ |
| 3035 HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION |
| 3036 ]); |
| 3037 } |
| 3038 |
| 3039 void test_invalidAssignment_instanceVariable() { |
| 3040 Source source = addSource(r''' |
| 3041 class A { |
| 3042 int x; |
| 3043 } |
| 3044 f(var y) { |
| 3045 A a; |
| 3046 if(y is String) { |
| 3047 a.x = y; |
| 3048 } |
| 3049 }'''); |
| 3050 computeLibrarySourceErrors(source); |
| 3051 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 3052 verify([source]); |
| 3053 } |
| 3054 |
| 3055 void test_invalidAssignment_localVariable() { |
| 3056 Source source = addSource(r''' |
| 3057 f(var y) { |
| 3058 if(y is String) { |
| 3059 int x = y; |
| 3060 } |
| 3061 }'''); |
| 3062 computeLibrarySourceErrors(source); |
| 3063 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 3064 verify([source]); |
| 3065 } |
| 3066 |
| 3067 void test_invalidAssignment_message() { |
| 3068 // The implementation of HintCode.INVALID_ASSIGNMENT assumes that |
| 3069 // StaticTypeWarningCode.INVALID_ASSIGNMENT has the same message. |
| 3070 expect(StaticTypeWarningCode.INVALID_ASSIGNMENT.message, |
| 3071 HintCode.INVALID_ASSIGNMENT.message); |
| 3072 } |
| 3073 |
| 3074 void test_invalidAssignment_staticVariable() { |
| 3075 Source source = addSource(r''' |
| 3076 class A { |
| 3077 static int x; |
| 3078 } |
| 3079 f(var y) { |
| 3080 if(y is String) { |
| 3081 A.x = y; |
| 3082 } |
| 3083 }'''); |
| 3084 computeLibrarySourceErrors(source); |
| 3085 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 3086 verify([source]); |
| 3087 } |
| 3088 |
| 3089 void test_invalidAssignment_variableDeclaration() { |
| 3090 // 17971 |
| 3091 Source source = addSource(r''' |
| 3092 class Point { |
| 3093 final num x, y; |
| 3094 Point(this.x, this.y); |
| 3095 Point operator +(Point other) { |
| 3096 return new Point(x+other.x, y+other.y); |
| 3097 } |
| 3098 } |
| 3099 main() { |
| 3100 var p1 = new Point(0, 0); |
| 3101 var p2 = new Point(10, 10); |
| 3102 int n = p1 + p2; |
| 3103 }'''); |
| 3104 computeLibrarySourceErrors(source); |
| 3105 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 3106 verify([source]); |
| 3107 } |
| 3108 |
| 3109 void test_isDouble() { |
| 3110 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 3111 options.dart2jsHint = true; |
| 3112 resetWithOptions(options); |
| 3113 Source source = addSource("var v = 1 is double;"); |
| 3114 computeLibrarySourceErrors(source); |
| 3115 assertErrors(source, [HintCode.IS_DOUBLE]); |
| 3116 verify([source]); |
| 3117 } |
| 3118 |
| 3119 void test_isNotDouble() { |
| 3120 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 3121 options.dart2jsHint = true; |
| 3122 resetWithOptions(options); |
| 3123 Source source = addSource("var v = 1 is! double;"); |
| 3124 computeLibrarySourceErrors(source); |
| 3125 assertErrors(source, [HintCode.IS_NOT_DOUBLE]); |
| 3126 verify([source]); |
| 3127 } |
| 3128 |
| 3129 void test_missingReturn_async() { |
| 3130 Source source = addSource(''' |
| 3131 import 'dart:async'; |
| 3132 Future<int> f() async {} |
| 3133 '''); |
| 3134 computeLibrarySourceErrors(source); |
| 3135 assertErrors(source, [HintCode.MISSING_RETURN]); |
| 3136 verify([source]); |
| 3137 } |
| 3138 |
| 3139 void test_missingReturn_function() { |
| 3140 Source source = addSource("int f() {}"); |
| 3141 computeLibrarySourceErrors(source); |
| 3142 assertErrors(source, [HintCode.MISSING_RETURN]); |
| 3143 verify([source]); |
| 3144 } |
| 3145 |
| 3146 void test_missingReturn_method() { |
| 3147 Source source = addSource(r''' |
| 3148 class A { |
| 3149 int m() {} |
| 3150 }'''); |
| 3151 computeLibrarySourceErrors(source); |
| 3152 assertErrors(source, [HintCode.MISSING_RETURN]); |
| 3153 verify([source]); |
| 3154 } |
| 3155 |
| 3156 void test_overrideOnNonOverridingGetter_invalid() { |
| 3157 Source source = addSource(r''' |
| 3158 library dart.core; |
| 3159 const override = null; |
| 3160 class A { |
| 3161 } |
| 3162 class B extends A { |
| 3163 @override |
| 3164 int get m => 1; |
| 3165 }'''); |
| 3166 computeLibrarySourceErrors(source); |
| 3167 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER]); |
| 3168 verify([source]); |
| 3169 } |
| 3170 |
| 3171 void test_overrideOnNonOverridingMethod_invalid() { |
| 3172 Source source = addSource(r''' |
| 3173 library dart.core; |
| 3174 const override = null; |
| 3175 class A { |
| 3176 } |
| 3177 class B extends A { |
| 3178 @override |
| 3179 int m() => 1; |
| 3180 }'''); |
| 3181 computeLibrarySourceErrors(source); |
| 3182 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD]); |
| 3183 verify([source]); |
| 3184 } |
| 3185 |
| 3186 void test_overrideOnNonOverridingSetter_invalid() { |
| 3187 Source source = addSource(r''' |
| 3188 library dart.core; |
| 3189 const override = null; |
| 3190 class A { |
| 3191 } |
| 3192 class B extends A { |
| 3193 @override |
| 3194 set m(int x) {} |
| 3195 }'''); |
| 3196 computeLibrarySourceErrors(source); |
| 3197 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER]); |
| 3198 verify([source]); |
| 3199 } |
| 3200 |
| 3201 void test_typeCheck_type_is_Null() { |
| 3202 Source source = addSource(r''' |
| 3203 m(i) { |
| 3204 bool b = i is Null; |
| 3205 }'''); |
| 3206 computeLibrarySourceErrors(source); |
| 3207 assertErrors(source, [HintCode.TYPE_CHECK_IS_NULL]); |
| 3208 verify([source]); |
| 3209 } |
| 3210 |
| 3211 void test_typeCheck_type_not_Null() { |
| 3212 Source source = addSource(r''' |
| 3213 m(i) { |
| 3214 bool b = i is! Null; |
| 3215 }'''); |
| 3216 computeLibrarySourceErrors(source); |
| 3217 assertErrors(source, [HintCode.TYPE_CHECK_IS_NOT_NULL]); |
| 3218 verify([source]); |
| 3219 } |
| 3220 |
| 3221 void test_undefinedGetter() { |
| 3222 Source source = addSource(r''' |
| 3223 class A {} |
| 3224 f(var a) { |
| 3225 if(a is A) { |
| 3226 return a.m; |
| 3227 } |
| 3228 }'''); |
| 3229 computeLibrarySourceErrors(source); |
| 3230 assertErrors(source, [HintCode.UNDEFINED_GETTER]); |
| 3231 } |
| 3232 |
| 3233 void test_undefinedGetter_message() { |
| 3234 // The implementation of HintCode.UNDEFINED_SETTER assumes that |
| 3235 // UNDEFINED_SETTER in StaticTypeWarningCode and StaticWarningCode are the |
| 3236 // same, this verifies that assumption. |
| 3237 expect(StaticWarningCode.UNDEFINED_GETTER.message, |
| 3238 StaticTypeWarningCode.UNDEFINED_GETTER.message); |
| 3239 } |
| 3240 |
| 3241 void test_undefinedMethod() { |
| 3242 Source source = addSource(r''' |
| 3243 f() { |
| 3244 var a = 'str'; |
| 3245 a.notAMethodOnString(); |
| 3246 }'''); |
| 3247 computeLibrarySourceErrors(source); |
| 3248 assertErrors(source, [HintCode.UNDEFINED_METHOD]); |
| 3249 } |
| 3250 |
| 3251 void test_undefinedMethod_assignmentExpression() { |
| 3252 Source source = addSource(r''' |
| 3253 class A {} |
| 3254 class B { |
| 3255 f(var a, var a2) { |
| 3256 a = new A(); |
| 3257 a2 = new A(); |
| 3258 a += a2; |
| 3259 } |
| 3260 }'''); |
| 3261 computeLibrarySourceErrors(source); |
| 3262 assertErrors(source, [HintCode.UNDEFINED_METHOD]); |
| 3263 } |
| 3264 |
| 3265 void test_undefinedOperator_binaryExpression() { |
| 3266 Source source = addSource(r''' |
| 3267 class A {} |
| 3268 f(var a) { |
| 3269 if(a is A) { |
| 3270 a + 1; |
| 3271 } |
| 3272 }'''); |
| 3273 computeLibrarySourceErrors(source); |
| 3274 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3275 } |
| 3276 |
| 3277 void test_undefinedOperator_indexBoth() { |
| 3278 Source source = addSource(r''' |
| 3279 class A {} |
| 3280 f(var a) { |
| 3281 if(a is A) { |
| 3282 a[0]++; |
| 3283 } |
| 3284 }'''); |
| 3285 computeLibrarySourceErrors(source); |
| 3286 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3287 } |
| 3288 |
| 3289 void test_undefinedOperator_indexGetter() { |
| 3290 Source source = addSource(r''' |
| 3291 class A {} |
| 3292 f(var a) { |
| 3293 if(a is A) { |
| 3294 a[0]; |
| 3295 } |
| 3296 }'''); |
| 3297 computeLibrarySourceErrors(source); |
| 3298 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3299 } |
| 3300 |
| 3301 void test_undefinedOperator_indexSetter() { |
| 3302 Source source = addSource(r''' |
| 3303 class A {} |
| 3304 f(var a) { |
| 3305 if(a is A) { |
| 3306 a[0] = 1; |
| 3307 } |
| 3308 }'''); |
| 3309 computeLibrarySourceErrors(source); |
| 3310 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3311 } |
| 3312 |
| 3313 void test_undefinedOperator_postfixExpression() { |
| 3314 Source source = addSource(r''' |
| 3315 class A {} |
| 3316 f(var a) { |
| 3317 if(a is A) { |
| 3318 a++; |
| 3319 } |
| 3320 }'''); |
| 3321 computeLibrarySourceErrors(source); |
| 3322 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3323 } |
| 3324 |
| 3325 void test_undefinedOperator_prefixExpression() { |
| 3326 Source source = addSource(r''' |
| 3327 class A {} |
| 3328 f(var a) { |
| 3329 if(a is A) { |
| 3330 ++a; |
| 3331 } |
| 3332 }'''); |
| 3333 computeLibrarySourceErrors(source); |
| 3334 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3335 } |
| 3336 |
| 3337 void test_undefinedSetter() { |
| 3338 Source source = addSource(r''' |
| 3339 class A {} |
| 3340 f(var a) { |
| 3341 if(a is A) { |
| 3342 a.m = 0; |
| 3343 } |
| 3344 }'''); |
| 3345 computeLibrarySourceErrors(source); |
| 3346 assertErrors(source, [HintCode.UNDEFINED_SETTER]); |
| 3347 } |
| 3348 |
| 3349 void test_undefinedSetter_message() { |
| 3350 // The implementation of HintCode.UNDEFINED_SETTER assumes that |
| 3351 // UNDEFINED_SETTER in StaticTypeWarningCode and StaticWarningCode are the |
| 3352 // same, this verifies that assumption. |
| 3353 expect(StaticWarningCode.UNDEFINED_SETTER.message, |
| 3354 StaticTypeWarningCode.UNDEFINED_SETTER.message); |
| 3355 } |
| 3356 |
| 3357 void test_unnecessaryCast_type_supertype() { |
| 3358 Source source = addSource(r''' |
| 3359 m(int i) { |
| 3360 var b = i as Object; |
| 3361 }'''); |
| 3362 computeLibrarySourceErrors(source); |
| 3363 assertErrors(source, [HintCode.UNNECESSARY_CAST]); |
| 3364 verify([source]); |
| 3365 } |
| 3366 |
| 3367 void test_unnecessaryCast_type_type() { |
| 3368 Source source = addSource(r''' |
| 3369 m(num i) { |
| 3370 var b = i as num; |
| 3371 }'''); |
| 3372 computeLibrarySourceErrors(source); |
| 3373 assertErrors(source, [HintCode.UNNECESSARY_CAST]); |
| 3374 verify([source]); |
| 3375 } |
| 3376 |
| 3377 void test_unnecessaryTypeCheck_null_is_Null() { |
| 3378 Source source = addSource("bool b = null is Null;"); |
| 3379 computeLibrarySourceErrors(source); |
| 3380 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); |
| 3381 verify([source]); |
| 3382 } |
| 3383 |
| 3384 void test_unnecessaryTypeCheck_null_not_Null() { |
| 3385 Source source = addSource("bool b = null is! Null;"); |
| 3386 computeLibrarySourceErrors(source); |
| 3387 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); |
| 3388 verify([source]); |
| 3389 } |
| 3390 |
| 3391 void test_unnecessaryTypeCheck_type_is_dynamic() { |
| 3392 Source source = addSource(r''' |
| 3393 m(i) { |
| 3394 bool b = i is dynamic; |
| 3395 }'''); |
| 3396 computeLibrarySourceErrors(source); |
| 3397 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); |
| 3398 verify([source]); |
| 3399 } |
| 3400 |
| 3401 void test_unnecessaryTypeCheck_type_is_object() { |
| 3402 Source source = addSource(r''' |
| 3403 m(i) { |
| 3404 bool b = i is Object; |
| 3405 }'''); |
| 3406 computeLibrarySourceErrors(source); |
| 3407 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); |
| 3408 verify([source]); |
| 3409 } |
| 3410 |
| 3411 void test_unnecessaryTypeCheck_type_not_dynamic() { |
| 3412 Source source = addSource(r''' |
| 3413 m(i) { |
| 3414 bool b = i is! dynamic; |
| 3415 }'''); |
| 3416 computeLibrarySourceErrors(source); |
| 3417 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); |
| 3418 verify([source]); |
| 3419 } |
| 3420 |
| 3421 void test_unnecessaryTypeCheck_type_not_object() { |
| 3422 Source source = addSource(r''' |
| 3423 m(i) { |
| 3424 bool b = i is! Object; |
| 3425 }'''); |
| 3426 computeLibrarySourceErrors(source); |
| 3427 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); |
| 3428 verify([source]); |
| 3429 } |
| 3430 |
| 3431 void test_unusedElement_class_isUsed_extends() { |
| 3432 enableUnusedElement = true; |
| 3433 Source source = addSource(r''' |
| 3434 class _A {} |
| 3435 class B extends _A {} |
| 3436 '''); |
| 3437 computeLibrarySourceErrors(source); |
| 3438 assertNoErrors(source); |
| 3439 verify([source]); |
| 3440 } |
| 3441 |
| 3442 void test_unusedElement_class_isUsed_implements() { |
| 3443 enableUnusedElement = true; |
| 3444 Source source = addSource(r''' |
| 3445 class _A {} |
| 3446 class B implements _A {} |
| 3447 '''); |
| 3448 computeLibrarySourceErrors(source); |
| 3449 assertNoErrors(source); |
| 3450 verify([source]); |
| 3451 } |
| 3452 |
| 3453 void test_unusedElement_class_isUsed_instanceCreation() { |
| 3454 enableUnusedElement = true; |
| 3455 Source source = addSource(r''' |
| 3456 class _A {} |
| 3457 main() { |
| 3458 new _A(); |
| 3459 }'''); |
| 3460 computeLibrarySourceErrors(source); |
| 3461 assertNoErrors(source); |
| 3462 verify([source]); |
| 3463 } |
| 3464 |
| 3465 void test_unusedElement_class_isUsed_staticFieldAccess() { |
| 3466 enableUnusedElement = true; |
| 3467 Source source = addSource(r''' |
| 3468 class _A { |
| 3469 static const F = 42; |
| 3470 } |
| 3471 main() { |
| 3472 _A.F; |
| 3473 }'''); |
| 3474 computeLibrarySourceErrors(source); |
| 3475 assertNoErrors(source); |
| 3476 verify([source]); |
| 3477 } |
| 3478 |
| 3479 void test_unusedElement_class_isUsed_staticMethodInvocation() { |
| 3480 enableUnusedElement = true; |
| 3481 Source source = addSource(r''' |
| 3482 class _A { |
| 3483 static m() {} |
| 3484 } |
| 3485 main() { |
| 3486 _A.m(); |
| 3487 }'''); |
| 3488 computeLibrarySourceErrors(source); |
| 3489 assertNoErrors(source); |
| 3490 verify([source]); |
| 3491 } |
| 3492 |
| 3493 void test_unusedElement_class_isUsed_typeArgument() { |
| 3494 enableUnusedElement = true; |
| 3495 Source source = addSource(r''' |
| 3496 class _A {} |
| 3497 main() { |
| 3498 var v = new List<_A>(); |
| 3499 print(v); |
| 3500 }'''); |
| 3501 computeLibrarySourceErrors(source); |
| 3502 assertNoErrors(source); |
| 3503 verify([source]); |
| 3504 } |
| 3505 |
| 3506 void test_unusedElement_class_notUsed_inClassMember() { |
| 3507 enableUnusedElement = true; |
| 3508 Source source = addSource(r''' |
| 3509 class _A { |
| 3510 static staticMethod() { |
| 3511 new _A(); |
| 3512 } |
| 3513 instanceMethod() { |
| 3514 new _A(); |
| 3515 } |
| 3516 } |
| 3517 '''); |
| 3518 computeLibrarySourceErrors(source); |
| 3519 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3520 verify([source]); |
| 3521 } |
| 3522 |
| 3523 void test_unusedElement_class_notUsed_inConstructorName() { |
| 3524 enableUnusedElement = true; |
| 3525 Source source = addSource(r''' |
| 3526 class _A { |
| 3527 _A() {} |
| 3528 _A.named() {} |
| 3529 } |
| 3530 '''); |
| 3531 computeLibrarySourceErrors(source); |
| 3532 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3533 verify([source]); |
| 3534 } |
| 3535 |
| 3536 void test_unusedElement_class_notUsed_isExpression() { |
| 3537 enableUnusedElement = true; |
| 3538 Source source = addSource(r''' |
| 3539 class _A {} |
| 3540 main(p) { |
| 3541 if (p is _A) { |
| 3542 } |
| 3543 } |
| 3544 '''); |
| 3545 computeLibrarySourceErrors(source); |
| 3546 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3547 verify([source]); |
| 3548 } |
| 3549 |
| 3550 void test_unusedElement_class_notUsed_noReference() { |
| 3551 enableUnusedElement = true; |
| 3552 Source source = addSource(r''' |
| 3553 class _A {} |
| 3554 main() { |
| 3555 }'''); |
| 3556 computeLibrarySourceErrors(source); |
| 3557 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3558 verify([source]); |
| 3559 } |
| 3560 |
| 3561 void test_unusedElement_class_notUsed_variableDeclaration() { |
| 3562 enableUnusedElement = true; |
| 3563 Source source = addSource(r''' |
| 3564 class _A {} |
| 3565 main() { |
| 3566 _A v; |
| 3567 print(v); |
| 3568 } |
| 3569 print(x) {} |
| 3570 '''); |
| 3571 computeLibrarySourceErrors(source); |
| 3572 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3573 verify([source]); |
| 3574 } |
| 3575 |
| 3576 void test_unusedElement_enum_isUsed_fieldReference() { |
| 3577 enableUnusedElement = true; |
| 3578 Source source = addSource(r''' |
| 3579 enum _MyEnum {A, B, C} |
| 3580 main() { |
| 3581 print(_MyEnum.B); |
| 3582 }'''); |
| 3583 computeLibrarySourceErrors(source); |
| 3584 assertNoErrors(source); |
| 3585 verify([source]); |
| 3586 } |
| 3587 |
| 3588 void test_unusedElement_enum_notUsed_noReference() { |
| 3589 enableUnusedElement = true; |
| 3590 Source source = addSource(r''' |
| 3591 enum _MyEnum {A, B, C} |
| 3592 main() { |
| 3593 }'''); |
| 3594 computeLibrarySourceErrors(source); |
| 3595 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3596 verify([source]); |
| 3597 } |
| 3598 |
| 3599 void test_unusedElement_functionLocal_isUsed_closure() { |
| 3600 enableUnusedElement = true; |
| 3601 Source source = addSource(r''' |
| 3602 main() { |
| 3603 print(() {}); |
| 3604 } |
| 3605 print(x) {} |
| 3606 '''); |
| 3607 computeLibrarySourceErrors(source); |
| 3608 assertNoErrors(source); |
| 3609 verify([source]); |
| 3610 } |
| 3611 |
| 3612 void test_unusedElement_functionLocal_isUsed_invocation() { |
| 3613 enableUnusedElement = true; |
| 3614 Source source = addSource(r''' |
| 3615 main() { |
| 3616 f() {} |
| 3617 f(); |
| 3618 }'''); |
| 3619 computeLibrarySourceErrors(source); |
| 3620 assertNoErrors(source); |
| 3621 verify([source]); |
| 3622 } |
| 3623 |
| 3624 void test_unusedElement_functionLocal_isUsed_reference() { |
| 3625 enableUnusedElement = true; |
| 3626 Source source = addSource(r''' |
| 3627 main() { |
| 3628 f() {} |
| 3629 print(f); |
| 3630 } |
| 3631 print(x) {} |
| 3632 '''); |
| 3633 computeLibrarySourceErrors(source); |
| 3634 assertNoErrors(source); |
| 3635 verify([source]); |
| 3636 } |
| 3637 |
| 3638 void test_unusedElement_functionLocal_notUsed_noReference() { |
| 3639 enableUnusedElement = true; |
| 3640 Source source = addSource(r''' |
| 3641 main() { |
| 3642 f() {} |
| 3643 }'''); |
| 3644 computeLibrarySourceErrors(source); |
| 3645 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3646 verify([source]); |
| 3647 } |
| 3648 |
| 3649 void test_unusedElement_functionLocal_notUsed_referenceFromItself() { |
| 3650 enableUnusedElement = true; |
| 3651 Source source = addSource(r''' |
| 3652 main() { |
| 3653 _f(int p) { |
| 3654 _f(p - 1); |
| 3655 } |
| 3656 }'''); |
| 3657 computeLibrarySourceErrors(source); |
| 3658 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3659 verify([source]); |
| 3660 } |
| 3661 |
| 3662 void test_unusedElement_functionTop_isUsed_invocation() { |
| 3663 enableUnusedElement = true; |
| 3664 Source source = addSource(r''' |
| 3665 _f() {} |
| 3666 main() { |
| 3667 _f(); |
| 3668 }'''); |
| 3669 computeLibrarySourceErrors(source); |
| 3670 assertNoErrors(source); |
| 3671 verify([source]); |
| 3672 } |
| 3673 |
| 3674 void test_unusedElement_functionTop_isUsed_reference() { |
| 3675 enableUnusedElement = true; |
| 3676 Source source = addSource(r''' |
| 3677 _f() {} |
| 3678 main() { |
| 3679 print(_f); |
| 3680 } |
| 3681 print(x) {} |
| 3682 '''); |
| 3683 computeLibrarySourceErrors(source); |
| 3684 assertNoErrors(source); |
| 3685 verify([source]); |
| 3686 } |
| 3687 |
| 3688 void test_unusedElement_functionTop_notUsed_noReference() { |
| 3689 enableUnusedElement = true; |
| 3690 Source source = addSource(r''' |
| 3691 _f() {} |
| 3692 main() { |
| 3693 }'''); |
| 3694 computeLibrarySourceErrors(source); |
| 3695 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3696 verify([source]); |
| 3697 } |
| 3698 |
| 3699 void test_unusedElement_functionTop_notUsed_referenceFromItself() { |
| 3700 enableUnusedElement = true; |
| 3701 Source source = addSource(r''' |
| 3702 _f(int p) { |
| 3703 _f(p - 1); |
| 3704 } |
| 3705 main() { |
| 3706 }'''); |
| 3707 computeLibrarySourceErrors(source); |
| 3708 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3709 verify([source]); |
| 3710 } |
| 3711 |
| 3712 void test_unusedElement_functionTypeAlias_isUsed_isExpression() { |
| 3713 enableUnusedElement = true; |
| 3714 Source source = addSource(r''' |
| 3715 typedef _F(a, b); |
| 3716 main(f) { |
| 3717 if (f is _F) { |
| 3718 print('F'); |
| 3719 } |
| 3720 }'''); |
| 3721 computeLibrarySourceErrors(source); |
| 3722 assertNoErrors(source); |
| 3723 verify([source]); |
| 3724 } |
| 3725 |
| 3726 void test_unusedElement_functionTypeAlias_isUsed_reference() { |
| 3727 enableUnusedElement = true; |
| 3728 Source source = addSource(r''' |
| 3729 typedef _F(a, b); |
| 3730 main(_F f) { |
| 3731 }'''); |
| 3732 computeLibrarySourceErrors(source); |
| 3733 assertNoErrors(source); |
| 3734 verify([source]); |
| 3735 } |
| 3736 |
| 3737 void test_unusedElement_functionTypeAlias_isUsed_typeArgument() { |
| 3738 enableUnusedElement = true; |
| 3739 Source source = addSource(r''' |
| 3740 typedef _F(a, b); |
| 3741 main() { |
| 3742 var v = new List<_F>(); |
| 3743 print(v); |
| 3744 }'''); |
| 3745 computeLibrarySourceErrors(source); |
| 3746 assertNoErrors(source); |
| 3747 verify([source]); |
| 3748 } |
| 3749 |
| 3750 void test_unusedElement_functionTypeAlias_isUsed_variableDeclaration() { |
| 3751 enableUnusedElement = true; |
| 3752 Source source = addSource(r''' |
| 3753 typedef _F(a, b); |
| 3754 class A { |
| 3755 _F f; |
| 3756 }'''); |
| 3757 computeLibrarySourceErrors(source); |
| 3758 assertNoErrors(source); |
| 3759 verify([source]); |
| 3760 } |
| 3761 |
| 3762 void test_unusedElement_functionTypeAlias_notUsed_noReference() { |
| 3763 enableUnusedElement = true; |
| 3764 Source source = addSource(r''' |
| 3765 typedef _F(a, b); |
| 3766 main() { |
| 3767 }'''); |
| 3768 computeLibrarySourceErrors(source); |
| 3769 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3770 verify([source]); |
| 3771 } |
| 3772 |
| 3773 void test_unusedElement_getter_isUsed_invocation_implicitThis() { |
| 3774 enableUnusedElement = true; |
| 3775 Source source = addSource(r''' |
| 3776 class A { |
| 3777 get _g => null; |
| 3778 useGetter() { |
| 3779 var v = _g; |
| 3780 } |
| 3781 }'''); |
| 3782 computeLibrarySourceErrors(source); |
| 3783 assertNoErrors(source); |
| 3784 verify([source]); |
| 3785 } |
| 3786 |
| 3787 void test_unusedElement_getter_isUsed_invocation_PrefixedIdentifier() { |
| 3788 enableUnusedElement = true; |
| 3789 Source source = addSource(r''' |
| 3790 class A { |
| 3791 get _g => null; |
| 3792 } |
| 3793 main(A a) { |
| 3794 var v = a._g; |
| 3795 } |
| 3796 '''); |
| 3797 computeLibrarySourceErrors(source); |
| 3798 assertNoErrors(source); |
| 3799 verify([source]); |
| 3800 } |
| 3801 |
| 3802 void test_unusedElement_getter_isUsed_invocation_PropertyAccess() { |
| 3803 enableUnusedElement = true; |
| 3804 Source source = addSource(r''' |
| 3805 class A { |
| 3806 get _g => null; |
| 3807 } |
| 3808 main() { |
| 3809 var v = new A()._g; |
| 3810 } |
| 3811 '''); |
| 3812 computeLibrarySourceErrors(source); |
| 3813 assertNoErrors(source); |
| 3814 verify([source]); |
| 3815 } |
| 3816 |
| 3817 void test_unusedElement_getter_notUsed_noReference() { |
| 3818 enableUnusedElement = true; |
| 3819 Source source = addSource(r''' |
| 3820 class A { |
| 3821 get _g => null; |
| 3822 }'''); |
| 3823 computeLibrarySourceErrors(source); |
| 3824 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3825 verify([source]); |
| 3826 } |
| 3827 |
| 3828 void test_unusedElement_getter_notUsed_referenceFromItself() { |
| 3829 enableUnusedElement = true; |
| 3830 Source source = addSource(r''' |
| 3831 class A { |
| 3832 get _g { |
| 3833 return _g; |
| 3834 } |
| 3835 }'''); |
| 3836 computeLibrarySourceErrors(source); |
| 3837 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3838 verify([source]); |
| 3839 } |
| 3840 |
| 3841 void test_unusedElement_method_isUsed_hasReference_implicitThis() { |
| 3842 enableUnusedElement = true; |
| 3843 Source source = addSource(r''' |
| 3844 class A { |
| 3845 _m() {} |
| 3846 useMethod() { |
| 3847 print(_m); |
| 3848 } |
| 3849 } |
| 3850 print(x) {} |
| 3851 '''); |
| 3852 computeLibrarySourceErrors(source); |
| 3853 assertNoErrors(source); |
| 3854 verify([source]); |
| 3855 } |
| 3856 |
| 3857 void test_unusedElement_method_isUsed_hasReference_implicitThis_subclass() { |
| 3858 enableUnusedElement = true; |
| 3859 Source source = addSource(r''' |
| 3860 class A { |
| 3861 _m() {} |
| 3862 useMethod() { |
| 3863 print(_m); |
| 3864 } |
| 3865 } |
| 3866 class B extends A { |
| 3867 _m() {} |
| 3868 } |
| 3869 print(x) {} |
| 3870 '''); |
| 3871 computeLibrarySourceErrors(source); |
| 3872 assertNoErrors(source); |
| 3873 verify([source]); |
| 3874 } |
| 3875 |
| 3876 void test_unusedElement_method_isUsed_hasReference_PrefixedIdentifier() { |
| 3877 enableUnusedElement = true; |
| 3878 Source source = addSource(r''' |
| 3879 class A { |
| 3880 _m() {} |
| 3881 } |
| 3882 main(A a) { |
| 3883 a._m; |
| 3884 }'''); |
| 3885 computeLibrarySourceErrors(source); |
| 3886 assertNoErrors(source); |
| 3887 verify([source]); |
| 3888 } |
| 3889 |
| 3890 void test_unusedElement_method_isUsed_hasReference_PropertyAccess() { |
| 3891 enableUnusedElement = true; |
| 3892 Source source = addSource(r''' |
| 3893 class A { |
| 3894 _m() {} |
| 3895 } |
| 3896 main() { |
| 3897 new A()._m; |
| 3898 }'''); |
| 3899 computeLibrarySourceErrors(source); |
| 3900 assertNoErrors(source); |
| 3901 verify([source]); |
| 3902 } |
| 3903 |
| 3904 void test_unusedElement_method_isUsed_invocation_implicitThis() { |
| 3905 enableUnusedElement = true; |
| 3906 Source source = addSource(r''' |
| 3907 class A { |
| 3908 _m() {} |
| 3909 useMethod() { |
| 3910 _m(); |
| 3911 } |
| 3912 }'''); |
| 3913 computeLibrarySourceErrors(source); |
| 3914 assertNoErrors(source); |
| 3915 verify([source]); |
| 3916 } |
| 3917 |
| 3918 void test_unusedElement_method_isUsed_invocation_implicitThis_subclass() { |
| 3919 enableUnusedElement = true; |
| 3920 Source source = addSource(r''' |
| 3921 class A { |
| 3922 _m() {} |
| 3923 useMethod() { |
| 3924 _m(); |
| 3925 } |
| 3926 } |
| 3927 class B extends A { |
| 3928 _m() {} |
| 3929 }'''); |
| 3930 computeLibrarySourceErrors(source); |
| 3931 assertNoErrors(source); |
| 3932 verify([source]); |
| 3933 } |
| 3934 |
| 3935 void test_unusedElement_method_isUsed_invocation_MemberElement() { |
| 3936 enableUnusedElement = true; |
| 3937 Source source = addSource(r''' |
| 3938 class A<T> { |
| 3939 _m(T t) {} |
| 3940 } |
| 3941 main(A<int> a) { |
| 3942 a._m(0); |
| 3943 }'''); |
| 3944 computeLibrarySourceErrors(source); |
| 3945 assertNoErrors(source); |
| 3946 verify([source]); |
| 3947 } |
| 3948 |
| 3949 void test_unusedElement_method_isUsed_invocation_propagated() { |
| 3950 enableUnusedElement = true; |
| 3951 Source source = addSource(r''' |
| 3952 class A { |
| 3953 _m() {} |
| 3954 } |
| 3955 main() { |
| 3956 var a = new A(); |
| 3957 a._m(); |
| 3958 }'''); |
| 3959 computeLibrarySourceErrors(source); |
| 3960 assertNoErrors(source); |
| 3961 verify([source]); |
| 3962 } |
| 3963 |
| 3964 void test_unusedElement_method_isUsed_invocation_static() { |
| 3965 enableUnusedElement = true; |
| 3966 Source source = addSource(r''' |
| 3967 class A { |
| 3968 _m() {} |
| 3969 } |
| 3970 main() { |
| 3971 A a = new A(); |
| 3972 a._m(); |
| 3973 }'''); |
| 3974 computeLibrarySourceErrors(source); |
| 3975 assertNoErrors(source); |
| 3976 verify([source]); |
| 3977 } |
| 3978 |
| 3979 void test_unusedElement_method_isUsed_invocation_subclass() { |
| 3980 enableUnusedElement = true; |
| 3981 Source source = addSource(r''' |
| 3982 class A { |
| 3983 _m() {} |
| 3984 } |
| 3985 class B extends A { |
| 3986 _m() {} |
| 3987 } |
| 3988 main(A a) { |
| 3989 a._m(); |
| 3990 }'''); |
| 3991 computeLibrarySourceErrors(source); |
| 3992 assertNoErrors(source); |
| 3993 verify([source]); |
| 3994 } |
| 3995 |
| 3996 void test_unusedElement_method_isUsed_notPrivate() { |
| 3997 enableUnusedElement = true; |
| 3998 Source source = addSource(r''' |
| 3999 class A { |
| 4000 m() {} |
| 4001 } |
| 4002 main() { |
| 4003 }'''); |
| 4004 computeLibrarySourceErrors(source); |
| 4005 assertNoErrors(source); |
| 4006 verify([source]); |
| 4007 } |
| 4008 |
| 4009 void test_unusedElement_method_isUsed_staticInvocation() { |
| 4010 enableUnusedElement = true; |
| 4011 Source source = addSource(r''' |
| 4012 class A { |
| 4013 static _m() {} |
| 4014 } |
| 4015 main() { |
| 4016 A._m(); |
| 4017 }'''); |
| 4018 computeLibrarySourceErrors(source); |
| 4019 assertNoErrors(source); |
| 4020 verify([source]); |
| 4021 } |
| 4022 |
| 4023 void test_unusedElement_method_notUsed_noReference() { |
| 4024 enableUnusedElement = true; |
| 4025 Source source = addSource(r''' |
| 4026 class A { |
| 4027 static _m() {} |
| 4028 }'''); |
| 4029 computeLibrarySourceErrors(source); |
| 4030 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 4031 verify([source]); |
| 4032 } |
| 4033 |
| 4034 void test_unusedElement_method_notUsed_referenceFromItself() { |
| 4035 enableUnusedElement = true; |
| 4036 Source source = addSource(r''' |
| 4037 class A { |
| 4038 static _m(int p) { |
| 4039 _m(p - 1); |
| 4040 } |
| 4041 }'''); |
| 4042 computeLibrarySourceErrors(source); |
| 4043 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 4044 verify([source]); |
| 4045 } |
| 4046 |
| 4047 void test_unusedElement_setter_isUsed_invocation_implicitThis() { |
| 4048 enableUnusedElement = true; |
| 4049 Source source = addSource(r''' |
| 4050 class A { |
| 4051 set _s(x) {} |
| 4052 useSetter() { |
| 4053 _s = 42; |
| 4054 } |
| 4055 }'''); |
| 4056 computeLibrarySourceErrors(source); |
| 4057 assertNoErrors(source); |
| 4058 verify([source]); |
| 4059 } |
| 4060 |
| 4061 void test_unusedElement_setter_isUsed_invocation_PrefixedIdentifier() { |
| 4062 enableUnusedElement = true; |
| 4063 Source source = addSource(r''' |
| 4064 class A { |
| 4065 set _s(x) {} |
| 4066 } |
| 4067 main(A a) { |
| 4068 a._s = 42; |
| 4069 } |
| 4070 '''); |
| 4071 computeLibrarySourceErrors(source); |
| 4072 assertNoErrors(source); |
| 4073 verify([source]); |
| 4074 } |
| 4075 |
| 4076 void test_unusedElement_setter_isUsed_invocation_PropertyAccess() { |
| 4077 enableUnusedElement = true; |
| 4078 Source source = addSource(r''' |
| 4079 class A { |
| 4080 set _s(x) {} |
| 4081 } |
| 4082 main() { |
| 4083 new A()._s = 42; |
| 4084 } |
| 4085 '''); |
| 4086 computeLibrarySourceErrors(source); |
| 4087 assertNoErrors(source); |
| 4088 verify([source]); |
| 4089 } |
| 4090 |
| 4091 void test_unusedElement_setter_notUsed_noReference() { |
| 4092 enableUnusedElement = true; |
| 4093 Source source = addSource(r''' |
| 4094 class A { |
| 4095 set _s(x) {} |
| 4096 }'''); |
| 4097 computeLibrarySourceErrors(source); |
| 4098 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 4099 verify([source]); |
| 4100 } |
| 4101 |
| 4102 void test_unusedElement_setter_notUsed_referenceFromItself() { |
| 4103 enableUnusedElement = true; |
| 4104 Source source = addSource(r''' |
| 4105 class A { |
| 4106 set _s(int x) { |
| 4107 if (x > 5) { |
| 4108 _s = x - 1; |
| 4109 } |
| 4110 } |
| 4111 }'''); |
| 4112 computeLibrarySourceErrors(source); |
| 4113 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 4114 verify([source]); |
| 4115 } |
| 4116 |
| 4117 void test_unusedField_isUsed_argument() { |
| 4118 enableUnusedElement = true; |
| 4119 Source source = addSource(r''' |
| 4120 class A { |
| 4121 int _f = 0; |
| 4122 main() { |
| 4123 print(++_f); |
| 4124 } |
| 4125 } |
| 4126 print(x) {}'''); |
| 4127 computeLibrarySourceErrors(source); |
| 4128 assertErrors(source); |
| 4129 verify([source]); |
| 4130 } |
| 4131 |
| 4132 void test_unusedField_isUsed_reference_implicitThis() { |
| 4133 enableUnusedElement = true; |
| 4134 Source source = addSource(r''' |
| 4135 class A { |
| 4136 int _f; |
| 4137 main() { |
| 4138 print(_f); |
| 4139 } |
| 4140 } |
| 4141 print(x) {}'''); |
| 4142 computeLibrarySourceErrors(source); |
| 4143 assertErrors(source); |
| 4144 verify([source]); |
| 4145 } |
| 4146 |
| 4147 void test_unusedField_isUsed_reference_implicitThis_expressionFunctionBody() { |
| 4148 enableUnusedElement = true; |
| 4149 Source source = addSource(r''' |
| 4150 class A { |
| 4151 int _f; |
| 4152 m() => _f; |
| 4153 }'''); |
| 4154 computeLibrarySourceErrors(source); |
| 4155 assertErrors(source); |
| 4156 verify([source]); |
| 4157 } |
| 4158 |
| 4159 void test_unusedField_isUsed_reference_implicitThis_subclass() { |
| 4160 enableUnusedElement = true; |
| 4161 Source source = addSource(r''' |
| 4162 class A { |
| 4163 int _f; |
| 4164 main() { |
| 4165 print(_f); |
| 4166 } |
| 4167 } |
| 4168 class B extends A { |
| 4169 int _f; |
| 4170 } |
| 4171 print(x) {}'''); |
| 4172 computeLibrarySourceErrors(source); |
| 4173 assertErrors(source); |
| 4174 verify([source]); |
| 4175 } |
| 4176 |
| 4177 void test_unusedField_isUsed_reference_qualified_propagatedElement() { |
| 4178 enableUnusedElement = true; |
| 4179 Source source = addSource(r''' |
| 4180 class A { |
| 4181 int _f; |
| 4182 } |
| 4183 main() { |
| 4184 var a = new A(); |
| 4185 print(a._f); |
| 4186 } |
| 4187 print(x) {}'''); |
| 4188 computeLibrarySourceErrors(source); |
| 4189 assertErrors(source); |
| 4190 verify([source]); |
| 4191 } |
| 4192 |
| 4193 void test_unusedField_isUsed_reference_qualified_staticElement() { |
| 4194 enableUnusedElement = true; |
| 4195 Source source = addSource(r''' |
| 4196 class A { |
| 4197 int _f; |
| 4198 } |
| 4199 main() { |
| 4200 A a = new A(); |
| 4201 print(a._f); |
| 4202 } |
| 4203 print(x) {}'''); |
| 4204 computeLibrarySourceErrors(source); |
| 4205 assertErrors(source); |
| 4206 verify([source]); |
| 4207 } |
| 4208 |
| 4209 void test_unusedField_isUsed_reference_qualified_unresolved() { |
| 4210 enableUnusedElement = true; |
| 4211 Source source = addSource(r''' |
| 4212 class A { |
| 4213 int _f; |
| 4214 } |
| 4215 main(a) { |
| 4216 print(a._f); |
| 4217 } |
| 4218 print(x) {}'''); |
| 4219 computeLibrarySourceErrors(source); |
| 4220 assertErrors(source); |
| 4221 verify([source]); |
| 4222 } |
| 4223 |
| 4224 void test_unusedField_notUsed_compoundAssign() { |
| 4225 enableUnusedElement = true; |
| 4226 Source source = addSource(r''' |
| 4227 class A { |
| 4228 int _f; |
| 4229 main() { |
| 4230 _f += 2; |
| 4231 } |
| 4232 }'''); |
| 4233 computeLibrarySourceErrors(source); |
| 4234 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4235 verify([source]); |
| 4236 } |
| 4237 |
| 4238 void test_unusedField_notUsed_noReference() { |
| 4239 enableUnusedElement = true; |
| 4240 Source source = addSource(r''' |
| 4241 class A { |
| 4242 int _f; |
| 4243 } |
| 4244 '''); |
| 4245 computeLibrarySourceErrors(source); |
| 4246 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4247 verify([source]); |
| 4248 } |
| 4249 |
| 4250 void test_unusedField_notUsed_postfixExpr() { |
| 4251 enableUnusedElement = true; |
| 4252 Source source = addSource(r''' |
| 4253 class A { |
| 4254 int _f = 0; |
| 4255 main() { |
| 4256 _f++; |
| 4257 } |
| 4258 }'''); |
| 4259 computeLibrarySourceErrors(source); |
| 4260 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4261 verify([source]); |
| 4262 } |
| 4263 |
| 4264 void test_unusedField_notUsed_prefixExpr() { |
| 4265 enableUnusedElement = true; |
| 4266 Source source = addSource(r''' |
| 4267 class A { |
| 4268 int _f = 0; |
| 4269 main() { |
| 4270 ++_f; |
| 4271 } |
| 4272 }'''); |
| 4273 computeLibrarySourceErrors(source); |
| 4274 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4275 verify([source]); |
| 4276 } |
| 4277 |
| 4278 void test_unusedField_notUsed_simpleAssignment() { |
| 4279 enableUnusedElement = true; |
| 4280 Source source = addSource(r''' |
| 4281 class A { |
| 4282 int _f; |
| 4283 m() { |
| 4284 _f = 1; |
| 4285 } |
| 4286 } |
| 4287 main(A a) { |
| 4288 a._f = 2; |
| 4289 } |
| 4290 '''); |
| 4291 computeLibrarySourceErrors(source); |
| 4292 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4293 verify([source]); |
| 4294 } |
| 4295 |
| 4296 void test_unusedImport() { |
| 4297 Source source = addSource(r''' |
| 4298 library L; |
| 4299 import 'lib1.dart';'''); |
| 4300 Source source2 = addNamedSource("/lib1.dart", "library lib1;"); |
| 4301 computeLibrarySourceErrors(source); |
| 4302 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 4303 assertNoErrors(source2); |
| 4304 verify([source, source2]); |
| 4305 } |
| 4306 |
| 4307 void test_unusedImport_as() { |
| 4308 Source source = addSource(r''' |
| 4309 library L; |
| 4310 import 'lib1.dart'; |
| 4311 import 'lib1.dart' as one; |
| 4312 one.A a;'''); |
| 4313 Source source2 = addNamedSource( |
| 4314 "/lib1.dart", |
| 4315 r''' |
| 4316 library lib1; |
| 4317 class A {}'''); |
| 4318 computeLibrarySourceErrors(source); |
| 4319 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 4320 assertNoErrors(source2); |
| 4321 verify([source, source2]); |
| 4322 } |
| 4323 |
| 4324 void test_unusedImport_hide() { |
| 4325 Source source = addSource(r''' |
| 4326 library L; |
| 4327 import 'lib1.dart'; |
| 4328 import 'lib1.dart' hide A; |
| 4329 A a;'''); |
| 4330 Source source2 = addNamedSource( |
| 4331 "/lib1.dart", |
| 4332 r''' |
| 4333 library lib1; |
| 4334 class A {}'''); |
| 4335 computeLibrarySourceErrors(source); |
| 4336 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 4337 assertNoErrors(source2); |
| 4338 verify([source, source2]); |
| 4339 } |
| 4340 |
| 4341 void test_unusedImport_show() { |
| 4342 Source source = addSource(r''' |
| 4343 library L; |
| 4344 import 'lib1.dart' show A; |
| 4345 import 'lib1.dart' show B; |
| 4346 A a;'''); |
| 4347 Source source2 = addNamedSource( |
| 4348 "/lib1.dart", |
| 4349 r''' |
| 4350 library lib1; |
| 4351 class A {} |
| 4352 class B {}'''); |
| 4353 computeLibrarySourceErrors(source); |
| 4354 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 4355 assertNoErrors(source2); |
| 4356 verify([source, source2]); |
| 4357 } |
| 4358 |
| 4359 void test_unusedLocalVariable_inCatch_exception() { |
| 4360 enableUnusedLocalVariable = true; |
| 4361 Source source = addSource(r''' |
| 4362 main() { |
| 4363 try { |
| 4364 } on String catch (exception) { |
| 4365 } |
| 4366 }'''); |
| 4367 computeLibrarySourceErrors(source); |
| 4368 assertErrors(source, [HintCode.UNUSED_CATCH_CLAUSE]); |
| 4369 verify([source]); |
| 4370 } |
| 4371 |
| 4372 void test_unusedLocalVariable_inCatch_exception_hasStack() { |
| 4373 enableUnusedLocalVariable = true; |
| 4374 Source source = addSource(r''' |
| 4375 main() { |
| 4376 try { |
| 4377 } catch (exception, stack) { |
| 4378 print(stack); |
| 4379 } |
| 4380 }'''); |
| 4381 computeLibrarySourceErrors(source); |
| 4382 assertNoErrors(source); |
| 4383 verify([source]); |
| 4384 } |
| 4385 |
| 4386 void test_unusedLocalVariable_inCatch_exception_noOnClause() { |
| 4387 enableUnusedLocalVariable = true; |
| 4388 Source source = addSource(r''' |
| 4389 main() { |
| 4390 try { |
| 4391 } catch (exception) { |
| 4392 } |
| 4393 }'''); |
| 4394 computeLibrarySourceErrors(source); |
| 4395 assertNoErrors(source); |
| 4396 verify([source]); |
| 4397 } |
| 4398 |
| 4399 void test_unusedLocalVariable_inCatch_stackTrace() { |
| 4400 enableUnusedLocalVariable = true; |
| 4401 Source source = addSource(r''' |
| 4402 main() { |
| 4403 try { |
| 4404 } catch (exception, stackTrace) { |
| 4405 } |
| 4406 }'''); |
| 4407 computeLibrarySourceErrors(source); |
| 4408 assertErrors(source, [HintCode.UNUSED_CATCH_STACK]); |
| 4409 verify([source]); |
| 4410 } |
| 4411 |
| 4412 void test_unusedLocalVariable_inCatch_stackTrace_used() { |
| 4413 enableUnusedLocalVariable = true; |
| 4414 Source source = addSource(r''' |
| 4415 main() { |
| 4416 try { |
| 4417 } catch (exception, stackTrace) { |
| 4418 print('exception at $stackTrace'); |
| 4419 } |
| 4420 } |
| 4421 print(x) {}'''); |
| 4422 computeLibrarySourceErrors(source); |
| 4423 assertErrors(source); |
| 4424 verify([source]); |
| 4425 } |
| 4426 |
| 4427 void test_unusedLocalVariable_inFor_underscore_ignored() { |
| 4428 enableUnusedLocalVariable = true; |
| 4429 Source source = addSource(r''' |
| 4430 main() { |
| 4431 for (var _ in [1,2,3]) { |
| 4432 for (var __ in [4,5,6]) { |
| 4433 // do something |
| 4434 } |
| 4435 } |
| 4436 }'''); |
| 4437 computeLibrarySourceErrors(source); |
| 4438 assertErrors(source); |
| 4439 verify([source]); |
| 4440 } |
| 4441 |
| 4442 void test_unusedLocalVariable_inFunction() { |
| 4443 enableUnusedLocalVariable = true; |
| 4444 Source source = addSource(r''' |
| 4445 main() { |
| 4446 var v = 1; |
| 4447 v = 2; |
| 4448 }'''); |
| 4449 computeLibrarySourceErrors(source); |
| 4450 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4451 verify([source]); |
| 4452 } |
| 4453 |
| 4454 void test_unusedLocalVariable_inMethod() { |
| 4455 enableUnusedLocalVariable = true; |
| 4456 Source source = addSource(r''' |
| 4457 class A { |
| 4458 foo() { |
| 4459 var v = 1; |
| 4460 v = 2; |
| 4461 } |
| 4462 }'''); |
| 4463 computeLibrarySourceErrors(source); |
| 4464 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4465 verify([source]); |
| 4466 } |
| 4467 |
| 4468 void test_unusedLocalVariable_isInvoked() { |
| 4469 enableUnusedLocalVariable = true; |
| 4470 Source source = addSource(r''' |
| 4471 typedef Foo(); |
| 4472 main() { |
| 4473 Foo foo; |
| 4474 foo(); |
| 4475 }'''); |
| 4476 computeLibrarySourceErrors(source); |
| 4477 assertErrors(source); |
| 4478 verify([source]); |
| 4479 } |
| 4480 |
| 4481 void test_unusedLocalVariable_isRead_notUsed_compoundAssign() { |
| 4482 enableUnusedLocalVariable = true; |
| 4483 Source source = addSource(r''' |
| 4484 main() { |
| 4485 var v = 1; |
| 4486 v += 2; |
| 4487 }'''); |
| 4488 computeLibrarySourceErrors(source); |
| 4489 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4490 verify([source]); |
| 4491 } |
| 4492 |
| 4493 void test_unusedLocalVariable_isRead_notUsed_postfixExpr() { |
| 4494 enableUnusedLocalVariable = true; |
| 4495 Source source = addSource(r''' |
| 4496 main() { |
| 4497 var v = 1; |
| 4498 v++; |
| 4499 }'''); |
| 4500 computeLibrarySourceErrors(source); |
| 4501 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4502 verify([source]); |
| 4503 } |
| 4504 |
| 4505 void test_unusedLocalVariable_isRead_notUsed_prefixExpr() { |
| 4506 enableUnusedLocalVariable = true; |
| 4507 Source source = addSource(r''' |
| 4508 main() { |
| 4509 var v = 1; |
| 4510 ++v; |
| 4511 }'''); |
| 4512 computeLibrarySourceErrors(source); |
| 4513 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4514 verify([source]); |
| 4515 } |
| 4516 |
| 4517 void test_unusedLocalVariable_isRead_usedArgument() { |
| 4518 enableUnusedLocalVariable = true; |
| 4519 Source source = addSource(r''' |
| 4520 main() { |
| 4521 var v = 1; |
| 4522 print(++v); |
| 4523 } |
| 4524 print(x) {}'''); |
| 4525 computeLibrarySourceErrors(source); |
| 4526 assertErrors(source); |
| 4527 verify([source]); |
| 4528 } |
| 4529 |
| 4530 void test_unusedLocalVariable_isRead_usedInvocationTarget() { |
| 4531 enableUnusedLocalVariable = true; |
| 4532 Source source = addSource(r''' |
| 4533 class A { |
| 4534 foo() {} |
| 4535 } |
| 4536 main() { |
| 4537 var a = new A(); |
| 4538 a.foo(); |
| 4539 } |
| 4540 '''); |
| 4541 computeLibrarySourceErrors(source); |
| 4542 assertErrors(source); |
| 4543 verify([source]); |
| 4544 } |
| 4545 |
| 4546 void test_useOfVoidResult_assignmentExpression_function() { |
| 4547 Source source = addSource(r''' |
| 4548 void f() {} |
| 4549 class A { |
| 4550 n() { |
| 4551 var a; |
| 4552 a = f(); |
| 4553 } |
| 4554 }'''); |
| 4555 computeLibrarySourceErrors(source); |
| 4556 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4557 verify([source]); |
| 4558 } |
| 4559 |
| 4560 void test_useOfVoidResult_assignmentExpression_method() { |
| 4561 Source source = addSource(r''' |
| 4562 class A { |
| 4563 void m() {} |
| 4564 n() { |
| 4565 var a; |
| 4566 a = m(); |
| 4567 } |
| 4568 }'''); |
| 4569 computeLibrarySourceErrors(source); |
| 4570 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4571 verify([source]); |
| 4572 } |
| 4573 |
| 4574 void test_useOfVoidResult_inForLoop() { |
| 4575 Source source = addSource(r''' |
| 4576 class A { |
| 4577 void m() {} |
| 4578 n() { |
| 4579 for(var a = m();;) {} |
| 4580 } |
| 4581 }'''); |
| 4582 computeLibrarySourceErrors(source); |
| 4583 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4584 verify([source]); |
| 4585 } |
| 4586 |
| 4587 void test_useOfVoidResult_variableDeclaration_function() { |
| 4588 Source source = addSource(r''' |
| 4589 void f() {} |
| 4590 class A { |
| 4591 n() { |
| 4592 var a = f(); |
| 4593 } |
| 4594 }'''); |
| 4595 computeLibrarySourceErrors(source); |
| 4596 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4597 verify([source]); |
| 4598 } |
| 4599 |
| 4600 void test_useOfVoidResult_variableDeclaration_method() { |
| 4601 Source source = addSource(r''' |
| 4602 class A { |
| 4603 void m() {} |
| 4604 n() { |
| 4605 var a = m(); |
| 4606 } |
| 4607 }'''); |
| 4608 computeLibrarySourceErrors(source); |
| 4609 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4610 verify([source]); |
| 4611 } |
| 4612 |
| 4613 void test_useOfVoidResult_variableDeclaration_method2() { |
| 4614 Source source = addSource(r''' |
| 4615 class A { |
| 4616 void m() {} |
| 4617 n() { |
| 4618 var a = m(), b = m(); |
| 4619 } |
| 4620 }'''); |
| 4621 computeLibrarySourceErrors(source); |
| 4622 assertErrors( |
| 4623 source, [HintCode.USE_OF_VOID_RESULT, HintCode.USE_OF_VOID_RESULT]); |
| 4624 verify([source]); |
| 4625 } |
| 4626 } |
| 4627 |
| 4628 @reflectiveTest |
| 4629 class InheritanceManagerTest extends EngineTestCase { |
| 4630 /** |
| 4631 * The type provider used to access the types. |
| 4632 */ |
| 4633 TestTypeProvider _typeProvider; |
| 4634 |
| 4635 /** |
| 4636 * The library containing the code being resolved. |
| 4637 */ |
| 4638 LibraryElementImpl _definingLibrary; |
| 4639 |
| 4640 /** |
| 4641 * The inheritance manager being tested. |
| 4642 */ |
| 4643 InheritanceManager _inheritanceManager; |
| 4644 |
| 4645 /** |
| 4646 * The number of members that Object implements (as determined by [TestTypePro
vider]). |
| 4647 */ |
| 4648 int _numOfMembersInObject = 0; |
| 4649 |
| 4650 @override |
| 4651 void setUp() { |
| 4652 _typeProvider = new TestTypeProvider(); |
| 4653 _inheritanceManager = _createInheritanceManager(); |
| 4654 InterfaceType objectType = _typeProvider.objectType; |
| 4655 _numOfMembersInObject = |
| 4656 objectType.methods.length + objectType.accessors.length; |
| 4657 } |
| 4658 |
| 4659 void test_getMapOfMembersInheritedFromClasses_accessor_extends() { |
| 4660 // class A { int get g; } |
| 4661 // class B extends A {} |
| 4662 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4663 String getterName = "g"; |
| 4664 PropertyAccessorElement getterG = |
| 4665 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4666 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4667 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 4668 MemberMap mapB = |
| 4669 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4670 MemberMap mapA = |
| 4671 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4672 expect(mapA.size, _numOfMembersInObject); |
| 4673 expect(mapB.size, _numOfMembersInObject + 1); |
| 4674 expect(mapB.get(getterName), same(getterG)); |
| 4675 _assertNoErrors(classA); |
| 4676 _assertNoErrors(classB); |
| 4677 } |
| 4678 |
| 4679 void test_getMapOfMembersInheritedFromClasses_accessor_implements() { |
| 4680 // class A { int get g; } |
| 4681 // class B implements A {} |
| 4682 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4683 String getterName = "g"; |
| 4684 PropertyAccessorElement getterG = |
| 4685 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4686 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4687 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4688 classB.interfaces = <InterfaceType>[classA.type]; |
| 4689 MemberMap mapB = |
| 4690 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4691 MemberMap mapA = |
| 4692 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4693 expect(mapA.size, _numOfMembersInObject); |
| 4694 expect(mapB.size, _numOfMembersInObject); |
| 4695 expect(mapB.get(getterName), isNull); |
| 4696 _assertNoErrors(classA); |
| 4697 _assertNoErrors(classB); |
| 4698 } |
| 4699 |
| 4700 void test_getMapOfMembersInheritedFromClasses_accessor_with() { |
| 4701 // class A { int get g; } |
| 4702 // class B extends Object with A {} |
| 4703 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4704 String getterName = "g"; |
| 4705 PropertyAccessorElement getterG = |
| 4706 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4707 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4708 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4709 classB.mixins = <InterfaceType>[classA.type]; |
| 4710 MemberMap mapB = |
| 4711 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4712 MemberMap mapA = |
| 4713 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4714 expect(mapA.size, _numOfMembersInObject); |
| 4715 expect(mapB.size, _numOfMembersInObject + 1); |
| 4716 expect(mapB.get(getterName), same(getterG)); |
| 4717 _assertNoErrors(classA); |
| 4718 _assertNoErrors(classB); |
| 4719 } |
| 4720 |
| 4721 void test_getMapOfMembersInheritedFromClasses_implicitExtends() { |
| 4722 // class A {} |
| 4723 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4724 MemberMap mapA = |
| 4725 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4726 expect(mapA.size, _numOfMembersInObject); |
| 4727 _assertNoErrors(classA); |
| 4728 } |
| 4729 |
| 4730 void test_getMapOfMembersInheritedFromClasses_method_extends() { |
| 4731 // class A { int g(); } |
| 4732 // class B extends A {} |
| 4733 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4734 String methodName = "m"; |
| 4735 MethodElement methodM = |
| 4736 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4737 classA.methods = <MethodElement>[methodM]; |
| 4738 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4739 classB.supertype = classA.type; |
| 4740 MemberMap mapB = |
| 4741 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4742 MemberMap mapA = |
| 4743 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4744 expect(mapA.size, _numOfMembersInObject); |
| 4745 expect(mapB.size, _numOfMembersInObject + 1); |
| 4746 expect(mapB.get(methodName), same(methodM)); |
| 4747 _assertNoErrors(classA); |
| 4748 _assertNoErrors(classB); |
| 4749 } |
| 4750 |
| 4751 void test_getMapOfMembersInheritedFromClasses_method_implements() { |
| 4752 // class A { int g(); } |
| 4753 // class B implements A {} |
| 4754 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4755 String methodName = "m"; |
| 4756 MethodElement methodM = |
| 4757 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4758 classA.methods = <MethodElement>[methodM]; |
| 4759 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4760 classB.interfaces = <InterfaceType>[classA.type]; |
| 4761 MemberMap mapB = |
| 4762 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4763 MemberMap mapA = |
| 4764 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4765 expect(mapA.size, _numOfMembersInObject); |
| 4766 expect(mapB.size, _numOfMembersInObject); |
| 4767 expect(mapB.get(methodName), isNull); |
| 4768 _assertNoErrors(classA); |
| 4769 _assertNoErrors(classB); |
| 4770 } |
| 4771 |
| 4772 void test_getMapOfMembersInheritedFromClasses_method_with() { |
| 4773 // class A { int g(); } |
| 4774 // class B extends Object with A {} |
| 4775 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4776 String methodName = "m"; |
| 4777 MethodElement methodM = |
| 4778 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4779 classA.methods = <MethodElement>[methodM]; |
| 4780 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4781 classB.mixins = <InterfaceType>[classA.type]; |
| 4782 MemberMap mapB = |
| 4783 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4784 MemberMap mapA = |
| 4785 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4786 expect(mapA.size, _numOfMembersInObject); |
| 4787 expect(mapB.size, _numOfMembersInObject + 1); |
| 4788 expect(mapB.get(methodName), same(methodM)); |
| 4789 _assertNoErrors(classA); |
| 4790 _assertNoErrors(classB); |
| 4791 } |
| 4792 |
| 4793 void test_getMapOfMembersInheritedFromClasses_method_with_two_mixins() { |
| 4794 // class A1 { int m(); } |
| 4795 // class A2 { int m(); } |
| 4796 // class B extends Object with A1, A2 {} |
| 4797 ClassElementImpl classA1 = ElementFactory.classElement2("A1"); |
| 4798 String methodName = "m"; |
| 4799 MethodElement methodA1M = |
| 4800 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4801 classA1.methods = <MethodElement>[methodA1M]; |
| 4802 ClassElementImpl classA2 = ElementFactory.classElement2("A2"); |
| 4803 MethodElement methodA2M = |
| 4804 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4805 classA2.methods = <MethodElement>[methodA2M]; |
| 4806 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4807 classB.mixins = <InterfaceType>[classA1.type, classA2.type]; |
| 4808 MemberMap mapB = |
| 4809 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4810 expect(mapB.get(methodName), same(methodA2M)); |
| 4811 _assertNoErrors(classA1); |
| 4812 _assertNoErrors(classA2); |
| 4813 _assertNoErrors(classB); |
| 4814 } |
| 4815 |
| 4816 void test_getMapOfMembersInheritedFromInterfaces_accessor_extends() { |
| 4817 // class A { int get g; } |
| 4818 // class B extends A {} |
| 4819 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4820 String getterName = "g"; |
| 4821 PropertyAccessorElement getterG = |
| 4822 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4823 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4824 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 4825 MemberMap mapB = |
| 4826 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 4827 MemberMap mapA = |
| 4828 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4829 expect(mapA.size, _numOfMembersInObject); |
| 4830 expect(mapB.size, _numOfMembersInObject + 1); |
| 4831 expect(mapB.get(getterName), same(getterG)); |
| 4832 _assertNoErrors(classA); |
| 4833 _assertNoErrors(classB); |
| 4834 } |
| 4835 |
| 4836 void test_getMapOfMembersInheritedFromInterfaces_accessor_implements() { |
| 4837 // class A { int get g; } |
| 4838 // class B implements A {} |
| 4839 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4840 String getterName = "g"; |
| 4841 PropertyAccessorElement getterG = |
| 4842 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4843 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4844 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4845 classB.interfaces = <InterfaceType>[classA.type]; |
| 4846 MemberMap mapB = |
| 4847 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 4848 MemberMap mapA = |
| 4849 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4850 expect(mapA.size, _numOfMembersInObject); |
| 4851 expect(mapB.size, _numOfMembersInObject + 1); |
| 4852 expect(mapB.get(getterName), same(getterG)); |
| 4853 _assertNoErrors(classA); |
| 4854 _assertNoErrors(classB); |
| 4855 } |
| 4856 |
| 4857 void test_getMapOfMembersInheritedFromInterfaces_accessor_with() { |
| 4858 // class A { int get g; } |
| 4859 // class B extends Object with A {} |
| 4860 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4861 String getterName = "g"; |
| 4862 PropertyAccessorElement getterG = |
| 4863 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4864 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4865 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4866 classB.mixins = <InterfaceType>[classA.type]; |
| 4867 MemberMap mapB = |
| 4868 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 4869 MemberMap mapA = |
| 4870 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4871 expect(mapA.size, _numOfMembersInObject); |
| 4872 expect(mapB.size, _numOfMembersInObject + 1); |
| 4873 expect(mapB.get(getterName), same(getterG)); |
| 4874 _assertNoErrors(classA); |
| 4875 _assertNoErrors(classB); |
| 4876 } |
| 4877 |
| 4878 void test_getMapOfMembersInheritedFromInterfaces_implicitExtends() { |
| 4879 // class A {} |
| 4880 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4881 MemberMap mapA = |
| 4882 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4883 expect(mapA.size, _numOfMembersInObject); |
| 4884 _assertNoErrors(classA); |
| 4885 } |
| 4886 |
| 4887 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_getter_method() { |
| 4888 // class I1 { int m(); } |
| 4889 // class I2 { int get m; } |
| 4890 // class A implements I2, I1 {} |
| 4891 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4892 String methodName = "m"; |
| 4893 MethodElement methodM = |
| 4894 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4895 classI1.methods = <MethodElement>[methodM]; |
| 4896 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 4897 PropertyAccessorElement getter = |
| 4898 ElementFactory.getterElement(methodName, false, _typeProvider.intType); |
| 4899 classI2.accessors = <PropertyAccessorElement>[getter]; |
| 4900 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4901 classA.interfaces = <InterfaceType>[classI2.type, classI1.type]; |
| 4902 MemberMap mapA = |
| 4903 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4904 expect(mapA.size, _numOfMembersInObject); |
| 4905 expect(mapA.get(methodName), isNull); |
| 4906 _assertErrors(classA, |
| 4907 [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]); |
| 4908 } |
| 4909 |
| 4910 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_int_str() { |
| 4911 // class I1 { int m(); } |
| 4912 // class I2 { String m(); } |
| 4913 // class A implements I1, I2 {} |
| 4914 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4915 String methodName = "m"; |
| 4916 MethodElement methodM1 = |
| 4917 ElementFactory.methodElement(methodName, null, [_typeProvider.intType]); |
| 4918 classI1.methods = <MethodElement>[methodM1]; |
| 4919 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 4920 MethodElement methodM2 = ElementFactory.methodElement( |
| 4921 methodName, null, [_typeProvider.stringType]); |
| 4922 classI2.methods = <MethodElement>[methodM2]; |
| 4923 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4924 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 4925 MemberMap mapA = |
| 4926 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4927 expect(mapA.size, _numOfMembersInObject); |
| 4928 expect(mapA.get(methodName), isNull); |
| 4929 _assertErrors( |
| 4930 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); |
| 4931 } |
| 4932 |
| 4933 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_method_getter() { |
| 4934 // class I1 { int m(); } |
| 4935 // class I2 { int get m; } |
| 4936 // class A implements I1, I2 {} |
| 4937 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4938 String methodName = "m"; |
| 4939 MethodElement methodM = |
| 4940 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4941 classI1.methods = <MethodElement>[methodM]; |
| 4942 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 4943 PropertyAccessorElement getter = |
| 4944 ElementFactory.getterElement(methodName, false, _typeProvider.intType); |
| 4945 classI2.accessors = <PropertyAccessorElement>[getter]; |
| 4946 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4947 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 4948 MemberMap mapA = |
| 4949 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4950 expect(mapA.size, _numOfMembersInObject); |
| 4951 expect(mapA.get(methodName), isNull); |
| 4952 _assertErrors(classA, |
| 4953 [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]); |
| 4954 } |
| 4955 |
| 4956 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_numOfRequiredParams() { |
| 4957 // class I1 { dynamic m(int, [int]); } |
| 4958 // class I2 { dynamic m(int, int, int); } |
| 4959 // class A implements I1, I2 {} |
| 4960 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4961 String methodName = "m"; |
| 4962 MethodElementImpl methodM1 = |
| 4963 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 4964 ParameterElementImpl parameter1 = |
| 4965 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); |
| 4966 parameter1.type = _typeProvider.intType; |
| 4967 parameter1.parameterKind = ParameterKind.REQUIRED; |
| 4968 ParameterElementImpl parameter2 = |
| 4969 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); |
| 4970 parameter2.type = _typeProvider.intType; |
| 4971 parameter2.parameterKind = ParameterKind.POSITIONAL; |
| 4972 methodM1.parameters = <ParameterElement>[parameter1, parameter2]; |
| 4973 classI1.methods = <MethodElement>[methodM1]; |
| 4974 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 4975 MethodElementImpl methodM2 = |
| 4976 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 4977 ParameterElementImpl parameter3 = |
| 4978 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); |
| 4979 parameter3.type = _typeProvider.intType; |
| 4980 parameter3.parameterKind = ParameterKind.REQUIRED; |
| 4981 ParameterElementImpl parameter4 = |
| 4982 new ParameterElementImpl.forNode(AstFactory.identifier3("a4")); |
| 4983 parameter4.type = _typeProvider.intType; |
| 4984 parameter4.parameterKind = ParameterKind.REQUIRED; |
| 4985 ParameterElementImpl parameter5 = |
| 4986 new ParameterElementImpl.forNode(AstFactory.identifier3("a5")); |
| 4987 parameter5.type = _typeProvider.intType; |
| 4988 parameter5.parameterKind = ParameterKind.REQUIRED; |
| 4989 methodM2.parameters = <ParameterElement>[ |
| 4990 parameter3, |
| 4991 parameter4, |
| 4992 parameter5 |
| 4993 ]; |
| 4994 classI2.methods = <MethodElement>[methodM2]; |
| 4995 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4996 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 4997 MemberMap mapA = |
| 4998 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4999 expect(mapA.size, _numOfMembersInObject); |
| 5000 expect(mapA.get(methodName), isNull); |
| 5001 _assertErrors( |
| 5002 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); |
| 5003 } |
| 5004 |
| 5005 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_str_int() { |
| 5006 // class I1 { int m(); } |
| 5007 // class I2 { String m(); } |
| 5008 // class A implements I2, I1 {} |
| 5009 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5010 String methodName = "m"; |
| 5011 MethodElement methodM1 = ElementFactory.methodElement( |
| 5012 methodName, null, [_typeProvider.stringType]); |
| 5013 classI1.methods = <MethodElement>[methodM1]; |
| 5014 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5015 MethodElement methodM2 = |
| 5016 ElementFactory.methodElement(methodName, null, [_typeProvider.intType]); |
| 5017 classI2.methods = <MethodElement>[methodM2]; |
| 5018 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5019 classA.interfaces = <InterfaceType>[classI2.type, classI1.type]; |
| 5020 MemberMap mapA = |
| 5021 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5022 expect(mapA.size, _numOfMembersInObject); |
| 5023 expect(mapA.get(methodName), isNull); |
| 5024 _assertErrors( |
| 5025 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); |
| 5026 } |
| 5027 |
| 5028 void test_getMapOfMembersInheritedFromInterfaces_method_extends() { |
| 5029 // class A { int g(); } |
| 5030 // class B extends A {} |
| 5031 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5032 String methodName = "m"; |
| 5033 MethodElement methodM = |
| 5034 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5035 classA.methods = <MethodElement>[methodM]; |
| 5036 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5037 MemberMap mapB = |
| 5038 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 5039 MemberMap mapA = |
| 5040 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5041 expect(mapA.size, _numOfMembersInObject); |
| 5042 expect(mapB.size, _numOfMembersInObject + 1); |
| 5043 expect(mapB.get(methodName), same(methodM)); |
| 5044 _assertNoErrors(classA); |
| 5045 _assertNoErrors(classB); |
| 5046 } |
| 5047 |
| 5048 void test_getMapOfMembersInheritedFromInterfaces_method_implements() { |
| 5049 // class A { int g(); } |
| 5050 // class B implements A {} |
| 5051 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5052 String methodName = "m"; |
| 5053 MethodElement methodM = |
| 5054 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5055 classA.methods = <MethodElement>[methodM]; |
| 5056 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5057 classB.interfaces = <InterfaceType>[classA.type]; |
| 5058 MemberMap mapB = |
| 5059 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 5060 MemberMap mapA = |
| 5061 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5062 expect(mapA.size, _numOfMembersInObject); |
| 5063 expect(mapB.size, _numOfMembersInObject + 1); |
| 5064 expect(mapB.get(methodName), same(methodM)); |
| 5065 _assertNoErrors(classA); |
| 5066 _assertNoErrors(classB); |
| 5067 } |
| 5068 |
| 5069 void test_getMapOfMembersInheritedFromInterfaces_method_with() { |
| 5070 // class A { int g(); } |
| 5071 // class B extends Object with A {} |
| 5072 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5073 String methodName = "m"; |
| 5074 MethodElement methodM = |
| 5075 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5076 classA.methods = <MethodElement>[methodM]; |
| 5077 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5078 classB.mixins = <InterfaceType>[classA.type]; |
| 5079 MemberMap mapB = |
| 5080 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 5081 MemberMap mapA = |
| 5082 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5083 expect(mapA.size, _numOfMembersInObject); |
| 5084 expect(mapB.size, _numOfMembersInObject + 1); |
| 5085 expect(mapB.get(methodName), same(methodM)); |
| 5086 _assertNoErrors(classA); |
| 5087 _assertNoErrors(classB); |
| 5088 } |
| 5089 |
| 5090 void test_getMapOfMembersInheritedFromInterfaces_union_differentNames() { |
| 5091 // class I1 { int m1(); } |
| 5092 // class I2 { int m2(); } |
| 5093 // class A implements I1, I2 {} |
| 5094 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5095 String methodName1 = "m1"; |
| 5096 MethodElement methodM1 = |
| 5097 ElementFactory.methodElement(methodName1, _typeProvider.intType); |
| 5098 classI1.methods = <MethodElement>[methodM1]; |
| 5099 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5100 String methodName2 = "m2"; |
| 5101 MethodElement methodM2 = |
| 5102 ElementFactory.methodElement(methodName2, _typeProvider.intType); |
| 5103 classI2.methods = <MethodElement>[methodM2]; |
| 5104 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5105 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5106 MemberMap mapA = |
| 5107 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5108 expect(mapA.size, _numOfMembersInObject + 2); |
| 5109 expect(mapA.get(methodName1), same(methodM1)); |
| 5110 expect(mapA.get(methodName2), same(methodM2)); |
| 5111 _assertNoErrors(classA); |
| 5112 } |
| 5113 |
| 5114 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_gett
ers() { |
| 5115 // class I1 { int get g; } |
| 5116 // class I2 { num get g; } |
| 5117 // class A implements I1, I2 {} |
| 5118 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5119 String accessorName = "g"; |
| 5120 PropertyAccessorElement getter1 = ElementFactory.getterElement( |
| 5121 accessorName, false, _typeProvider.intType); |
| 5122 classI1.accessors = <PropertyAccessorElement>[getter1]; |
| 5123 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5124 PropertyAccessorElement getter2 = ElementFactory.getterElement( |
| 5125 accessorName, false, _typeProvider.numType); |
| 5126 classI2.accessors = <PropertyAccessorElement>[getter2]; |
| 5127 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5128 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5129 MemberMap mapA = |
| 5130 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5131 expect(mapA.size, _numOfMembersInObject + 1); |
| 5132 PropertyAccessorElement syntheticAccessor = ElementFactory.getterElement( |
| 5133 accessorName, false, _typeProvider.dynamicType); |
| 5134 expect(mapA.get(accessorName).type, syntheticAccessor.type); |
| 5135 _assertNoErrors(classA); |
| 5136 } |
| 5137 |
| 5138 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_meth
ods() { |
| 5139 // class I1 { dynamic m(int); } |
| 5140 // class I2 { dynamic m(num); } |
| 5141 // class A implements I1, I2 {} |
| 5142 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5143 String methodName = "m"; |
| 5144 MethodElementImpl methodM1 = |
| 5145 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5146 ParameterElementImpl parameter1 = |
| 5147 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5148 parameter1.type = _typeProvider.intType; |
| 5149 parameter1.parameterKind = ParameterKind.REQUIRED; |
| 5150 methodM1.parameters = <ParameterElement>[parameter1]; |
| 5151 classI1.methods = <MethodElement>[methodM1]; |
| 5152 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5153 MethodElementImpl methodM2 = |
| 5154 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5155 ParameterElementImpl parameter2 = |
| 5156 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5157 parameter2.type = _typeProvider.numType; |
| 5158 parameter2.parameterKind = ParameterKind.REQUIRED; |
| 5159 methodM2.parameters = <ParameterElement>[parameter2]; |
| 5160 classI2.methods = <MethodElement>[methodM2]; |
| 5161 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5162 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5163 MemberMap mapA = |
| 5164 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5165 expect(mapA.size, _numOfMembersInObject + 1); |
| 5166 MethodElement syntheticMethod = ElementFactory.methodElement( |
| 5167 methodName, _typeProvider.dynamicType, [_typeProvider.dynamicType]); |
| 5168 expect(mapA.get(methodName).type, syntheticMethod.type); |
| 5169 _assertNoErrors(classA); |
| 5170 } |
| 5171 |
| 5172 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_sett
ers() { |
| 5173 // class I1 { set s(int); } |
| 5174 // class I2 { set s(num); } |
| 5175 // class A implements I1, I2 {} |
| 5176 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5177 String accessorName = "s"; |
| 5178 PropertyAccessorElement setter1 = ElementFactory.setterElement( |
| 5179 accessorName, false, _typeProvider.intType); |
| 5180 classI1.accessors = <PropertyAccessorElement>[setter1]; |
| 5181 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5182 PropertyAccessorElement setter2 = ElementFactory.setterElement( |
| 5183 accessorName, false, _typeProvider.numType); |
| 5184 classI2.accessors = <PropertyAccessorElement>[setter2]; |
| 5185 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5186 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5187 MemberMap mapA = |
| 5188 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5189 expect(mapA.size, _numOfMembersInObject + 1); |
| 5190 PropertyAccessorElementImpl syntheticAccessor = ElementFactory |
| 5191 .setterElement(accessorName, false, _typeProvider.dynamicType); |
| 5192 syntheticAccessor.returnType = _typeProvider.dynamicType; |
| 5193 expect(mapA.get("$accessorName=").type, syntheticAccessor.type); |
| 5194 _assertNoErrors(classA); |
| 5195 } |
| 5196 |
| 5197 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_gett
ers() { |
| 5198 // class A {} |
| 5199 // class B extends A {} |
| 5200 // class C extends B {} |
| 5201 // class I1 { A get g; } |
| 5202 // class I2 { B get g; } |
| 5203 // class I3 { C get g; } |
| 5204 // class D implements I1, I2, I3 {} |
| 5205 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5206 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5207 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); |
| 5208 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5209 String accessorName = "g"; |
| 5210 PropertyAccessorElement getter1 = |
| 5211 ElementFactory.getterElement(accessorName, false, classA.type); |
| 5212 classI1.accessors = <PropertyAccessorElement>[getter1]; |
| 5213 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5214 PropertyAccessorElement getter2 = |
| 5215 ElementFactory.getterElement(accessorName, false, classB.type); |
| 5216 classI2.accessors = <PropertyAccessorElement>[getter2]; |
| 5217 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5218 PropertyAccessorElement getter3 = |
| 5219 ElementFactory.getterElement(accessorName, false, classC.type); |
| 5220 classI3.accessors = <PropertyAccessorElement>[getter3]; |
| 5221 ClassElementImpl classD = ElementFactory.classElement2("D"); |
| 5222 classD.interfaces = <InterfaceType>[ |
| 5223 classI1.type, |
| 5224 classI2.type, |
| 5225 classI3.type |
| 5226 ]; |
| 5227 MemberMap mapD = |
| 5228 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); |
| 5229 expect(mapD.size, _numOfMembersInObject + 1); |
| 5230 PropertyAccessorElement syntheticAccessor = ElementFactory.getterElement( |
| 5231 accessorName, false, _typeProvider.dynamicType); |
| 5232 expect(mapD.get(accessorName).type, syntheticAccessor.type); |
| 5233 _assertNoErrors(classD); |
| 5234 } |
| 5235 |
| 5236 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_meth
ods() { |
| 5237 // class A {} |
| 5238 // class B extends A {} |
| 5239 // class C extends B {} |
| 5240 // class I1 { dynamic m(A a); } |
| 5241 // class I2 { dynamic m(B b); } |
| 5242 // class I3 { dynamic m(C c); } |
| 5243 // class D implements I1, I2, I3 {} |
| 5244 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5245 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5246 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); |
| 5247 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5248 String methodName = "m"; |
| 5249 MethodElementImpl methodM1 = |
| 5250 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5251 ParameterElementImpl parameter1 = |
| 5252 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5253 parameter1.type = classA.type; |
| 5254 parameter1.parameterKind = ParameterKind.REQUIRED; |
| 5255 methodM1.parameters = <ParameterElement>[parameter1]; |
| 5256 classI1.methods = <MethodElement>[methodM1]; |
| 5257 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5258 MethodElementImpl methodM2 = |
| 5259 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5260 ParameterElementImpl parameter2 = |
| 5261 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5262 parameter2.type = classB.type; |
| 5263 parameter2.parameterKind = ParameterKind.REQUIRED; |
| 5264 methodM2.parameters = <ParameterElement>[parameter2]; |
| 5265 classI2.methods = <MethodElement>[methodM2]; |
| 5266 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5267 MethodElementImpl methodM3 = |
| 5268 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5269 ParameterElementImpl parameter3 = |
| 5270 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5271 parameter3.type = classC.type; |
| 5272 parameter3.parameterKind = ParameterKind.REQUIRED; |
| 5273 methodM3.parameters = <ParameterElement>[parameter3]; |
| 5274 classI3.methods = <MethodElement>[methodM3]; |
| 5275 ClassElementImpl classD = ElementFactory.classElement2("D"); |
| 5276 classD.interfaces = <InterfaceType>[ |
| 5277 classI1.type, |
| 5278 classI2.type, |
| 5279 classI3.type |
| 5280 ]; |
| 5281 MemberMap mapD = |
| 5282 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); |
| 5283 expect(mapD.size, _numOfMembersInObject + 1); |
| 5284 MethodElement syntheticMethod = ElementFactory.methodElement( |
| 5285 methodName, _typeProvider.dynamicType, [_typeProvider.dynamicType]); |
| 5286 expect(mapD.get(methodName).type, syntheticMethod.type); |
| 5287 _assertNoErrors(classD); |
| 5288 } |
| 5289 |
| 5290 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_sett
ers() { |
| 5291 // class A {} |
| 5292 // class B extends A {} |
| 5293 // class C extends B {} |
| 5294 // class I1 { set s(A); } |
| 5295 // class I2 { set s(B); } |
| 5296 // class I3 { set s(C); } |
| 5297 // class D implements I1, I2, I3 {} |
| 5298 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5299 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5300 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); |
| 5301 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5302 String accessorName = "s"; |
| 5303 PropertyAccessorElement setter1 = |
| 5304 ElementFactory.setterElement(accessorName, false, classA.type); |
| 5305 classI1.accessors = <PropertyAccessorElement>[setter1]; |
| 5306 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5307 PropertyAccessorElement setter2 = |
| 5308 ElementFactory.setterElement(accessorName, false, classB.type); |
| 5309 classI2.accessors = <PropertyAccessorElement>[setter2]; |
| 5310 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5311 PropertyAccessorElement setter3 = |
| 5312 ElementFactory.setterElement(accessorName, false, classC.type); |
| 5313 classI3.accessors = <PropertyAccessorElement>[setter3]; |
| 5314 ClassElementImpl classD = ElementFactory.classElement2("D"); |
| 5315 classD.interfaces = <InterfaceType>[ |
| 5316 classI1.type, |
| 5317 classI2.type, |
| 5318 classI3.type |
| 5319 ]; |
| 5320 MemberMap mapD = |
| 5321 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); |
| 5322 expect(mapD.size, _numOfMembersInObject + 1); |
| 5323 PropertyAccessorElementImpl syntheticAccessor = ElementFactory |
| 5324 .setterElement(accessorName, false, _typeProvider.dynamicType); |
| 5325 syntheticAccessor.returnType = _typeProvider.dynamicType; |
| 5326 expect(mapD.get("$accessorName=").type, syntheticAccessor.type); |
| 5327 _assertNoErrors(classD); |
| 5328 } |
| 5329 |
| 5330 void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_2_methods()
{ |
| 5331 // class I1 { int m(); } |
| 5332 // class I2 { int m([int]); } |
| 5333 // class A implements I1, I2 {} |
| 5334 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5335 String methodName = "m"; |
| 5336 MethodElement methodM1 = |
| 5337 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5338 classI1.methods = <MethodElement>[methodM1]; |
| 5339 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5340 MethodElementImpl methodM2 = |
| 5341 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5342 ParameterElementImpl parameter1 = |
| 5343 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); |
| 5344 parameter1.type = _typeProvider.intType; |
| 5345 parameter1.parameterKind = ParameterKind.POSITIONAL; |
| 5346 methodM2.parameters = <ParameterElement>[parameter1]; |
| 5347 classI2.methods = <MethodElement>[methodM2]; |
| 5348 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5349 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5350 MemberMap mapA = |
| 5351 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5352 expect(mapA.size, _numOfMembersInObject + 1); |
| 5353 expect(mapA.get(methodName), same(methodM2)); |
| 5354 _assertNoErrors(classA); |
| 5355 } |
| 5356 |
| 5357 void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_3_methods()
{ |
| 5358 // class I1 { int m(); } |
| 5359 // class I2 { int m([int]); } |
| 5360 // class I3 { int m([int, int]); } |
| 5361 // class A implements I1, I2, I3 {} |
| 5362 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5363 String methodName = "m"; |
| 5364 MethodElementImpl methodM1 = |
| 5365 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5366 classI1.methods = <MethodElement>[methodM1]; |
| 5367 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5368 MethodElementImpl methodM2 = |
| 5369 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5370 ParameterElementImpl parameter1 = |
| 5371 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); |
| 5372 parameter1.type = _typeProvider.intType; |
| 5373 parameter1.parameterKind = ParameterKind.POSITIONAL; |
| 5374 methodM1.parameters = <ParameterElement>[parameter1]; |
| 5375 classI2.methods = <MethodElement>[methodM2]; |
| 5376 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5377 MethodElementImpl methodM3 = |
| 5378 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5379 ParameterElementImpl parameter2 = |
| 5380 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); |
| 5381 parameter2.type = _typeProvider.intType; |
| 5382 parameter2.parameterKind = ParameterKind.POSITIONAL; |
| 5383 ParameterElementImpl parameter3 = |
| 5384 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); |
| 5385 parameter3.type = _typeProvider.intType; |
| 5386 parameter3.parameterKind = ParameterKind.POSITIONAL; |
| 5387 methodM3.parameters = <ParameterElement>[parameter2, parameter3]; |
| 5388 classI3.methods = <MethodElement>[methodM3]; |
| 5389 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5390 classA.interfaces = <InterfaceType>[ |
| 5391 classI1.type, |
| 5392 classI2.type, |
| 5393 classI3.type |
| 5394 ]; |
| 5395 MemberMap mapA = |
| 5396 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5397 expect(mapA.size, _numOfMembersInObject + 1); |
| 5398 expect(mapA.get(methodName), same(methodM3)); |
| 5399 _assertNoErrors(classA); |
| 5400 } |
| 5401 |
| 5402 void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_4_methods()
{ |
| 5403 // class I1 { int m(); } |
| 5404 // class I2 { int m(); } |
| 5405 // class I3 { int m([int]); } |
| 5406 // class I4 { int m([int, int]); } |
| 5407 // class A implements I1, I2, I3, I4 {} |
| 5408 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5409 String methodName = "m"; |
| 5410 MethodElement methodM1 = |
| 5411 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5412 classI1.methods = <MethodElement>[methodM1]; |
| 5413 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5414 MethodElement methodM2 = |
| 5415 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5416 classI2.methods = <MethodElement>[methodM2]; |
| 5417 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5418 MethodElementImpl methodM3 = |
| 5419 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5420 ParameterElementImpl parameter1 = |
| 5421 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); |
| 5422 parameter1.type = _typeProvider.intType; |
| 5423 parameter1.parameterKind = ParameterKind.POSITIONAL; |
| 5424 methodM3.parameters = <ParameterElement>[parameter1]; |
| 5425 classI3.methods = <MethodElement>[methodM3]; |
| 5426 ClassElementImpl classI4 = ElementFactory.classElement2("I4"); |
| 5427 MethodElementImpl methodM4 = |
| 5428 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5429 ParameterElementImpl parameter2 = |
| 5430 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); |
| 5431 parameter2.type = _typeProvider.intType; |
| 5432 parameter2.parameterKind = ParameterKind.POSITIONAL; |
| 5433 ParameterElementImpl parameter3 = |
| 5434 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); |
| 5435 parameter3.type = _typeProvider.intType; |
| 5436 parameter3.parameterKind = ParameterKind.POSITIONAL; |
| 5437 methodM4.parameters = <ParameterElement>[parameter2, parameter3]; |
| 5438 classI4.methods = <MethodElement>[methodM4]; |
| 5439 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5440 classA.interfaces = <InterfaceType>[ |
| 5441 classI1.type, |
| 5442 classI2.type, |
| 5443 classI3.type, |
| 5444 classI4.type |
| 5445 ]; |
| 5446 MemberMap mapA = |
| 5447 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5448 expect(mapA.size, _numOfMembersInObject + 1); |
| 5449 expect(mapA.get(methodName), same(methodM4)); |
| 5450 _assertNoErrors(classA); |
| 5451 } |
| 5452 |
| 5453 void test_lookupInheritance_interface_getter() { |
| 5454 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5455 String getterName = "g"; |
| 5456 PropertyAccessorElement getterG = |
| 5457 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 5458 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5459 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5460 classB.interfaces = <InterfaceType>[classA.type]; |
| 5461 expect(_inheritanceManager.lookupInheritance(classB, getterName), |
| 5462 same(getterG)); |
| 5463 _assertNoErrors(classA); |
| 5464 _assertNoErrors(classB); |
| 5465 } |
| 5466 |
| 5467 void test_lookupInheritance_interface_method() { |
| 5468 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5469 String methodName = "m"; |
| 5470 MethodElement methodM = |
| 5471 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5472 classA.methods = <MethodElement>[methodM]; |
| 5473 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5474 classB.interfaces = <InterfaceType>[classA.type]; |
| 5475 expect(_inheritanceManager.lookupInheritance(classB, methodName), |
| 5476 same(methodM)); |
| 5477 _assertNoErrors(classA); |
| 5478 _assertNoErrors(classB); |
| 5479 } |
| 5480 |
| 5481 void test_lookupInheritance_interface_setter() { |
| 5482 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5483 String setterName = "s"; |
| 5484 PropertyAccessorElement setterS = |
| 5485 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 5486 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5487 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5488 classB.interfaces = <InterfaceType>[classA.type]; |
| 5489 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), |
| 5490 same(setterS)); |
| 5491 _assertNoErrors(classA); |
| 5492 _assertNoErrors(classB); |
| 5493 } |
| 5494 |
| 5495 void test_lookupInheritance_interface_staticMember() { |
| 5496 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5497 String methodName = "m"; |
| 5498 MethodElement methodM = |
| 5499 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5500 (methodM as MethodElementImpl).static = true; |
| 5501 classA.methods = <MethodElement>[methodM]; |
| 5502 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5503 classB.interfaces = <InterfaceType>[classA.type]; |
| 5504 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); |
| 5505 _assertNoErrors(classA); |
| 5506 _assertNoErrors(classB); |
| 5507 } |
| 5508 |
| 5509 void test_lookupInheritance_interfaces_infiniteLoop() { |
| 5510 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5511 classA.interfaces = <InterfaceType>[classA.type]; |
| 5512 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); |
| 5513 _assertNoErrors(classA); |
| 5514 } |
| 5515 |
| 5516 void test_lookupInheritance_interfaces_infiniteLoop2() { |
| 5517 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5518 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5519 classA.interfaces = <InterfaceType>[classB.type]; |
| 5520 classB.interfaces = <InterfaceType>[classA.type]; |
| 5521 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); |
| 5522 _assertNoErrors(classA); |
| 5523 _assertNoErrors(classB); |
| 5524 } |
| 5525 |
| 5526 void test_lookupInheritance_interfaces_union2() { |
| 5527 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5528 String methodName1 = "m1"; |
| 5529 MethodElement methodM1 = |
| 5530 ElementFactory.methodElement(methodName1, _typeProvider.intType); |
| 5531 classI1.methods = <MethodElement>[methodM1]; |
| 5532 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5533 String methodName2 = "m2"; |
| 5534 MethodElement methodM2 = |
| 5535 ElementFactory.methodElement(methodName2, _typeProvider.intType); |
| 5536 classI2.methods = <MethodElement>[methodM2]; |
| 5537 classI2.interfaces = <InterfaceType>[classI1.type]; |
| 5538 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5539 classA.interfaces = <InterfaceType>[classI2.type]; |
| 5540 expect(_inheritanceManager.lookupInheritance(classA, methodName1), |
| 5541 same(methodM1)); |
| 5542 expect(_inheritanceManager.lookupInheritance(classA, methodName2), |
| 5543 same(methodM2)); |
| 5544 _assertNoErrors(classI1); |
| 5545 _assertNoErrors(classI2); |
| 5546 _assertNoErrors(classA); |
| 5547 } |
| 5548 |
| 5549 void test_lookupInheritance_mixin_getter() { |
| 5550 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5551 String getterName = "g"; |
| 5552 PropertyAccessorElement getterG = |
| 5553 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 5554 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5555 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5556 classB.mixins = <InterfaceType>[classA.type]; |
| 5557 expect(_inheritanceManager.lookupInheritance(classB, getterName), |
| 5558 same(getterG)); |
| 5559 _assertNoErrors(classA); |
| 5560 _assertNoErrors(classB); |
| 5561 } |
| 5562 |
| 5563 void test_lookupInheritance_mixin_method() { |
| 5564 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5565 String methodName = "m"; |
| 5566 MethodElement methodM = |
| 5567 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5568 classA.methods = <MethodElement>[methodM]; |
| 5569 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5570 classB.mixins = <InterfaceType>[classA.type]; |
| 5571 expect(_inheritanceManager.lookupInheritance(classB, methodName), |
| 5572 same(methodM)); |
| 5573 _assertNoErrors(classA); |
| 5574 _assertNoErrors(classB); |
| 5575 } |
| 5576 |
| 5577 void test_lookupInheritance_mixin_setter() { |
| 5578 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5579 String setterName = "s"; |
| 5580 PropertyAccessorElement setterS = |
| 5581 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 5582 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5583 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5584 classB.mixins = <InterfaceType>[classA.type]; |
| 5585 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), |
| 5586 same(setterS)); |
| 5587 _assertNoErrors(classA); |
| 5588 _assertNoErrors(classB); |
| 5589 } |
| 5590 |
| 5591 void test_lookupInheritance_mixin_staticMember() { |
| 5592 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5593 String methodName = "m"; |
| 5594 MethodElement methodM = |
| 5595 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5596 (methodM as MethodElementImpl).static = true; |
| 5597 classA.methods = <MethodElement>[methodM]; |
| 5598 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5599 classB.mixins = <InterfaceType>[classA.type]; |
| 5600 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); |
| 5601 _assertNoErrors(classA); |
| 5602 _assertNoErrors(classB); |
| 5603 } |
| 5604 |
| 5605 void test_lookupInheritance_noMember() { |
| 5606 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5607 expect(_inheritanceManager.lookupInheritance(classA, "a"), isNull); |
| 5608 _assertNoErrors(classA); |
| 5609 } |
| 5610 |
| 5611 void test_lookupInheritance_superclass_getter() { |
| 5612 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5613 String getterName = "g"; |
| 5614 PropertyAccessorElement getterG = |
| 5615 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 5616 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5617 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5618 expect(_inheritanceManager.lookupInheritance(classB, getterName), |
| 5619 same(getterG)); |
| 5620 _assertNoErrors(classA); |
| 5621 _assertNoErrors(classB); |
| 5622 } |
| 5623 |
| 5624 void test_lookupInheritance_superclass_infiniteLoop() { |
| 5625 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5626 classA.supertype = classA.type; |
| 5627 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); |
| 5628 _assertNoErrors(classA); |
| 5629 } |
| 5630 |
| 5631 void test_lookupInheritance_superclass_infiniteLoop2() { |
| 5632 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5633 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5634 classA.supertype = classB.type; |
| 5635 classB.supertype = classA.type; |
| 5636 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); |
| 5637 _assertNoErrors(classA); |
| 5638 _assertNoErrors(classB); |
| 5639 } |
| 5640 |
| 5641 void test_lookupInheritance_superclass_method() { |
| 5642 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5643 String methodName = "m"; |
| 5644 MethodElement methodM = |
| 5645 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5646 classA.methods = <MethodElement>[methodM]; |
| 5647 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5648 expect(_inheritanceManager.lookupInheritance(classB, methodName), |
| 5649 same(methodM)); |
| 5650 _assertNoErrors(classA); |
| 5651 _assertNoErrors(classB); |
| 5652 } |
| 5653 |
| 5654 void test_lookupInheritance_superclass_setter() { |
| 5655 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5656 String setterName = "s"; |
| 5657 PropertyAccessorElement setterS = |
| 5658 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 5659 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5660 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5661 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), |
| 5662 same(setterS)); |
| 5663 _assertNoErrors(classA); |
| 5664 _assertNoErrors(classB); |
| 5665 } |
| 5666 |
| 5667 void test_lookupInheritance_superclass_staticMember() { |
| 5668 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5669 String methodName = "m"; |
| 5670 MethodElement methodM = |
| 5671 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5672 (methodM as MethodElementImpl).static = true; |
| 5673 classA.methods = <MethodElement>[methodM]; |
| 5674 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5675 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); |
| 5676 _assertNoErrors(classA); |
| 5677 _assertNoErrors(classB); |
| 5678 } |
| 5679 |
| 5680 void test_lookupMember_getter() { |
| 5681 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5682 String getterName = "g"; |
| 5683 PropertyAccessorElement getterG = |
| 5684 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 5685 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5686 expect(_inheritanceManager.lookupMember(classA, getterName), same(getterG)); |
| 5687 _assertNoErrors(classA); |
| 5688 } |
| 5689 |
| 5690 void test_lookupMember_getter_static() { |
| 5691 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5692 String getterName = "g"; |
| 5693 PropertyAccessorElement getterG = |
| 5694 ElementFactory.getterElement(getterName, true, _typeProvider.intType); |
| 5695 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5696 expect(_inheritanceManager.lookupMember(classA, getterName), isNull); |
| 5697 _assertNoErrors(classA); |
| 5698 } |
| 5699 |
| 5700 void test_lookupMember_method() { |
| 5701 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5702 String methodName = "m"; |
| 5703 MethodElement methodM = |
| 5704 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5705 classA.methods = <MethodElement>[methodM]; |
| 5706 expect(_inheritanceManager.lookupMember(classA, methodName), same(methodM)); |
| 5707 _assertNoErrors(classA); |
| 5708 } |
| 5709 |
| 5710 void test_lookupMember_method_static() { |
| 5711 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5712 String methodName = "m"; |
| 5713 MethodElement methodM = |
| 5714 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5715 (methodM as MethodElementImpl).static = true; |
| 5716 classA.methods = <MethodElement>[methodM]; |
| 5717 expect(_inheritanceManager.lookupMember(classA, methodName), isNull); |
| 5718 _assertNoErrors(classA); |
| 5719 } |
| 5720 |
| 5721 void test_lookupMember_noMember() { |
| 5722 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5723 expect(_inheritanceManager.lookupMember(classA, "a"), isNull); |
| 5724 _assertNoErrors(classA); |
| 5725 } |
| 5726 |
| 5727 void test_lookupMember_setter() { |
| 5728 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5729 String setterName = "s"; |
| 5730 PropertyAccessorElement setterS = |
| 5731 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 5732 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5733 expect(_inheritanceManager.lookupMember(classA, "$setterName="), |
| 5734 same(setterS)); |
| 5735 _assertNoErrors(classA); |
| 5736 } |
| 5737 |
| 5738 void test_lookupMember_setter_static() { |
| 5739 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5740 String setterName = "s"; |
| 5741 PropertyAccessorElement setterS = |
| 5742 ElementFactory.setterElement(setterName, true, _typeProvider.intType); |
| 5743 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5744 expect(_inheritanceManager.lookupMember(classA, setterName), isNull); |
| 5745 _assertNoErrors(classA); |
| 5746 } |
| 5747 |
| 5748 void test_lookupOverrides_noParentClasses() { |
| 5749 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5750 String methodName = "m"; |
| 5751 MethodElementImpl methodM = |
| 5752 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5753 classA.methods = <MethodElement>[methodM]; |
| 5754 expect( |
| 5755 _inheritanceManager.lookupOverrides(classA, methodName), hasLength(0)); |
| 5756 _assertNoErrors(classA); |
| 5757 } |
| 5758 |
| 5759 void test_lookupOverrides_overrideBaseClass() { |
| 5760 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5761 String methodName = "m"; |
| 5762 MethodElementImpl methodMinA = |
| 5763 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5764 classA.methods = <MethodElement>[methodMinA]; |
| 5765 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5766 MethodElementImpl methodMinB = |
| 5767 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5768 classB.methods = <MethodElement>[methodMinB]; |
| 5769 List<ExecutableElement> overrides = |
| 5770 _inheritanceManager.lookupOverrides(classB, methodName); |
| 5771 expect(overrides, unorderedEquals([methodMinA])); |
| 5772 _assertNoErrors(classA); |
| 5773 _assertNoErrors(classB); |
| 5774 } |
| 5775 |
| 5776 void test_lookupOverrides_overrideInterface() { |
| 5777 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5778 String methodName = "m"; |
| 5779 MethodElementImpl methodMinA = |
| 5780 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5781 classA.methods = <MethodElement>[methodMinA]; |
| 5782 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5783 classB.interfaces = <InterfaceType>[classA.type]; |
| 5784 MethodElementImpl methodMinB = |
| 5785 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5786 classB.methods = <MethodElement>[methodMinB]; |
| 5787 List<ExecutableElement> overrides = |
| 5788 _inheritanceManager.lookupOverrides(classB, methodName); |
| 5789 expect(overrides, unorderedEquals([methodMinA])); |
| 5790 _assertNoErrors(classA); |
| 5791 _assertNoErrors(classB); |
| 5792 } |
| 5793 |
| 5794 void test_lookupOverrides_overrideTwoInterfaces() { |
| 5795 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5796 String methodName = "m"; |
| 5797 MethodElementImpl methodMinA = |
| 5798 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5799 classA.methods = <MethodElement>[methodMinA]; |
| 5800 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5801 MethodElementImpl methodMinB = |
| 5802 ElementFactory.methodElement(methodName, _typeProvider.doubleType); |
| 5803 classB.methods = <MethodElement>[methodMinB]; |
| 5804 ClassElementImpl classC = ElementFactory.classElement2("C"); |
| 5805 classC.interfaces = <InterfaceType>[classA.type, classB.type]; |
| 5806 MethodElementImpl methodMinC = |
| 5807 ElementFactory.methodElement(methodName, _typeProvider.numType); |
| 5808 classC.methods = <MethodElement>[methodMinC]; |
| 5809 List<ExecutableElement> overrides = |
| 5810 _inheritanceManager.lookupOverrides(classC, methodName); |
| 5811 expect(overrides, unorderedEquals([methodMinA, methodMinB])); |
| 5812 _assertNoErrors(classA); |
| 5813 _assertNoErrors(classB); |
| 5814 _assertNoErrors(classC); |
| 5815 } |
| 5816 |
| 5817 void _assertErrors(ClassElement classElt, |
| 5818 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { |
| 5819 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 5820 HashSet<AnalysisError> actualErrors = |
| 5821 _inheritanceManager.getErrors(classElt); |
| 5822 if (actualErrors != null) { |
| 5823 for (AnalysisError error in actualErrors) { |
| 5824 errorListener.onError(error); |
| 5825 } |
| 5826 } |
| 5827 errorListener.assertErrorsWithCodes(expectedErrorCodes); |
| 5828 } |
| 5829 |
| 5830 void _assertNoErrors(ClassElement classElt) { |
| 5831 _assertErrors(classElt); |
| 5832 } |
| 5833 |
| 5834 /** |
| 5835 * Create the inheritance manager used by the tests. |
| 5836 * |
| 5837 * @return the inheritance manager that was created |
| 5838 */ |
| 5839 InheritanceManager _createInheritanceManager() { |
| 5840 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 5841 FileBasedSource source = |
| 5842 new FileBasedSource(FileUtilities2.createFile("/test.dart")); |
| 5843 CompilationUnitElementImpl definingCompilationUnit = |
| 5844 new CompilationUnitElementImpl("test.dart"); |
| 5845 definingCompilationUnit.librarySource = |
| 5846 definingCompilationUnit.source = source; |
| 5847 _definingLibrary = ElementFactory.library(context, "test"); |
| 5848 _definingLibrary.definingCompilationUnit = definingCompilationUnit; |
| 5849 return new InheritanceManager(_definingLibrary); |
| 5850 } |
| 5851 } |
| 5852 |
| 5853 @reflectiveTest |
| 5854 class LibraryElementBuilderTest extends EngineTestCase { |
| 5855 /** |
| 5856 * The analysis context used to analyze sources. |
| 5857 */ |
| 5858 InternalAnalysisContext _context; |
| 5859 |
| 5860 /** |
| 5861 * Add a source file to the content provider. The file path should be absolute
. |
| 5862 * |
| 5863 * @param filePath the path of the file being added |
| 5864 * @param contents the contents to be returned by the content provider for the
specified file |
| 5865 * @return the source object representing the added file |
| 5866 */ |
| 5867 Source addSource(String filePath, String contents) { |
| 5868 Source source = new FileBasedSource(FileUtilities2.createFile(filePath)); |
| 5869 _context.setContents(source, contents); |
| 5870 return source; |
| 5871 } |
| 5872 |
| 5873 @override |
| 5874 void setUp() { |
| 5875 _context = AnalysisContextFactory.contextWithCore(); |
| 5876 } |
| 5877 |
| 5878 @override |
| 5879 void tearDown() { |
| 5880 _context = null; |
| 5881 super.tearDown(); |
| 5882 } |
| 5883 |
| 5884 void test_accessorsAcrossFiles() { |
| 5885 Source librarySource = addSource( |
| 5886 "/lib.dart", |
| 5887 r''' |
| 5888 library lib; |
| 5889 part 'first.dart'; |
| 5890 part 'second.dart';'''); |
| 5891 addSource( |
| 5892 "/first.dart", |
| 5893 r''' |
| 5894 part of lib; |
| 5895 int get V => 0;'''); |
| 5896 addSource( |
| 5897 "/second.dart", |
| 5898 r''' |
| 5899 part of lib; |
| 5900 void set V(int v) {}'''); |
| 5901 LibraryElement element = _buildLibrary(librarySource); |
| 5902 expect(element, isNotNull); |
| 5903 List<CompilationUnitElement> sourcedUnits = element.parts; |
| 5904 expect(sourcedUnits, hasLength(2)); |
| 5905 List<PropertyAccessorElement> firstAccessors = sourcedUnits[0].accessors; |
| 5906 expect(firstAccessors, hasLength(1)); |
| 5907 List<PropertyAccessorElement> secondAccessors = sourcedUnits[1].accessors; |
| 5908 expect(secondAccessors, hasLength(1)); |
| 5909 expect(secondAccessors[0].variable, same(firstAccessors[0].variable)); |
| 5910 } |
| 5911 |
| 5912 void test_empty() { |
| 5913 Source librarySource = addSource("/lib.dart", "library lib;"); |
| 5914 LibraryElement element = _buildLibrary(librarySource); |
| 5915 expect(element, isNotNull); |
| 5916 expect(element.name, "lib"); |
| 5917 expect(element.entryPoint, isNull); |
| 5918 expect(element.importedLibraries, hasLength(0)); |
| 5919 expect(element.imports, hasLength(0)); |
| 5920 expect(element.library, same(element)); |
| 5921 expect(element.prefixes, hasLength(0)); |
| 5922 expect(element.parts, hasLength(0)); |
| 5923 CompilationUnitElement unit = element.definingCompilationUnit; |
| 5924 expect(unit, isNotNull); |
| 5925 expect(unit.name, "lib.dart"); |
| 5926 expect(unit.library, element); |
| 5927 expect(unit.accessors, hasLength(0)); |
| 5928 expect(unit.functions, hasLength(0)); |
| 5929 expect(unit.functionTypeAliases, hasLength(0)); |
| 5930 expect(unit.types, hasLength(0)); |
| 5931 expect(unit.topLevelVariables, hasLength(0)); |
| 5932 } |
| 5933 |
| 5934 void test_libraryElement_docRange() { |
| 5935 String code = r''' |
| 5936 /// My dart doc. |
| 5937 library lib; |
| 5938 |
| 5939 class A {}'''; |
| 5940 Source librarySource = addSource("/lib.dart", code); |
| 5941 LibraryElement element = _buildLibrary(librarySource); |
| 5942 expect(element, isNotNull); |
| 5943 SourceRange docRange = element.docRange; |
| 5944 expect(docRange, isNotNull); |
| 5945 expect(docRange.offset, code.indexOf('/// My dart doc.')); |
| 5946 expect(docRange.length, '/// My dart doc.'.length); |
| 5947 } |
| 5948 |
| 5949 void test_missingLibraryDirectiveWithPart() { |
| 5950 addSource("/a.dart", "part of lib;"); |
| 5951 Source librarySource = addSource("/lib.dart", "part 'a.dart';"); |
| 5952 LibraryElement element = _buildLibrary( |
| 5953 librarySource, [ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART]); |
| 5954 expect(element, isNotNull); |
| 5955 } |
| 5956 |
| 5957 void test_missingPartOfDirective() { |
| 5958 addSource("/a.dart", "class A {}"); |
| 5959 Source librarySource = addSource( |
| 5960 "/lib.dart", |
| 5961 r''' |
| 5962 library lib; |
| 5963 |
| 5964 part 'a.dart';'''); |
| 5965 LibraryElement element = |
| 5966 _buildLibrary(librarySource, [CompileTimeErrorCode.PART_OF_NON_PART]); |
| 5967 expect(element, isNotNull); |
| 5968 } |
| 5969 |
| 5970 void test_multipleFiles() { |
| 5971 Source librarySource = addSource( |
| 5972 "/lib.dart", |
| 5973 r''' |
| 5974 library lib; |
| 5975 part 'first.dart'; |
| 5976 part 'second.dart'; |
| 5977 |
| 5978 class A {}'''); |
| 5979 addSource( |
| 5980 "/first.dart", |
| 5981 r''' |
| 5982 part of lib; |
| 5983 class B {}'''); |
| 5984 addSource( |
| 5985 "/second.dart", |
| 5986 r''' |
| 5987 part of lib; |
| 5988 class C {}'''); |
| 5989 LibraryElement element = _buildLibrary(librarySource); |
| 5990 expect(element, isNotNull); |
| 5991 List<CompilationUnitElement> sourcedUnits = element.parts; |
| 5992 expect(sourcedUnits, hasLength(2)); |
| 5993 _assertTypes(element.definingCompilationUnit, ["A"]); |
| 5994 if (sourcedUnits[0].name == "first.dart") { |
| 5995 _assertTypes(sourcedUnits[0], ["B"]); |
| 5996 _assertTypes(sourcedUnits[1], ["C"]); |
| 5997 } else { |
| 5998 _assertTypes(sourcedUnits[0], ["C"]); |
| 5999 _assertTypes(sourcedUnits[1], ["B"]); |
| 6000 } |
| 6001 } |
| 6002 |
| 6003 void test_singleFile() { |
| 6004 Source librarySource = addSource( |
| 6005 "/lib.dart", |
| 6006 r''' |
| 6007 /// My dart doc. |
| 6008 library lib; |
| 6009 |
| 6010 class A {}'''); |
| 6011 LibraryElement element = _buildLibrary(librarySource); |
| 6012 expect(element, isNotNull); |
| 6013 _assertTypes(element.definingCompilationUnit, ["A"]); |
| 6014 } |
| 6015 |
| 6016 /** |
| 6017 * Ensure that there are elements representing all of the types in the given a
rray of type names. |
| 6018 * |
| 6019 * @param unit the compilation unit containing the types |
| 6020 * @param typeNames the names of the types that should be found |
| 6021 */ |
| 6022 void _assertTypes(CompilationUnitElement unit, List<String> typeNames) { |
| 6023 expect(unit, isNotNull); |
| 6024 List<ClassElement> types = unit.types; |
| 6025 expect(types, hasLength(typeNames.length)); |
| 6026 for (ClassElement type in types) { |
| 6027 expect(type, isNotNull); |
| 6028 String actualTypeName = type.displayName; |
| 6029 bool wasExpected = false; |
| 6030 for (String expectedTypeName in typeNames) { |
| 6031 if (expectedTypeName == actualTypeName) { |
| 6032 wasExpected = true; |
| 6033 } |
| 6034 } |
| 6035 if (!wasExpected) { |
| 6036 fail("Found unexpected type $actualTypeName"); |
| 6037 } |
| 6038 } |
| 6039 } |
| 6040 |
| 6041 /** |
| 6042 * Build the element model for the library whose defining compilation unit has
the given source. |
| 6043 * |
| 6044 * @param librarySource the source of the defining compilation unit for the li
brary |
| 6045 * @param expectedErrorCodes the errors that are expected to be found while bu
ilding the element |
| 6046 * model |
| 6047 * @return the element model that was built for the library |
| 6048 * @throws Exception if the element model could not be built |
| 6049 */ |
| 6050 LibraryElement _buildLibrary(Source librarySource, |
| 6051 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { |
| 6052 LibraryResolver resolver = new LibraryResolver(_context); |
| 6053 LibraryElementBuilder builder = new LibraryElementBuilder( |
| 6054 resolver.analysisContext, resolver.errorListener); |
| 6055 Library library = resolver.createLibrary(librarySource); |
| 6056 LibraryElement element = builder.buildLibrary(library); |
| 6057 GatheringErrorListener listener = new GatheringErrorListener(); |
| 6058 listener.addAll2(resolver.errorListener); |
| 6059 listener.assertErrorsWithCodes(expectedErrorCodes); |
| 6060 return element; |
| 6061 } |
| 6062 } |
| 6063 |
| 6064 @reflectiveTest |
| 6065 class LibraryImportScopeTest extends ResolverTestCase { |
| 6066 void test_conflictingImports() { |
| 6067 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6068 String typeNameA = "A"; |
| 6069 String typeNameB = "B"; |
| 6070 String typeNameC = "C"; |
| 6071 ClassElement typeA = ElementFactory.classElement2(typeNameA); |
| 6072 ClassElement typeB1 = ElementFactory.classElement2(typeNameB); |
| 6073 ClassElement typeB2 = ElementFactory.classElement2(typeNameB); |
| 6074 ClassElement typeC = ElementFactory.classElement2(typeNameC); |
| 6075 LibraryElement importedLibrary1 = createTestLibrary(context, "imported1"); |
| 6076 (importedLibrary1.definingCompilationUnit as CompilationUnitElementImpl) |
| 6077 .types = <ClassElement>[typeA, typeB1]; |
| 6078 ImportElementImpl import1 = |
| 6079 ElementFactory.importFor(importedLibrary1, null); |
| 6080 LibraryElement importedLibrary2 = createTestLibrary(context, "imported2"); |
| 6081 (importedLibrary2.definingCompilationUnit as CompilationUnitElementImpl) |
| 6082 .types = <ClassElement>[typeB2, typeC]; |
| 6083 ImportElementImpl import2 = |
| 6084 ElementFactory.importFor(importedLibrary2, null); |
| 6085 LibraryElementImpl importingLibrary = |
| 6086 createTestLibrary(context, "importing"); |
| 6087 importingLibrary.imports = <ImportElement>[import1, import2]; |
| 6088 { |
| 6089 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6090 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6091 expect(scope.lookup(AstFactory.identifier3(typeNameA), importingLibrary), |
| 6092 typeA); |
| 6093 errorListener.assertNoErrors(); |
| 6094 expect(scope.lookup(AstFactory.identifier3(typeNameC), importingLibrary), |
| 6095 typeC); |
| 6096 errorListener.assertNoErrors(); |
| 6097 Element element = |
| 6098 scope.lookup(AstFactory.identifier3(typeNameB), importingLibrary); |
| 6099 errorListener.assertErrorsWithCodes([StaticWarningCode.AMBIGUOUS_IMPORT]); |
| 6100 EngineTestCase.assertInstanceOf((obj) => obj is MultiplyDefinedElement, |
| 6101 MultiplyDefinedElement, element); |
| 6102 List<Element> conflictingElements = |
| 6103 (element as MultiplyDefinedElement).conflictingElements; |
| 6104 expect(conflictingElements, hasLength(2)); |
| 6105 if (identical(conflictingElements[0], typeB1)) { |
| 6106 expect(conflictingElements[1], same(typeB2)); |
| 6107 } else if (identical(conflictingElements[0], typeB2)) { |
| 6108 expect(conflictingElements[1], same(typeB1)); |
| 6109 } else { |
| 6110 expect(conflictingElements[0], same(typeB1)); |
| 6111 } |
| 6112 } |
| 6113 { |
| 6114 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6115 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6116 Identifier identifier = AstFactory.identifier3(typeNameB); |
| 6117 AstFactory.methodDeclaration(null, AstFactory.typeName3(identifier), null, |
| 6118 null, AstFactory.identifier3("foo"), null); |
| 6119 Element element = scope.lookup(identifier, importingLibrary); |
| 6120 errorListener.assertErrorsWithCodes([StaticWarningCode.AMBIGUOUS_IMPORT]); |
| 6121 EngineTestCase.assertInstanceOf((obj) => obj is MultiplyDefinedElement, |
| 6122 MultiplyDefinedElement, element); |
| 6123 } |
| 6124 } |
| 6125 |
| 6126 void test_creation_empty() { |
| 6127 LibraryElement definingLibrary = createDefaultTestLibrary(); |
| 6128 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6129 new LibraryImportScope(definingLibrary, errorListener); |
| 6130 } |
| 6131 |
| 6132 void test_creation_nonEmpty() { |
| 6133 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6134 String importedTypeName = "A"; |
| 6135 ClassElement importedType = |
| 6136 new ClassElementImpl.forNode(AstFactory.identifier3(importedTypeName)); |
| 6137 LibraryElement importedLibrary = createTestLibrary(context, "imported"); |
| 6138 (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6139 .types = <ClassElement>[importedType]; |
| 6140 LibraryElementImpl definingLibrary = |
| 6141 createTestLibrary(context, "importing"); |
| 6142 ImportElementImpl importElement = new ImportElementImpl(0); |
| 6143 importElement.importedLibrary = importedLibrary; |
| 6144 definingLibrary.imports = <ImportElement>[importElement]; |
| 6145 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6146 Scope scope = new LibraryImportScope(definingLibrary, errorListener); |
| 6147 expect( |
| 6148 scope.lookup(AstFactory.identifier3(importedTypeName), definingLibrary), |
| 6149 importedType); |
| 6150 } |
| 6151 |
| 6152 void test_getErrorListener() { |
| 6153 LibraryElement definingLibrary = createDefaultTestLibrary(); |
| 6154 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6155 LibraryImportScope scope = |
| 6156 new LibraryImportScope(definingLibrary, errorListener); |
| 6157 expect(scope.errorListener, errorListener); |
| 6158 } |
| 6159 |
| 6160 void test_nonConflictingImports_fromSdk() { |
| 6161 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6162 String typeName = "List"; |
| 6163 ClassElement type = ElementFactory.classElement2(typeName); |
| 6164 LibraryElement importedLibrary = createTestLibrary(context, "lib"); |
| 6165 (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6166 .types = <ClassElement>[type]; |
| 6167 ImportElementImpl importCore = ElementFactory.importFor( |
| 6168 context.getLibraryElement(context.sourceFactory.forUri("dart:core")), |
| 6169 null); |
| 6170 ImportElementImpl importLib = |
| 6171 ElementFactory.importFor(importedLibrary, null); |
| 6172 LibraryElementImpl importingLibrary = |
| 6173 createTestLibrary(context, "importing"); |
| 6174 importingLibrary.imports = <ImportElement>[importCore, importLib]; |
| 6175 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6176 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6177 expect( |
| 6178 scope.lookup(AstFactory.identifier3(typeName), importingLibrary), type); |
| 6179 errorListener |
| 6180 .assertErrorsWithCodes([StaticWarningCode.CONFLICTING_DART_IMPORT]); |
| 6181 } |
| 6182 |
| 6183 void test_nonConflictingImports_sameElement() { |
| 6184 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6185 String typeNameA = "A"; |
| 6186 String typeNameB = "B"; |
| 6187 ClassElement typeA = ElementFactory.classElement2(typeNameA); |
| 6188 ClassElement typeB = ElementFactory.classElement2(typeNameB); |
| 6189 LibraryElement importedLibrary = createTestLibrary(context, "imported"); |
| 6190 (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6191 .types = <ClassElement>[typeA, typeB]; |
| 6192 ImportElementImpl import1 = ElementFactory.importFor(importedLibrary, null); |
| 6193 ImportElementImpl import2 = ElementFactory.importFor(importedLibrary, null); |
| 6194 LibraryElementImpl importingLibrary = |
| 6195 createTestLibrary(context, "importing"); |
| 6196 importingLibrary.imports = <ImportElement>[import1, import2]; |
| 6197 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6198 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6199 expect(scope.lookup(AstFactory.identifier3(typeNameA), importingLibrary), |
| 6200 typeA); |
| 6201 errorListener.assertNoErrors(); |
| 6202 expect(scope.lookup(AstFactory.identifier3(typeNameB), importingLibrary), |
| 6203 typeB); |
| 6204 errorListener.assertNoErrors(); |
| 6205 } |
| 6206 |
| 6207 void test_prefixedAndNonPrefixed() { |
| 6208 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6209 String typeName = "C"; |
| 6210 String prefixName = "p"; |
| 6211 ClassElement prefixedType = ElementFactory.classElement2(typeName); |
| 6212 ClassElement nonPrefixedType = ElementFactory.classElement2(typeName); |
| 6213 LibraryElement prefixedLibrary = |
| 6214 createTestLibrary(context, "import.prefixed"); |
| 6215 (prefixedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6216 .types = <ClassElement>[prefixedType]; |
| 6217 ImportElementImpl prefixedImport = ElementFactory.importFor( |
| 6218 prefixedLibrary, ElementFactory.prefix(prefixName)); |
| 6219 LibraryElement nonPrefixedLibrary = |
| 6220 createTestLibrary(context, "import.nonPrefixed"); |
| 6221 (nonPrefixedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6222 .types = <ClassElement>[nonPrefixedType]; |
| 6223 ImportElementImpl nonPrefixedImport = |
| 6224 ElementFactory.importFor(nonPrefixedLibrary, null); |
| 6225 LibraryElementImpl importingLibrary = |
| 6226 createTestLibrary(context, "importing"); |
| 6227 importingLibrary.imports = <ImportElement>[ |
| 6228 prefixedImport, |
| 6229 nonPrefixedImport |
| 6230 ]; |
| 6231 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6232 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6233 Element prefixedElement = scope.lookup( |
| 6234 AstFactory.identifier5(prefixName, typeName), importingLibrary); |
| 6235 errorListener.assertNoErrors(); |
| 6236 expect(prefixedElement, same(prefixedType)); |
| 6237 Element nonPrefixedElement = |
| 6238 scope.lookup(AstFactory.identifier3(typeName), importingLibrary); |
| 6239 errorListener.assertNoErrors(); |
| 6240 expect(nonPrefixedElement, same(nonPrefixedType)); |
| 6241 } |
| 6242 } |
| 6243 |
| 6244 @reflectiveTest |
| 6245 class LibraryResolver2Test extends ResolverTestCase { |
| 6246 LibraryResolver2 _resolver; |
| 6247 |
| 6248 Source _coreLibrarySource; |
| 6249 |
| 6250 Source _asyncLibrarySource; |
| 6251 |
| 6252 @override |
| 6253 void setUp() { |
| 6254 super.setUp(); |
| 6255 _resolver = new LibraryResolver2(analysisContext2); |
| 6256 _coreLibrarySource = |
| 6257 analysisContext2.sourceFactory.forUri(DartSdk.DART_CORE); |
| 6258 _asyncLibrarySource = |
| 6259 analysisContext2.sourceFactory.forUri(DartSdk.DART_ASYNC); |
| 6260 } |
| 6261 |
| 6262 void test_imports_relative() { |
| 6263 Source sourceA = addSource(r''' |
| 6264 library libA; |
| 6265 import 'libB.dart'; |
| 6266 class A {}'''); |
| 6267 Source sourceB = addNamedSource( |
| 6268 "/libB.dart", |
| 6269 r''' |
| 6270 library libB; |
| 6271 import 'test.dart |
| 6272 class B {}'''); |
| 6273 List<ResolvableLibrary> cycle = new List<ResolvableLibrary>(); |
| 6274 ResolvableLibrary coreLib = _createResolvableLibrary(_coreLibrarySource); |
| 6275 coreLib.libraryElement = analysisContext2 |
| 6276 .computeLibraryElement(_coreLibrarySource) as LibraryElementImpl; |
| 6277 ResolvableLibrary asyncLib = _createResolvableLibrary(_asyncLibrarySource); |
| 6278 asyncLib.libraryElement = analysisContext2 |
| 6279 .computeLibraryElement(_asyncLibrarySource) as LibraryElementImpl; |
| 6280 ResolvableLibrary libA = _createResolvableLibrary(sourceA); |
| 6281 ResolvableLibrary libB = _createResolvableLibrary(sourceB); |
| 6282 libA.importedLibraries = <ResolvableLibrary>[coreLib, asyncLib, libB]; |
| 6283 libB.importedLibraries = <ResolvableLibrary>[coreLib, asyncLib, libA]; |
| 6284 cycle.add(libA); |
| 6285 cycle.add(libB); |
| 6286 LibraryElement library = _resolver.resolveLibrary(sourceA, cycle); |
| 6287 List<LibraryElement> importedLibraries = library.importedLibraries; |
| 6288 assertNamedElements(importedLibraries, ["dart.core", "libB"]); |
| 6289 } |
| 6290 |
| 6291 ResolvableLibrary _createResolvableLibrary(Source source) { |
| 6292 CompilationUnit unit = analysisContext2.parseCompilationUnit(source); |
| 6293 ResolvableLibrary resolvableLibrary = new ResolvableLibrary(source); |
| 6294 resolvableLibrary.resolvableCompilationUnits = <ResolvableCompilationUnit>[ |
| 6295 new ResolvableCompilationUnit(source, unit) |
| 6296 ]; |
| 6297 return resolvableLibrary; |
| 6298 } |
| 6299 } |
| 6300 |
| 6301 @reflectiveTest |
| 6302 class LibraryResolverTest extends ResolverTestCase { |
| 6303 LibraryResolver _resolver; |
| 6304 |
| 6305 @override |
| 6306 void setUp() { |
| 6307 super.setUp(); |
| 6308 _resolver = new LibraryResolver(analysisContext2); |
| 6309 } |
| 6310 |
| 6311 void test_imports_dart_html() { |
| 6312 Source source = addSource(r''' |
| 6313 library libA; |
| 6314 import 'dart:html'; |
| 6315 class A {}'''); |
| 6316 LibraryElement library = _resolver.resolveLibrary(source, true); |
| 6317 List<LibraryElement> importedLibraries = library.importedLibraries; |
| 6318 assertNamedElements(importedLibraries, ["dart.core", "dart.dom.html"]); |
| 6319 } |
| 6320 |
| 6321 void test_imports_none() { |
| 6322 Source source = addSource(r''' |
| 6323 library libA; |
| 6324 class A {}'''); |
| 6325 LibraryElement library = _resolver.resolveLibrary(source, true); |
| 6326 List<LibraryElement> importedLibraries = library.importedLibraries; |
| 6327 assertNamedElements(importedLibraries, ["dart.core"]); |
| 6328 } |
| 6329 |
| 6330 void test_imports_relative() { |
| 6331 addNamedSource("/libB.dart", "library libB;"); |
| 6332 Source source = addSource(r''' |
| 6333 library libA; |
| 6334 import 'libB.dart'; |
| 6335 class A {}'''); |
| 6336 LibraryElement library = _resolver.resolveLibrary(source, true); |
| 6337 List<LibraryElement> importedLibraries = library.importedLibraries; |
| 6338 assertNamedElements(importedLibraries, ["dart.core", "libB"]); |
| 6339 } |
| 6340 } |
| 6341 |
| 6342 @reflectiveTest |
| 6343 class LibraryScopeTest extends ResolverTestCase { |
| 6344 void test_creation_empty() { |
| 6345 LibraryElement definingLibrary = createDefaultTestLibrary(); |
| 6346 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6347 new LibraryScope(definingLibrary, errorListener); |
| 6348 } |
| 6349 |
| 6350 void test_creation_nonEmpty() { |
| 6351 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6352 String importedTypeName = "A"; |
| 6353 ClassElement importedType = |
| 6354 new ClassElementImpl.forNode(AstFactory.identifier3(importedTypeName)); |
| 6355 LibraryElement importedLibrary = createTestLibrary(context, "imported"); |
| 6356 (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6357 .types = <ClassElement>[importedType]; |
| 6358 LibraryElementImpl definingLibrary = |
| 6359 createTestLibrary(context, "importing"); |
| 6360 ImportElementImpl importElement = new ImportElementImpl(0); |
| 6361 importElement.importedLibrary = importedLibrary; |
| 6362 definingLibrary.imports = <ImportElement>[importElement]; |
| 6363 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6364 Scope scope = new LibraryScope(definingLibrary, errorListener); |
| 6365 expect( |
| 6366 scope.lookup(AstFactory.identifier3(importedTypeName), definingLibrary), |
| 6367 importedType); |
| 6368 } |
| 6369 |
| 6370 void test_getErrorListener() { |
| 6371 LibraryElement definingLibrary = createDefaultTestLibrary(); |
| 6372 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6373 LibraryScope scope = new LibraryScope(definingLibrary, errorListener); |
| 6374 expect(scope.errorListener, errorListener); |
| 6375 } |
| 6376 } |
| 6377 |
| 6378 @reflectiveTest |
| 6379 class LibraryTest extends EngineTestCase { |
| 6380 /** |
| 6381 * The error listener to which all errors will be reported. |
| 6382 */ |
| 6383 GatheringErrorListener _errorListener; |
| 6384 |
| 6385 /** |
| 6386 * The analysis context to pass in to all libraries created by the tests. |
| 6387 */ |
| 6388 InternalAnalysisContext _analysisContext; |
| 6389 |
| 6390 /** |
| 6391 * The library used by the tests. |
| 6392 */ |
| 6393 Library _library; |
| 6394 |
| 6395 @override |
| 6396 void setUp() { |
| 6397 _analysisContext = AnalysisContextFactory.contextWithCore(); |
| 6398 _errorListener = new GatheringErrorListener(); |
| 6399 _library = _createLibrary("/lib.dart"); |
| 6400 } |
| 6401 |
| 6402 @override |
| 6403 void tearDown() { |
| 6404 _errorListener = null; |
| 6405 _analysisContext = null; |
| 6406 _library = null; |
| 6407 super.tearDown(); |
| 6408 } |
| 6409 |
| 6410 void test_getExplicitlyImportsCore() { |
| 6411 expect(_library.explicitlyImportsCore, isFalse); |
| 6412 _errorListener.assertNoErrors(); |
| 6413 } |
| 6414 |
| 6415 void test_getExports() { |
| 6416 expect(_library.exports, hasLength(0)); |
| 6417 _errorListener.assertNoErrors(); |
| 6418 } |
| 6419 |
| 6420 void test_getImports() { |
| 6421 expect(_library.imports, hasLength(0)); |
| 6422 _errorListener.assertNoErrors(); |
| 6423 } |
| 6424 |
| 6425 void test_getImportsAndExports() { |
| 6426 _library.importedLibraries = <Library>[_createLibrary("/imported.dart")]; |
| 6427 _library.exportedLibraries = <Library>[_createLibrary("/exported.dart")]; |
| 6428 expect(_library.importsAndExports, hasLength(2)); |
| 6429 _errorListener.assertNoErrors(); |
| 6430 } |
| 6431 |
| 6432 void test_getLibraryScope() { |
| 6433 LibraryElementImpl element = new LibraryElementImpl.forNode( |
| 6434 _analysisContext, AstFactory.libraryIdentifier2(["lib"])); |
| 6435 element.definingCompilationUnit = |
| 6436 new CompilationUnitElementImpl("lib.dart"); |
| 6437 _library.libraryElement = element; |
| 6438 expect(_library.libraryScope, isNotNull); |
| 6439 _errorListener.assertNoErrors(); |
| 6440 } |
| 6441 |
| 6442 void test_getLibrarySource() { |
| 6443 expect(_library.librarySource, isNotNull); |
| 6444 } |
| 6445 |
| 6446 void test_setExplicitlyImportsCore() { |
| 6447 _library.explicitlyImportsCore = true; |
| 6448 expect(_library.explicitlyImportsCore, isTrue); |
| 6449 _errorListener.assertNoErrors(); |
| 6450 } |
| 6451 |
| 6452 void test_setExportedLibraries() { |
| 6453 Library exportLibrary = _createLibrary("/exported.dart"); |
| 6454 _library.exportedLibraries = <Library>[exportLibrary]; |
| 6455 List<Library> exports = _library.exports; |
| 6456 expect(exports, hasLength(1)); |
| 6457 expect(exports[0], same(exportLibrary)); |
| 6458 _errorListener.assertNoErrors(); |
| 6459 } |
| 6460 |
| 6461 void test_setImportedLibraries() { |
| 6462 Library importLibrary = _createLibrary("/imported.dart"); |
| 6463 _library.importedLibraries = <Library>[importLibrary]; |
| 6464 List<Library> imports = _library.imports; |
| 6465 expect(imports, hasLength(1)); |
| 6466 expect(imports[0], same(importLibrary)); |
| 6467 _errorListener.assertNoErrors(); |
| 6468 } |
| 6469 |
| 6470 void test_setLibraryElement() { |
| 6471 LibraryElementImpl element = new LibraryElementImpl.forNode( |
| 6472 _analysisContext, AstFactory.libraryIdentifier2(["lib"])); |
| 6473 _library.libraryElement = element; |
| 6474 expect(_library.libraryElement, same(element)); |
| 6475 } |
| 6476 |
| 6477 Library _createLibrary(String definingCompilationUnitPath) => new Library( |
| 6478 _analysisContext, |
| 6479 _errorListener, |
| 6480 new FileBasedSource( |
| 6481 FileUtilities2.createFile(definingCompilationUnitPath))); |
| 6482 } |
| 6483 |
| 6484 @reflectiveTest |
| 6485 class MemberMapTest { |
| 6486 /** |
| 6487 * The null type. |
| 6488 */ |
| 6489 InterfaceType _nullType; |
| 6490 |
| 6491 void setUp() { |
| 6492 _nullType = new TestTypeProvider().nullType; |
| 6493 } |
| 6494 |
| 6495 void test_MemberMap_copyConstructor() { |
| 6496 MethodElement m1 = ElementFactory.methodElement("m1", _nullType); |
| 6497 MethodElement m2 = ElementFactory.methodElement("m2", _nullType); |
| 6498 MethodElement m3 = ElementFactory.methodElement("m3", _nullType); |
| 6499 MemberMap map = new MemberMap(); |
| 6500 map.put(m1.name, m1); |
| 6501 map.put(m2.name, m2); |
| 6502 map.put(m3.name, m3); |
| 6503 MemberMap copy = new MemberMap.from(map); |
| 6504 expect(copy.size, map.size); |
| 6505 expect(copy.get(m1.name), m1); |
| 6506 expect(copy.get(m2.name), m2); |
| 6507 expect(copy.get(m3.name), m3); |
| 6508 } |
| 6509 |
| 6510 void test_MemberMap_override() { |
| 6511 MethodElement m1 = ElementFactory.methodElement("m", _nullType); |
| 6512 MethodElement m2 = ElementFactory.methodElement("m", _nullType); |
| 6513 MemberMap map = new MemberMap(); |
| 6514 map.put(m1.name, m1); |
| 6515 map.put(m2.name, m2); |
| 6516 expect(map.size, 1); |
| 6517 expect(map.get("m"), m2); |
| 6518 } |
| 6519 |
| 6520 void test_MemberMap_put() { |
| 6521 MethodElement m1 = ElementFactory.methodElement("m1", _nullType); |
| 6522 MemberMap map = new MemberMap(); |
| 6523 expect(map.size, 0); |
| 6524 map.put(m1.name, m1); |
| 6525 expect(map.size, 1); |
| 6526 expect(map.get("m1"), m1); |
| 6527 } |
| 6528 } |
| 6529 |
| 6530 /** |
| 6531 * An analysis context that has a fake SDK that is much smaller and faster for |
| 6532 * testing purposes. |
| 6533 */ |
| 6534 class NewAnalysisContextForTests extends newContext.AnalysisContextImpl { |
| 6535 @override |
| 6536 void set analysisOptions(AnalysisOptions options) { |
| 6537 AnalysisOptions currentOptions = analysisOptions; |
| 6538 bool needsRecompute = currentOptions.analyzeFunctionBodiesPredicate != |
| 6539 options.analyzeFunctionBodiesPredicate || |
| 6540 currentOptions.generateImplicitErrors != |
| 6541 options.generateImplicitErrors || |
| 6542 currentOptions.generateSdkErrors != options.generateSdkErrors || |
| 6543 currentOptions.dart2jsHint != options.dart2jsHint || |
| 6544 (currentOptions.hint && !options.hint) || |
| 6545 currentOptions.preserveComments != options.preserveComments || |
| 6546 currentOptions.enableStrictCallChecks != options.enableStrictCallChecks; |
| 6547 if (needsRecompute) { |
| 6548 fail( |
| 6549 "Cannot set options that cause the sources to be reanalyzed in a test
context"); |
| 6550 } |
| 6551 super.analysisOptions = options; |
| 6552 } |
| 6553 |
| 6554 @override |
| 6555 bool exists(Source source) => |
| 6556 super.exists(source) || sourceFactory.dartSdk.context.exists(source); |
| 6557 |
| 6558 @override |
| 6559 TimestampedData<String> getContents(Source source) { |
| 6560 if (source.isInSystemLibrary) { |
| 6561 return sourceFactory.dartSdk.context.getContents(source); |
| 6562 } |
| 6563 return super.getContents(source); |
| 6564 } |
| 6565 |
| 6566 @override |
| 6567 int getModificationStamp(Source source) { |
| 6568 if (source.isInSystemLibrary) { |
| 6569 return sourceFactory.dartSdk.context.getModificationStamp(source); |
| 6570 } |
| 6571 return super.getModificationStamp(source); |
| 6572 } |
| 6573 |
| 6574 /** |
| 6575 * Set the analysis options, even if they would force re-analysis. This method
should only be |
| 6576 * invoked before the fake SDK is initialized. |
| 6577 * |
| 6578 * @param options the analysis options to be set |
| 6579 */ |
| 6580 void _internalSetAnalysisOptions(AnalysisOptions options) { |
| 6581 super.analysisOptions = options; |
| 6582 } |
| 6583 } |
| 6584 |
| 6585 @reflectiveTest |
| 6586 class NonHintCodeTest extends ResolverTestCase { |
| 6587 void test_deadCode_deadBlock_conditionalElse_debugConst() { |
| 6588 Source source = addSource(r''' |
| 6589 const bool DEBUG = true; |
| 6590 f() { |
| 6591 DEBUG ? 1 : 2; |
| 6592 }'''); |
| 6593 computeLibrarySourceErrors(source); |
| 6594 assertNoErrors(source); |
| 6595 verify([source]); |
| 6596 } |
| 6597 |
| 6598 void test_deadCode_deadBlock_conditionalIf_debugConst() { |
| 6599 Source source = addSource(r''' |
| 6600 const bool DEBUG = false; |
| 6601 f() { |
| 6602 DEBUG ? 1 : 2; |
| 6603 }'''); |
| 6604 computeLibrarySourceErrors(source); |
| 6605 assertNoErrors(source); |
| 6606 verify([source]); |
| 6607 } |
| 6608 |
| 6609 void test_deadCode_deadBlock_else() { |
| 6610 Source source = addSource(r''' |
| 6611 const bool DEBUG = true; |
| 6612 f() { |
| 6613 if(DEBUG) {} else {} |
| 6614 }'''); |
| 6615 computeLibrarySourceErrors(source); |
| 6616 assertNoErrors(source); |
| 6617 verify([source]); |
| 6618 } |
| 6619 |
| 6620 void test_deadCode_deadBlock_if_debugConst_prefixedIdentifier() { |
| 6621 Source source = addSource(r''' |
| 6622 class A { |
| 6623 static const bool DEBUG = false; |
| 6624 } |
| 6625 f() { |
| 6626 if(A.DEBUG) {} |
| 6627 }'''); |
| 6628 computeLibrarySourceErrors(source); |
| 6629 assertNoErrors(source); |
| 6630 verify([source]); |
| 6631 } |
| 6632 |
| 6633 void test_deadCode_deadBlock_if_debugConst_prefixedIdentifier2() { |
| 6634 Source source = addSource(r''' |
| 6635 library L; |
| 6636 import 'lib2.dart'; |
| 6637 f() { |
| 6638 if(A.DEBUG) {} |
| 6639 }'''); |
| 6640 addNamedSource( |
| 6641 "/lib2.dart", |
| 6642 r''' |
| 6643 library lib2; |
| 6644 class A { |
| 6645 static const bool DEBUG = false; |
| 6646 }'''); |
| 6647 computeLibrarySourceErrors(source); |
| 6648 assertNoErrors(source); |
| 6649 verify([source]); |
| 6650 } |
| 6651 |
| 6652 void test_deadCode_deadBlock_if_debugConst_propertyAccessor() { |
| 6653 Source source = addSource(r''' |
| 6654 library L; |
| 6655 import 'lib2.dart' as LIB; |
| 6656 f() { |
| 6657 if(LIB.A.DEBUG) {} |
| 6658 }'''); |
| 6659 addNamedSource( |
| 6660 "/lib2.dart", |
| 6661 r''' |
| 6662 library lib2; |
| 6663 class A { |
| 6664 static const bool DEBUG = false; |
| 6665 }'''); |
| 6666 computeLibrarySourceErrors(source); |
| 6667 assertNoErrors(source); |
| 6668 verify([source]); |
| 6669 } |
| 6670 |
| 6671 void test_deadCode_deadBlock_if_debugConst_simpleIdentifier() { |
| 6672 Source source = addSource(r''' |
| 6673 const bool DEBUG = false; |
| 6674 f() { |
| 6675 if(DEBUG) {} |
| 6676 }'''); |
| 6677 computeLibrarySourceErrors(source); |
| 6678 assertNoErrors(source); |
| 6679 verify([source]); |
| 6680 } |
| 6681 |
| 6682 void test_deadCode_deadBlock_while_debugConst() { |
| 6683 Source source = addSource(r''' |
| 6684 const bool DEBUG = false; |
| 6685 f() { |
| 6686 while(DEBUG) {} |
| 6687 }'''); |
| 6688 computeLibrarySourceErrors(source); |
| 6689 assertNoErrors(source); |
| 6690 verify([source]); |
| 6691 } |
| 6692 |
| 6693 void test_deadCode_deadCatch_onCatchSubtype() { |
| 6694 Source source = addSource(r''' |
| 6695 class A {} |
| 6696 class B extends A {} |
| 6697 f() { |
| 6698 try {} on B catch (e) {} on A catch (e) {} catch (e) {} |
| 6699 }'''); |
| 6700 computeLibrarySourceErrors(source); |
| 6701 assertNoErrors(source); |
| 6702 verify([source]); |
| 6703 } |
| 6704 |
| 6705 void test_deadCode_deadOperandLHS_and_debugConst() { |
| 6706 Source source = addSource(r''' |
| 6707 const bool DEBUG = false; |
| 6708 f() { |
| 6709 bool b = DEBUG && false; |
| 6710 }'''); |
| 6711 computeLibrarySourceErrors(source); |
| 6712 assertNoErrors(source); |
| 6713 verify([source]); |
| 6714 } |
| 6715 |
| 6716 void test_deadCode_deadOperandLHS_or_debugConst() { |
| 6717 Source source = addSource(r''' |
| 6718 const bool DEBUG = true; |
| 6719 f() { |
| 6720 bool b = DEBUG || true; |
| 6721 }'''); |
| 6722 computeLibrarySourceErrors(source); |
| 6723 assertNoErrors(source); |
| 6724 verify([source]); |
| 6725 } |
| 6726 |
| 6727 void test_divisionOptimization() { |
| 6728 Source source = addSource(r''' |
| 6729 f(int x, int y) { |
| 6730 var v = x / y.toInt(); |
| 6731 }'''); |
| 6732 computeLibrarySourceErrors(source); |
| 6733 assertNoErrors(source); |
| 6734 verify([source]); |
| 6735 } |
| 6736 |
| 6737 void test_divisionOptimization_supressIfDivisionNotDefinedInCore() { |
| 6738 Source source = addSource(r''' |
| 6739 f(x, y) { |
| 6740 var v = (x / y).toInt(); |
| 6741 }'''); |
| 6742 computeLibrarySourceErrors(source); |
| 6743 assertNoErrors(source); |
| 6744 verify([source]); |
| 6745 } |
| 6746 |
| 6747 void test_divisionOptimization_supressIfDivisionOverridden() { |
| 6748 Source source = addSource(r''' |
| 6749 class A { |
| 6750 num operator /(x) { return x; } |
| 6751 } |
| 6752 f(A x, A y) { |
| 6753 var v = (x / y).toInt(); |
| 6754 }'''); |
| 6755 computeLibrarySourceErrors(source); |
| 6756 assertNoErrors(source); |
| 6757 verify([source]); |
| 6758 } |
| 6759 |
| 6760 void test_duplicateImport_as() { |
| 6761 Source source = addSource(r''' |
| 6762 library L; |
| 6763 import 'lib1.dart'; |
| 6764 import 'lib1.dart' as one; |
| 6765 A a; |
| 6766 one.A a2;'''); |
| 6767 addNamedSource( |
| 6768 "/lib1.dart", |
| 6769 r''' |
| 6770 library lib1; |
| 6771 class A {}'''); |
| 6772 computeLibrarySourceErrors(source); |
| 6773 assertNoErrors(source); |
| 6774 verify([source]); |
| 6775 } |
| 6776 |
| 6777 void test_duplicateImport_hide() { |
| 6778 Source source = addSource(r''' |
| 6779 library L; |
| 6780 import 'lib1.dart'; |
| 6781 import 'lib1.dart' hide A; |
| 6782 A a; |
| 6783 B b;'''); |
| 6784 addNamedSource( |
| 6785 "/lib1.dart", |
| 6786 r''' |
| 6787 library lib1; |
| 6788 class A {} |
| 6789 class B {}'''); |
| 6790 computeLibrarySourceErrors(source); |
| 6791 assertNoErrors(source); |
| 6792 verify([source]); |
| 6793 } |
| 6794 |
| 6795 void test_duplicateImport_show() { |
| 6796 Source source = addSource(r''' |
| 6797 library L; |
| 6798 import 'lib1.dart'; |
| 6799 import 'lib1.dart' show A; |
| 6800 A a; |
| 6801 B b;'''); |
| 6802 addNamedSource( |
| 6803 "/lib1.dart", |
| 6804 r''' |
| 6805 library lib1; |
| 6806 class A {} |
| 6807 class B {}'''); |
| 6808 computeLibrarySourceErrors(source); |
| 6809 assertNoErrors(source); |
| 6810 verify([source]); |
| 6811 } |
| 6812 |
| 6813 void test_importDeferredLibraryWithLoadFunction() { |
| 6814 resolveWithErrors(<String>[ |
| 6815 r''' |
| 6816 library lib1; |
| 6817 f() {}''', |
| 6818 r''' |
| 6819 library root; |
| 6820 import 'lib1.dart' deferred as lib1; |
| 6821 main() { lib1.f(); }''' |
| 6822 ], ErrorCode.EMPTY_LIST); |
| 6823 } |
| 6824 |
| 6825 void test_issue20904BuggyTypePromotionAtIfJoin_1() { |
| 6826 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 6827 Source source = addSource(r''' |
| 6828 f(var message, var dynamic_) { |
| 6829 if (message is Function) { |
| 6830 message = dynamic_; |
| 6831 } |
| 6832 int s = message; |
| 6833 }'''); |
| 6834 computeLibrarySourceErrors(source); |
| 6835 assertNoErrors(source); |
| 6836 verify([source]); |
| 6837 } |
| 6838 |
| 6839 void test_issue20904BuggyTypePromotionAtIfJoin_3() { |
| 6840 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 6841 Source source = addSource(r''' |
| 6842 f(var message) { |
| 6843 var dynamic_; |
| 6844 if (message is Function) { |
| 6845 message = dynamic_; |
| 6846 } else { |
| 6847 return; |
| 6848 } |
| 6849 int s = message; |
| 6850 }'''); |
| 6851 computeLibrarySourceErrors(source); |
| 6852 assertNoErrors(source); |
| 6853 verify([source]); |
| 6854 } |
| 6855 |
| 6856 void test_issue20904BuggyTypePromotionAtIfJoin_4() { |
| 6857 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 6858 Source source = addSource(r''' |
| 6859 f(var message) { |
| 6860 if (message is Function) { |
| 6861 message = ''; |
| 6862 } else { |
| 6863 return; |
| 6864 } |
| 6865 String s = message; |
| 6866 }'''); |
| 6867 computeLibrarySourceErrors(source); |
| 6868 assertNoErrors(source); |
| 6869 verify([source]); |
| 6870 } |
| 6871 |
| 6872 void test_missingReturn_emptyFunctionBody() { |
| 6873 Source source = addSource(r''' |
| 6874 abstract class A { |
| 6875 int m(); |
| 6876 }'''); |
| 6877 computeLibrarySourceErrors(source); |
| 6878 assertNoErrors(source); |
| 6879 verify([source]); |
| 6880 } |
| 6881 |
| 6882 void test_missingReturn_expressionFunctionBody() { |
| 6883 Source source = addSource("int f() => 0;"); |
| 6884 computeLibrarySourceErrors(source); |
| 6885 assertNoErrors(source); |
| 6886 verify([source]); |
| 6887 } |
| 6888 |
| 6889 void test_missingReturn_noReturnType() { |
| 6890 Source source = addSource("f() {}"); |
| 6891 computeLibrarySourceErrors(source); |
| 6892 assertNoErrors(source); |
| 6893 verify([source]); |
| 6894 } |
| 6895 |
| 6896 void test_missingReturn_voidReturnType() { |
| 6897 Source source = addSource("void f() {}"); |
| 6898 computeLibrarySourceErrors(source); |
| 6899 assertNoErrors(source); |
| 6900 verify([source]); |
| 6901 } |
| 6902 |
| 6903 void test_overrideEqualsButNotHashCode() { |
| 6904 Source source = addSource(r''' |
| 6905 class A { |
| 6906 bool operator ==(x) { return x; } |
| 6907 get hashCode => 0; |
| 6908 }'''); |
| 6909 computeLibrarySourceErrors(source); |
| 6910 assertNoErrors(source); |
| 6911 verify([source]); |
| 6912 } |
| 6913 |
| 6914 void test_overrideOnNonOverridingGetter_inInterface() { |
| 6915 Source source = addSource(r''' |
| 6916 library dart.core; |
| 6917 const override = null; |
| 6918 class A { |
| 6919 int get m => 0; |
| 6920 } |
| 6921 class B implements A { |
| 6922 @override |
| 6923 int get m => 1; |
| 6924 }'''); |
| 6925 computeLibrarySourceErrors(source); |
| 6926 assertNoErrors(source); |
| 6927 verify([source]); |
| 6928 } |
| 6929 |
| 6930 void test_overrideOnNonOverridingGetter_inSuperclass() { |
| 6931 Source source = addSource(r''' |
| 6932 library dart.core; |
| 6933 const override = null; |
| 6934 class A { |
| 6935 int get m => 0; |
| 6936 } |
| 6937 class B extends A { |
| 6938 @override |
| 6939 int get m => 1; |
| 6940 }'''); |
| 6941 computeLibrarySourceErrors(source); |
| 6942 assertNoErrors(source); |
| 6943 verify([source]); |
| 6944 } |
| 6945 |
| 6946 void test_overrideOnNonOverridingMethod_inInterface() { |
| 6947 Source source = addSource(r''' |
| 6948 library dart.core; |
| 6949 const override = null; |
| 6950 class A { |
| 6951 int m() => 0; |
| 6952 } |
| 6953 class B implements A { |
| 6954 @override |
| 6955 int m() => 1; |
| 6956 }'''); |
| 6957 computeLibrarySourceErrors(source); |
| 6958 assertNoErrors(source); |
| 6959 verify([source]); |
| 6960 } |
| 6961 |
| 6962 void test_overrideOnNonOverridingMethod_inSuperclass() { |
| 6963 Source source = addSource(r''' |
| 6964 library dart.core; |
| 6965 const override = null; |
| 6966 class A { |
| 6967 int m() => 0; |
| 6968 } |
| 6969 class B extends A { |
| 6970 @override |
| 6971 int m() => 1; |
| 6972 }'''); |
| 6973 computeLibrarySourceErrors(source); |
| 6974 assertNoErrors(source); |
| 6975 verify([source]); |
| 6976 } |
| 6977 |
| 6978 void test_overrideOnNonOverridingSetter_inInterface() { |
| 6979 Source source = addSource(r''' |
| 6980 library dart.core; |
| 6981 const override = null; |
| 6982 class A { |
| 6983 set m(int x) {} |
| 6984 } |
| 6985 class B implements A { |
| 6986 @override |
| 6987 set m(int x) {} |
| 6988 }'''); |
| 6989 computeLibrarySourceErrors(source); |
| 6990 assertNoErrors(source); |
| 6991 verify([source]); |
| 6992 } |
| 6993 |
| 6994 void test_overrideOnNonOverridingSetter_inSuperclass() { |
| 6995 Source source = addSource(r''' |
| 6996 library dart.core; |
| 6997 const override = null; |
| 6998 class A { |
| 6999 set m(int x) {} |
| 7000 } |
| 7001 class B extends A { |
| 7002 @override |
| 7003 set m(int x) {} |
| 7004 }'''); |
| 7005 computeLibrarySourceErrors(source); |
| 7006 assertNoErrors(source); |
| 7007 verify([source]); |
| 7008 } |
| 7009 |
| 7010 void test_propagatedFieldType() { |
| 7011 Source source = addSource(r''' |
| 7012 class A { } |
| 7013 class X<T> { |
| 7014 final x = new List<T>(); |
| 7015 } |
| 7016 class Z { |
| 7017 final X<A> y = new X<A>(); |
| 7018 foo() { |
| 7019 y.x.add(new A()); |
| 7020 } |
| 7021 }'''); |
| 7022 computeLibrarySourceErrors(source); |
| 7023 assertNoErrors(source); |
| 7024 verify([source]); |
| 7025 } |
| 7026 |
| 7027 void test_proxy_annotation_prefixed() { |
| 7028 Source source = addSource(r''' |
| 7029 library L; |
| 7030 @proxy |
| 7031 class A {} |
| 7032 f(var a) { |
| 7033 a = new A(); |
| 7034 a.m(); |
| 7035 var x = a.g; |
| 7036 a.s = 1; |
| 7037 var y = a + a; |
| 7038 a++; |
| 7039 ++a; |
| 7040 }'''); |
| 7041 computeLibrarySourceErrors(source); |
| 7042 assertNoErrors(source); |
| 7043 } |
| 7044 |
| 7045 void test_proxy_annotation_prefixed2() { |
| 7046 Source source = addSource(r''' |
| 7047 library L; |
| 7048 @proxy |
| 7049 class A {} |
| 7050 class B { |
| 7051 f(var a) { |
| 7052 a = new A(); |
| 7053 a.m(); |
| 7054 var x = a.g; |
| 7055 a.s = 1; |
| 7056 var y = a + a; |
| 7057 a++; |
| 7058 ++a; |
| 7059 } |
| 7060 }'''); |
| 7061 computeLibrarySourceErrors(source); |
| 7062 assertNoErrors(source); |
| 7063 } |
| 7064 |
| 7065 void test_proxy_annotation_prefixed3() { |
| 7066 Source source = addSource(r''' |
| 7067 library L; |
| 7068 class B { |
| 7069 f(var a) { |
| 7070 a = new A(); |
| 7071 a.m(); |
| 7072 var x = a.g; |
| 7073 a.s = 1; |
| 7074 var y = a + a; |
| 7075 a++; |
| 7076 ++a; |
| 7077 } |
| 7078 } |
| 7079 @proxy |
| 7080 class A {}'''); |
| 7081 computeLibrarySourceErrors(source); |
| 7082 assertNoErrors(source); |
| 7083 } |
| 7084 |
| 7085 void test_undefinedGetter_inSubtype() { |
| 7086 Source source = addSource(r''' |
| 7087 class A {} |
| 7088 class B extends A { |
| 7089 get b => 0; |
| 7090 } |
| 7091 f(var a) { |
| 7092 if(a is A) { |
| 7093 return a.b; |
| 7094 } |
| 7095 }'''); |
| 7096 computeLibrarySourceErrors(source); |
| 7097 assertNoErrors(source); |
| 7098 } |
| 7099 |
| 7100 void test_undefinedMethod_assignmentExpression_inSubtype() { |
| 7101 Source source = addSource(r''' |
| 7102 class A {} |
| 7103 class B extends A { |
| 7104 operator +(B b) {return new B();} |
| 7105 } |
| 7106 f(var a, var a2) { |
| 7107 a = new A(); |
| 7108 a2 = new A(); |
| 7109 a += a2; |
| 7110 }'''); |
| 7111 computeLibrarySourceErrors(source); |
| 7112 assertNoErrors(source); |
| 7113 } |
| 7114 |
| 7115 void test_undefinedMethod_dynamic() { |
| 7116 Source source = addSource(r''' |
| 7117 class D<T extends dynamic> { |
| 7118 fieldAccess(T t) => t.abc; |
| 7119 methodAccess(T t) => t.xyz(1, 2, 'three'); |
| 7120 }'''); |
| 7121 computeLibrarySourceErrors(source); |
| 7122 assertNoErrors(source); |
| 7123 } |
| 7124 |
| 7125 void test_undefinedMethod_inSubtype() { |
| 7126 Source source = addSource(r''' |
| 7127 class A {} |
| 7128 class B extends A { |
| 7129 b() {} |
| 7130 } |
| 7131 f() { |
| 7132 var a = new A(); |
| 7133 a.b(); |
| 7134 }'''); |
| 7135 computeLibrarySourceErrors(source); |
| 7136 assertNoErrors(source); |
| 7137 } |
| 7138 |
| 7139 void test_undefinedMethod_unionType_all() { |
| 7140 Source source = addSource(r''' |
| 7141 class A { |
| 7142 int m(int x) => 0; |
| 7143 } |
| 7144 class B { |
| 7145 String m() => '0'; |
| 7146 } |
| 7147 f(A a, B b) { |
| 7148 var ab; |
| 7149 if (0 < 1) { |
| 7150 ab = a; |
| 7151 } else { |
| 7152 ab = b; |
| 7153 } |
| 7154 ab.m(); |
| 7155 }'''); |
| 7156 computeLibrarySourceErrors(source); |
| 7157 assertNoErrors(source); |
| 7158 } |
| 7159 |
| 7160 void test_undefinedMethod_unionType_some() { |
| 7161 Source source = addSource(r''' |
| 7162 class A { |
| 7163 int m(int x) => 0; |
| 7164 } |
| 7165 class B {} |
| 7166 f(A a, B b) { |
| 7167 var ab; |
| 7168 if (0 < 1) { |
| 7169 ab = a; |
| 7170 } else { |
| 7171 ab = b; |
| 7172 } |
| 7173 ab.m(0); |
| 7174 }'''); |
| 7175 computeLibrarySourceErrors(source); |
| 7176 assertNoErrors(source); |
| 7177 } |
| 7178 |
| 7179 void test_undefinedOperator_binaryExpression_inSubtype() { |
| 7180 Source source = addSource(r''' |
| 7181 class A {} |
| 7182 class B extends A { |
| 7183 operator +(B b) {} |
| 7184 } |
| 7185 f(var a) { |
| 7186 if(a is A) { |
| 7187 a + 1; |
| 7188 } |
| 7189 }'''); |
| 7190 computeLibrarySourceErrors(source); |
| 7191 assertNoErrors(source); |
| 7192 } |
| 7193 |
| 7194 void test_undefinedOperator_indexBoth_inSubtype() { |
| 7195 Source source = addSource(r''' |
| 7196 class A {} |
| 7197 class B extends A { |
| 7198 operator [](int index) {} |
| 7199 } |
| 7200 f(var a) { |
| 7201 if(a is A) { |
| 7202 a[0]++; |
| 7203 } |
| 7204 }'''); |
| 7205 computeLibrarySourceErrors(source); |
| 7206 assertNoErrors(source); |
| 7207 } |
| 7208 |
| 7209 void test_undefinedOperator_indexGetter_inSubtype() { |
| 7210 Source source = addSource(r''' |
| 7211 class A {} |
| 7212 class B extends A { |
| 7213 operator [](int index) {} |
| 7214 } |
| 7215 f(var a) { |
| 7216 if(a is A) { |
| 7217 a[0]; |
| 7218 } |
| 7219 }'''); |
| 7220 computeLibrarySourceErrors(source); |
| 7221 assertNoErrors(source); |
| 7222 } |
| 7223 |
| 7224 void test_undefinedOperator_indexSetter_inSubtype() { |
| 7225 Source source = addSource(r''' |
| 7226 class A {} |
| 7227 class B extends A { |
| 7228 operator []=(i, v) {} |
| 7229 } |
| 7230 f(var a) { |
| 7231 if(a is A) { |
| 7232 a[0] = 1; |
| 7233 } |
| 7234 }'''); |
| 7235 computeLibrarySourceErrors(source); |
| 7236 assertNoErrors(source); |
| 7237 } |
| 7238 |
| 7239 void test_undefinedOperator_postfixExpression() { |
| 7240 Source source = addSource(r''' |
| 7241 class A {} |
| 7242 class B extends A { |
| 7243 operator +(B b) {return new B();} |
| 7244 } |
| 7245 f(var a) { |
| 7246 if(a is A) { |
| 7247 a++; |
| 7248 } |
| 7249 }'''); |
| 7250 computeLibrarySourceErrors(source); |
| 7251 assertNoErrors(source); |
| 7252 } |
| 7253 |
| 7254 void test_undefinedOperator_prefixExpression() { |
| 7255 Source source = addSource(r''' |
| 7256 class A {} |
| 7257 class B extends A { |
| 7258 operator +(B b) {return new B();} |
| 7259 } |
| 7260 f(var a) { |
| 7261 if(a is A) { |
| 7262 ++a; |
| 7263 } |
| 7264 }'''); |
| 7265 computeLibrarySourceErrors(source); |
| 7266 assertNoErrors(source); |
| 7267 } |
| 7268 |
| 7269 void test_undefinedSetter_inSubtype() { |
| 7270 Source source = addSource(r''' |
| 7271 class A {} |
| 7272 class B extends A { |
| 7273 set b(x) {} |
| 7274 } |
| 7275 f(var a) { |
| 7276 if(a is A) { |
| 7277 a.b = 0; |
| 7278 } |
| 7279 }'''); |
| 7280 computeLibrarySourceErrors(source); |
| 7281 assertNoErrors(source); |
| 7282 } |
| 7283 |
| 7284 void test_unnecessaryCast_13855_parameter_A() { |
| 7285 // dartbug.com/13855, dartbug.com/13732 |
| 7286 Source source = addSource(r''' |
| 7287 class A{ |
| 7288 a() {} |
| 7289 } |
| 7290 class B<E> { |
| 7291 E e; |
| 7292 m() { |
| 7293 (e as A).a(); |
| 7294 } |
| 7295 }'''); |
| 7296 computeLibrarySourceErrors(source); |
| 7297 assertNoErrors(source); |
| 7298 verify([source]); |
| 7299 } |
| 7300 |
| 7301 void test_unnecessaryCast_conditionalExpression() { |
| 7302 Source source = addSource(r''' |
| 7303 abstract class I {} |
| 7304 class A implements I {} |
| 7305 class B implements I {} |
| 7306 I m(A a, B b) { |
| 7307 return a == null ? b as I : a as I; |
| 7308 }'''); |
| 7309 computeLibrarySourceErrors(source); |
| 7310 assertNoErrors(source); |
| 7311 verify([source]); |
| 7312 } |
| 7313 |
| 7314 void test_unnecessaryCast_dynamic_type() { |
| 7315 Source source = addSource(r''' |
| 7316 m(v) { |
| 7317 var b = v as Object; |
| 7318 }'''); |
| 7319 computeLibrarySourceErrors(source); |
| 7320 assertNoErrors(source); |
| 7321 verify([source]); |
| 7322 } |
| 7323 |
| 7324 void test_unnecessaryCast_generics() { |
| 7325 // dartbug.com/18953 |
| 7326 Source source = addSource(r''' |
| 7327 import 'dart:async'; |
| 7328 Future<int> f() => new Future.value(0); |
| 7329 void g(bool c) { |
| 7330 (c ? f(): new Future.value(0) as Future<int>).then((int value) {}); |
| 7331 }'''); |
| 7332 computeLibrarySourceErrors(source); |
| 7333 assertNoErrors(source); |
| 7334 verify([source]); |
| 7335 } |
| 7336 |
| 7337 void test_unnecessaryCast_type_dynamic() { |
| 7338 Source source = addSource(r''' |
| 7339 m(v) { |
| 7340 var b = Object as dynamic; |
| 7341 }'''); |
| 7342 computeLibrarySourceErrors(source); |
| 7343 assertNoErrors(source); |
| 7344 verify([source]); |
| 7345 } |
| 7346 |
| 7347 void test_unusedImport_annotationOnDirective() { |
| 7348 Source source = addSource(r''' |
| 7349 library L; |
| 7350 @A() |
| 7351 import 'lib1.dart';'''); |
| 7352 Source source2 = addNamedSource( |
| 7353 "/lib1.dart", |
| 7354 r''' |
| 7355 library lib1; |
| 7356 class A { |
| 7357 const A() {} |
| 7358 }'''); |
| 7359 computeLibrarySourceErrors(source); |
| 7360 assertErrors(source); |
| 7361 verify([source, source2]); |
| 7362 } |
| 7363 |
| 7364 void test_unusedImport_as_equalPrefixes() { |
| 7365 // 18818 |
| 7366 Source source = addSource(r''' |
| 7367 library L; |
| 7368 import 'lib1.dart' as one; |
| 7369 import 'lib2.dart' as one; |
| 7370 one.A a; |
| 7371 one.B b;'''); |
| 7372 Source source2 = addNamedSource( |
| 7373 "/lib1.dart", |
| 7374 r''' |
| 7375 library lib1; |
| 7376 class A {}'''); |
| 7377 Source source3 = addNamedSource( |
| 7378 "/lib2.dart", |
| 7379 r''' |
| 7380 library lib2; |
| 7381 class B {}'''); |
| 7382 computeLibrarySourceErrors(source); |
| 7383 assertErrors(source); |
| 7384 assertNoErrors(source2); |
| 7385 assertNoErrors(source3); |
| 7386 verify([source, source2, source3]); |
| 7387 } |
| 7388 |
| 7389 void test_unusedImport_core_library() { |
| 7390 Source source = addSource(r''' |
| 7391 library L; |
| 7392 import 'dart:core';'''); |
| 7393 computeLibrarySourceErrors(source); |
| 7394 assertNoErrors(source); |
| 7395 verify([source]); |
| 7396 } |
| 7397 |
| 7398 void test_unusedImport_export() { |
| 7399 Source source = addSource(r''' |
| 7400 library L; |
| 7401 import 'lib1.dart'; |
| 7402 Two two;'''); |
| 7403 addNamedSource( |
| 7404 "/lib1.dart", |
| 7405 r''' |
| 7406 library lib1; |
| 7407 export 'lib2.dart'; |
| 7408 class One {}'''); |
| 7409 addNamedSource( |
| 7410 "/lib2.dart", |
| 7411 r''' |
| 7412 library lib2; |
| 7413 class Two {}'''); |
| 7414 computeLibrarySourceErrors(source); |
| 7415 assertNoErrors(source); |
| 7416 verify([source]); |
| 7417 } |
| 7418 |
| 7419 void test_unusedImport_export2() { |
| 7420 Source source = addSource(r''' |
| 7421 library L; |
| 7422 import 'lib1.dart'; |
| 7423 Three three;'''); |
| 7424 addNamedSource( |
| 7425 "/lib1.dart", |
| 7426 r''' |
| 7427 library lib1; |
| 7428 export 'lib2.dart'; |
| 7429 class One {}'''); |
| 7430 addNamedSource( |
| 7431 "/lib2.dart", |
| 7432 r''' |
| 7433 library lib2; |
| 7434 export 'lib3.dart'; |
| 7435 class Two {}'''); |
| 7436 addNamedSource( |
| 7437 "/lib3.dart", |
| 7438 r''' |
| 7439 library lib3; |
| 7440 class Three {}'''); |
| 7441 computeLibrarySourceErrors(source); |
| 7442 assertNoErrors(source); |
| 7443 verify([source]); |
| 7444 } |
| 7445 |
| 7446 void test_unusedImport_export_infiniteLoop() { |
| 7447 Source source = addSource(r''' |
| 7448 library L; |
| 7449 import 'lib1.dart'; |
| 7450 Two two;'''); |
| 7451 addNamedSource( |
| 7452 "/lib1.dart", |
| 7453 r''' |
| 7454 library lib1; |
| 7455 export 'lib2.dart'; |
| 7456 class One {}'''); |
| 7457 addNamedSource( |
| 7458 "/lib2.dart", |
| 7459 r''' |
| 7460 library lib2; |
| 7461 export 'lib3.dart'; |
| 7462 class Two {}'''); |
| 7463 addNamedSource( |
| 7464 "/lib3.dart", |
| 7465 r''' |
| 7466 library lib3; |
| 7467 export 'lib2.dart'; |
| 7468 class Three {}'''); |
| 7469 computeLibrarySourceErrors(source); |
| 7470 assertNoErrors(source); |
| 7471 verify([source]); |
| 7472 } |
| 7473 |
| 7474 void test_unusedImport_metadata() { |
| 7475 Source source = addSource(r''' |
| 7476 library L; |
| 7477 @A(x) |
| 7478 import 'lib1.dart'; |
| 7479 class A { |
| 7480 final int value; |
| 7481 const A(this.value); |
| 7482 }'''); |
| 7483 addNamedSource( |
| 7484 "/lib1.dart", |
| 7485 r''' |
| 7486 library lib1; |
| 7487 const x = 0;'''); |
| 7488 computeLibrarySourceErrors(source); |
| 7489 assertNoErrors(source); |
| 7490 verify([source]); |
| 7491 } |
| 7492 |
| 7493 void test_unusedImport_prefix_topLevelFunction() { |
| 7494 Source source = addSource(r''' |
| 7495 library L; |
| 7496 import 'lib1.dart' hide topLevelFunction; |
| 7497 import 'lib1.dart' as one show topLevelFunction; |
| 7498 class A { |
| 7499 static void x() { |
| 7500 One o; |
| 7501 one.topLevelFunction(); |
| 7502 } |
| 7503 }'''); |
| 7504 addNamedSource( |
| 7505 "/lib1.dart", |
| 7506 r''' |
| 7507 library lib1; |
| 7508 class One {} |
| 7509 topLevelFunction() {}'''); |
| 7510 computeLibrarySourceErrors(source); |
| 7511 assertNoErrors(source); |
| 7512 verify([source]); |
| 7513 } |
| 7514 |
| 7515 void test_useOfVoidResult_implicitReturnValue() { |
| 7516 Source source = addSource(r''' |
| 7517 f() {} |
| 7518 class A { |
| 7519 n() { |
| 7520 var a = f(); |
| 7521 } |
| 7522 }'''); |
| 7523 computeLibrarySourceErrors(source); |
| 7524 assertNoErrors(source); |
| 7525 verify([source]); |
| 7526 } |
| 7527 |
| 7528 void test_useOfVoidResult_nonVoidReturnValue() { |
| 7529 Source source = addSource(r''' |
| 7530 int f() => 1; |
| 7531 g() { |
| 7532 var a = f(); |
| 7533 }'''); |
| 7534 computeLibrarySourceErrors(source); |
| 7535 assertNoErrors(source); |
| 7536 verify([source]); |
| 7537 } |
| 7538 } |
| 7539 |
| 7540 class PubSuggestionCodeTest extends ResolverTestCase { |
| 7541 void test_import_package() { |
| 7542 Source source = addSource("import 'package:somepackage/other.dart';"); |
| 7543 computeLibrarySourceErrors(source); |
| 7544 assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]); |
| 7545 } |
| 7546 |
| 7547 void test_import_packageWithDotDot() { |
| 7548 Source source = addSource("import 'package:somepackage/../other.dart';"); |
| 7549 computeLibrarySourceErrors(source); |
| 7550 assertErrors(source, [ |
| 7551 CompileTimeErrorCode.URI_DOES_NOT_EXIST, |
| 7552 HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT |
| 7553 ]); |
| 7554 } |
| 7555 |
| 7556 void test_import_packageWithLeadingDotDot() { |
| 7557 Source source = addSource("import 'package:../other.dart';"); |
| 7558 computeLibrarySourceErrors(source); |
| 7559 assertErrors(source, [ |
| 7560 CompileTimeErrorCode.URI_DOES_NOT_EXIST, |
| 7561 HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT |
| 7562 ]); |
| 7563 } |
| 7564 |
| 7565 void test_import_referenceIntoLibDirectory() { |
| 7566 cacheSource("/myproj/pubspec.yaml", ""); |
| 7567 cacheSource("/myproj/lib/other.dart", ""); |
| 7568 Source source = |
| 7569 addNamedSource("/myproj/web/test.dart", "import '../lib/other.dart';"); |
| 7570 computeLibrarySourceErrors(source); |
| 7571 assertErrors( |
| 7572 source, [HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE]); |
| 7573 } |
| 7574 |
| 7575 void test_import_referenceIntoLibDirectory_no_pubspec() { |
| 7576 cacheSource("/myproj/lib/other.dart", ""); |
| 7577 Source source = |
| 7578 addNamedSource("/myproj/web/test.dart", "import '../lib/other.dart';"); |
| 7579 computeLibrarySourceErrors(source); |
| 7580 assertNoErrors(source); |
| 7581 } |
| 7582 |
| 7583 void test_import_referenceOutOfLibDirectory() { |
| 7584 cacheSource("/myproj/pubspec.yaml", ""); |
| 7585 cacheSource("/myproj/web/other.dart", ""); |
| 7586 Source source = |
| 7587 addNamedSource("/myproj/lib/test.dart", "import '../web/other.dart';"); |
| 7588 computeLibrarySourceErrors(source); |
| 7589 assertErrors( |
| 7590 source, [HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE]); |
| 7591 } |
| 7592 |
| 7593 void test_import_referenceOutOfLibDirectory_no_pubspec() { |
| 7594 cacheSource("/myproj/web/other.dart", ""); |
| 7595 Source source = |
| 7596 addNamedSource("/myproj/lib/test.dart", "import '../web/other.dart';"); |
| 7597 computeLibrarySourceErrors(source); |
| 7598 assertNoErrors(source); |
| 7599 } |
| 7600 |
| 7601 void test_import_valid_inside_lib1() { |
| 7602 cacheSource("/myproj/pubspec.yaml", ""); |
| 7603 cacheSource("/myproj/lib/other.dart", ""); |
| 7604 Source source = |
| 7605 addNamedSource("/myproj/lib/test.dart", "import 'other.dart';"); |
| 7606 computeLibrarySourceErrors(source); |
| 7607 assertNoErrors(source); |
| 7608 } |
| 7609 |
| 7610 void test_import_valid_inside_lib2() { |
| 7611 cacheSource("/myproj/pubspec.yaml", ""); |
| 7612 cacheSource("/myproj/lib/bar/other.dart", ""); |
| 7613 Source source = addNamedSource( |
| 7614 "/myproj/lib/foo/test.dart", "import '../bar/other.dart';"); |
| 7615 computeLibrarySourceErrors(source); |
| 7616 assertNoErrors(source); |
| 7617 } |
| 7618 |
| 7619 void test_import_valid_outside_lib() { |
| 7620 cacheSource("/myproj/pubspec.yaml", ""); |
| 7621 cacheSource("/myproj/web/other.dart", ""); |
| 7622 Source source = |
| 7623 addNamedSource("/myproj/lib2/test.dart", "import '../web/other.dart';"); |
| 7624 computeLibrarySourceErrors(source); |
| 7625 assertNoErrors(source); |
| 7626 } |
| 7627 } |
| 7628 |
| 7629 /** |
| 7630 * An AST visitor used to verify that all of the nodes in an AST structure that |
| 7631 * should have been resolved were resolved. |
| 7632 */ |
| 7633 class ResolutionVerifier extends RecursiveAstVisitor<Object> { |
| 7634 /** |
| 7635 * A set containing nodes that are known to not be resolvable and should |
| 7636 * therefore not cause the test to fail. |
| 7637 */ |
| 7638 final Set<AstNode> _knownExceptions; |
| 7639 |
| 7640 /** |
| 7641 * A list containing all of the AST nodes that were not resolved. |
| 7642 */ |
| 7643 List<AstNode> _unresolvedNodes = new List<AstNode>(); |
| 7644 |
| 7645 /** |
| 7646 * A list containing all of the AST nodes that were resolved to an element of |
| 7647 * the wrong type. |
| 7648 */ |
| 7649 List<AstNode> _wrongTypedNodes = new List<AstNode>(); |
| 7650 |
| 7651 /** |
| 7652 * Initialize a newly created verifier to verify that all of the identifiers |
| 7653 * in the visited AST structures that are expected to have been resolved have |
| 7654 * an element associated with them. Nodes in the set of [_knownExceptions] are |
| 7655 * not expected to have been resolved, even if they normally would have been |
| 7656 * expected to have been resolved. |
| 7657 */ |
| 7658 ResolutionVerifier([this._knownExceptions]); |
| 7659 |
| 7660 /** |
| 7661 * Assert that all of the visited identifiers were resolved. |
| 7662 */ |
| 7663 void assertResolved() { |
| 7664 if (!_unresolvedNodes.isEmpty || !_wrongTypedNodes.isEmpty) { |
| 7665 StringBuffer buffer = new StringBuffer(); |
| 7666 if (!_unresolvedNodes.isEmpty) { |
| 7667 buffer.write("Failed to resolve "); |
| 7668 buffer.write(_unresolvedNodes.length); |
| 7669 buffer.writeln(" nodes:"); |
| 7670 _printNodes(buffer, _unresolvedNodes); |
| 7671 } |
| 7672 if (!_wrongTypedNodes.isEmpty) { |
| 7673 buffer.write("Resolved "); |
| 7674 buffer.write(_wrongTypedNodes.length); |
| 7675 buffer.writeln(" to the wrong type of element:"); |
| 7676 _printNodes(buffer, _wrongTypedNodes); |
| 7677 } |
| 7678 fail(buffer.toString()); |
| 7679 } |
| 7680 } |
| 7681 |
| 7682 @override |
| 7683 Object visitAnnotation(Annotation node) { |
| 7684 node.visitChildren(this); |
| 7685 ElementAnnotation elementAnnotation = node.elementAnnotation; |
| 7686 if (elementAnnotation == null) { |
| 7687 if (_knownExceptions == null || !_knownExceptions.contains(node)) { |
| 7688 _unresolvedNodes.add(node); |
| 7689 } |
| 7690 } else if (elementAnnotation is! ElementAnnotation) { |
| 7691 _wrongTypedNodes.add(node); |
| 7692 } |
| 7693 return null; |
| 7694 } |
| 7695 |
| 7696 @override |
| 7697 Object visitBinaryExpression(BinaryExpression node) { |
| 7698 node.visitChildren(this); |
| 7699 if (!node.operator.isUserDefinableOperator) { |
| 7700 return null; |
| 7701 } |
| 7702 DartType operandType = node.leftOperand.staticType; |
| 7703 if (operandType == null || operandType.isDynamic) { |
| 7704 return null; |
| 7705 } |
| 7706 return _checkResolved( |
| 7707 node, node.staticElement, (node) => node is MethodElement); |
| 7708 } |
| 7709 |
| 7710 @override |
| 7711 Object visitCommentReference(CommentReference node) => null; |
| 7712 |
| 7713 @override |
| 7714 Object visitCompilationUnit(CompilationUnit node) { |
| 7715 node.visitChildren(this); |
| 7716 return _checkResolved( |
| 7717 node, node.element, (node) => node is CompilationUnitElement); |
| 7718 } |
| 7719 |
| 7720 @override |
| 7721 Object visitExportDirective(ExportDirective node) => |
| 7722 _checkResolved(node, node.element, (node) => node is ExportElement); |
| 7723 |
| 7724 @override |
| 7725 Object visitFunctionDeclaration(FunctionDeclaration node) { |
| 7726 node.visitChildren(this); |
| 7727 if (node.element is LibraryElement) { |
| 7728 _wrongTypedNodes.add(node); |
| 7729 } |
| 7730 return null; |
| 7731 } |
| 7732 |
| 7733 @override |
| 7734 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| 7735 node.visitChildren(this); |
| 7736 // TODO(brianwilkerson) If we start resolving function expressions, then |
| 7737 // conditionally check to see whether the node was resolved correctly. |
| 7738 return null; |
| 7739 //checkResolved(node, node.getElement(), FunctionElement.class); |
| 7740 } |
| 7741 |
| 7742 @override |
| 7743 Object visitImportDirective(ImportDirective node) { |
| 7744 // Not sure how to test the combinators given that it isn't an error if the |
| 7745 // names are not defined. |
| 7746 _checkResolved(node, node.element, (node) => node is ImportElement); |
| 7747 SimpleIdentifier prefix = node.prefix; |
| 7748 if (prefix == null) { |
| 7749 return null; |
| 7750 } |
| 7751 return _checkResolved( |
| 7752 prefix, prefix.staticElement, (node) => node is PrefixElement); |
| 7753 } |
| 7754 |
| 7755 @override |
| 7756 Object visitIndexExpression(IndexExpression node) { |
| 7757 node.visitChildren(this); |
| 7758 DartType targetType = node.realTarget.staticType; |
| 7759 if (targetType == null || targetType.isDynamic) { |
| 7760 return null; |
| 7761 } |
| 7762 return _checkResolved( |
| 7763 node, node.staticElement, (node) => node is MethodElement); |
| 7764 } |
| 7765 |
| 7766 @override |
| 7767 Object visitLibraryDirective(LibraryDirective node) => |
| 7768 _checkResolved(node, node.element, (node) => node is LibraryElement); |
| 7769 |
| 7770 @override |
| 7771 Object visitNamedExpression(NamedExpression node) => |
| 7772 node.expression.accept(this); |
| 7773 |
| 7774 @override |
| 7775 Object visitPartDirective(PartDirective node) => _checkResolved( |
| 7776 node, node.element, (node) => node is CompilationUnitElement); |
| 7777 |
| 7778 @override |
| 7779 Object visitPartOfDirective(PartOfDirective node) => |
| 7780 _checkResolved(node, node.element, (node) => node is LibraryElement); |
| 7781 |
| 7782 @override |
| 7783 Object visitPostfixExpression(PostfixExpression node) { |
| 7784 node.visitChildren(this); |
| 7785 if (!node.operator.isUserDefinableOperator) { |
| 7786 return null; |
| 7787 } |
| 7788 DartType operandType = node.operand.staticType; |
| 7789 if (operandType == null || operandType.isDynamic) { |
| 7790 return null; |
| 7791 } |
| 7792 return _checkResolved( |
| 7793 node, node.staticElement, (node) => node is MethodElement); |
| 7794 } |
| 7795 |
| 7796 @override |
| 7797 Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 7798 SimpleIdentifier prefix = node.prefix; |
| 7799 prefix.accept(this); |
| 7800 DartType prefixType = prefix.staticType; |
| 7801 if (prefixType == null || prefixType.isDynamic) { |
| 7802 return null; |
| 7803 } |
| 7804 return _checkResolved(node, node.staticElement, null); |
| 7805 } |
| 7806 |
| 7807 @override |
| 7808 Object visitPrefixExpression(PrefixExpression node) { |
| 7809 node.visitChildren(this); |
| 7810 if (!node.operator.isUserDefinableOperator) { |
| 7811 return null; |
| 7812 } |
| 7813 DartType operandType = node.operand.staticType; |
| 7814 if (operandType == null || operandType.isDynamic) { |
| 7815 return null; |
| 7816 } |
| 7817 return _checkResolved( |
| 7818 node, node.staticElement, (node) => node is MethodElement); |
| 7819 } |
| 7820 |
| 7821 @override |
| 7822 Object visitPropertyAccess(PropertyAccess node) { |
| 7823 Expression target = node.realTarget; |
| 7824 target.accept(this); |
| 7825 DartType targetType = target.staticType; |
| 7826 if (targetType == null || targetType.isDynamic) { |
| 7827 return null; |
| 7828 } |
| 7829 return node.propertyName.accept(this); |
| 7830 } |
| 7831 |
| 7832 @override |
| 7833 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 7834 if (node.name == "void") { |
| 7835 return null; |
| 7836 } |
| 7837 AstNode parent = node.parent; |
| 7838 if (parent is MethodInvocation) { |
| 7839 MethodInvocation invocation = parent; |
| 7840 if (identical(invocation.methodName, node)) { |
| 7841 Expression target = invocation.realTarget; |
| 7842 DartType targetType = target == null ? null : target.staticType; |
| 7843 if (targetType == null || targetType.isDynamic) { |
| 7844 return null; |
| 7845 } |
| 7846 } |
| 7847 } |
| 7848 return _checkResolved(node, node.staticElement, null); |
| 7849 } |
| 7850 |
| 7851 Object _checkResolved( |
| 7852 AstNode node, Element element, Predicate<Element> predicate) { |
| 7853 if (element == null) { |
| 7854 if (_knownExceptions == null || !_knownExceptions.contains(node)) { |
| 7855 _unresolvedNodes.add(node); |
| 7856 } |
| 7857 } else if (predicate != null) { |
| 7858 if (!predicate(element)) { |
| 7859 _wrongTypedNodes.add(node); |
| 7860 } |
| 7861 } |
| 7862 return null; |
| 7863 } |
| 7864 |
| 7865 String _getFileName(AstNode node) { |
| 7866 // TODO (jwren) there are two copies of this method, one here and one in |
| 7867 // StaticTypeVerifier, they should be resolved into a single method |
| 7868 if (node != null) { |
| 7869 AstNode root = node.root; |
| 7870 if (root is CompilationUnit) { |
| 7871 CompilationUnit rootCU = root; |
| 7872 if (rootCU.element != null) { |
| 7873 return rootCU.element.source.fullName; |
| 7874 } else { |
| 7875 return "<unknown file- CompilationUnit.getElement() returned null>"; |
| 7876 } |
| 7877 } else { |
| 7878 return "<unknown file- CompilationUnit.getRoot() is not a CompilationUni
t>"; |
| 7879 } |
| 7880 } |
| 7881 return "<unknown file- ASTNode is null>"; |
| 7882 } |
| 7883 |
| 7884 void _printNodes(StringBuffer buffer, List<AstNode> nodes) { |
| 7885 for (AstNode identifier in nodes) { |
| 7886 buffer.write(" "); |
| 7887 buffer.write(identifier.toString()); |
| 7888 buffer.write(" ("); |
| 7889 buffer.write(_getFileName(identifier)); |
| 7890 buffer.write(" : "); |
| 7891 buffer.write(identifier.offset); |
| 7892 buffer.writeln(")"); |
| 7893 } |
| 7894 } |
| 7895 } |
| 7896 |
| 7897 class ResolverTestCase extends EngineTestCase { |
| 7898 /** |
| 7899 * The analysis context used to parse the compilation units being resolved. |
| 7900 */ |
| 7901 InternalAnalysisContext analysisContext2; |
| 7902 |
| 7903 /** |
| 7904 * Specifies if [assertErrors] should check for [HintCode.UNUSED_ELEMENT] and |
| 7905 * [HintCode.UNUSED_FIELD]. |
| 7906 */ |
| 7907 bool enableUnusedElement = false; |
| 7908 |
| 7909 /** |
| 7910 * Specifies if [assertErrors] should check for [HintCode.UNUSED_LOCAL_VARIABL
E]. |
| 7911 */ |
| 7912 bool enableUnusedLocalVariable = false; |
| 7913 |
| 7914 AnalysisContext get analysisContext => analysisContext2; |
| 7915 |
| 7916 /** |
| 7917 * Return a type provider that can be used to test the results of resolution. |
| 7918 * |
| 7919 * @return a type provider |
| 7920 * @throws AnalysisException if dart:core cannot be resolved |
| 7921 */ |
| 7922 TypeProvider get typeProvider => analysisContext2.typeProvider; |
| 7923 |
| 7924 /** |
| 7925 * Return a type system that can be used to test the results of resolution. |
| 7926 * |
| 7927 * @return a type system |
| 7928 */ |
| 7929 TypeSystem get typeSystem => analysisContext2.typeSystem; |
| 7930 |
| 7931 /** |
| 7932 * Add a source file to the content provider. The file path should be absolute
. |
| 7933 * |
| 7934 * @param filePath the path of the file being added |
| 7935 * @param contents the contents to be returned by the content provider for the
specified file |
| 7936 * @return the source object representing the added file |
| 7937 */ |
| 7938 Source addNamedSource(String filePath, String contents) { |
| 7939 Source source = cacheSource(filePath, contents); |
| 7940 ChangeSet changeSet = new ChangeSet(); |
| 7941 changeSet.addedSource(source); |
| 7942 analysisContext2.applyChanges(changeSet); |
| 7943 return source; |
| 7944 } |
| 7945 |
| 7946 /** |
| 7947 * Add a source file to the content provider. |
| 7948 * |
| 7949 * @param contents the contents to be returned by the content provider for the
specified file |
| 7950 * @return the source object representing the added file |
| 7951 */ |
| 7952 Source addSource(String contents) => addNamedSource("/test.dart", contents); |
| 7953 |
| 7954 /** |
| 7955 * Assert that the number of errors reported against the given source matches
the number of errors |
| 7956 * that are given and that they have the expected error codes. The order in wh
ich the errors were |
| 7957 * gathered is ignored. |
| 7958 * |
| 7959 * @param source the source against which the errors should have been reported |
| 7960 * @param expectedErrorCodes the error codes of the errors that should have be
en reported |
| 7961 * @throws AnalysisException if the reported errors could not be computed |
| 7962 * @throws AssertionFailedError if a different number of errors have been repo
rted than were |
| 7963 * expected |
| 7964 */ |
| 7965 void assertErrors(Source source, |
| 7966 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { |
| 7967 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 7968 for (AnalysisError error in analysisContext2.computeErrors(source)) { |
| 7969 ErrorCode errorCode = error.errorCode; |
| 7970 if (!enableUnusedElement && |
| 7971 (errorCode == HintCode.UNUSED_ELEMENT || |
| 7972 errorCode == HintCode.UNUSED_FIELD)) { |
| 7973 continue; |
| 7974 } |
| 7975 if (!enableUnusedLocalVariable && |
| 7976 (errorCode == HintCode.UNUSED_CATCH_CLAUSE || |
| 7977 errorCode == HintCode.UNUSED_CATCH_STACK || |
| 7978 errorCode == HintCode.UNUSED_LOCAL_VARIABLE)) { |
| 7979 continue; |
| 7980 } |
| 7981 errorListener.onError(error); |
| 7982 } |
| 7983 errorListener.assertErrorsWithCodes(expectedErrorCodes); |
| 7984 } |
| 7985 |
| 7986 /** |
| 7987 * Assert that no errors have been reported against the given source. |
| 7988 * |
| 7989 * @param source the source against which no errors should have been reported |
| 7990 * @throws AnalysisException if the reported errors could not be computed |
| 7991 * @throws AssertionFailedError if any errors have been reported |
| 7992 */ |
| 7993 void assertNoErrors(Source source) { |
| 7994 assertErrors(source); |
| 7995 } |
| 7996 |
| 7997 /** |
| 7998 * Cache the source file content in the source factory but don't add the sourc
e to the analysis |
| 7999 * context. The file path should be absolute. |
| 8000 * |
| 8001 * @param filePath the path of the file being cached |
| 8002 * @param contents the contents to be returned by the content provider for the
specified file |
| 8003 * @return the source object representing the cached file |
| 8004 */ |
| 8005 Source cacheSource(String filePath, String contents) { |
| 8006 Source source = new FileBasedSource(FileUtilities2.createFile(filePath)); |
| 8007 analysisContext2.setContents(source, contents); |
| 8008 return source; |
| 8009 } |
| 8010 |
| 8011 /** |
| 8012 * Change the contents of the given [source] to the given [contents]. |
| 8013 */ |
| 8014 void changeSource(Source source, String contents) { |
| 8015 analysisContext2.setContents(source, contents); |
| 8016 ChangeSet changeSet = new ChangeSet(); |
| 8017 changeSet.changedSource(source); |
| 8018 analysisContext2.applyChanges(changeSet); |
| 8019 } |
| 8020 |
| 8021 /** |
| 8022 * Computes errors for the given [librarySource]. |
| 8023 * This assumes that the given [librarySource] and its parts have already |
| 8024 * been added to the content provider using the method [addNamedSource]. |
| 8025 */ |
| 8026 void computeLibrarySourceErrors(Source librarySource) { |
| 8027 analysisContext.computeErrors(librarySource); |
| 8028 } |
| 8029 |
| 8030 /** |
| 8031 * Create a library element that represents a library named `"test"` containin
g a single |
| 8032 * empty compilation unit. |
| 8033 * |
| 8034 * @return the library element that was created |
| 8035 */ |
| 8036 LibraryElementImpl createDefaultTestLibrary() => |
| 8037 createTestLibrary(AnalysisContextFactory.contextWithCore(), "test"); |
| 8038 |
| 8039 /** |
| 8040 * Create a library element that represents a library with the given name cont
aining a single |
| 8041 * empty compilation unit. |
| 8042 * |
| 8043 * @param libraryName the name of the library to be created |
| 8044 * @return the library element that was created |
| 8045 */ |
| 8046 LibraryElementImpl createTestLibrary( |
| 8047 AnalysisContext context, String libraryName, |
| 8048 [List<String> typeNames]) { |
| 8049 String fileName = "$libraryName.dart"; |
| 8050 FileBasedSource definingCompilationUnitSource = |
| 8051 _createNamedSource(fileName); |
| 8052 List<CompilationUnitElement> sourcedCompilationUnits; |
| 8053 if (typeNames == null) { |
| 8054 sourcedCompilationUnits = CompilationUnitElement.EMPTY_LIST; |
| 8055 } else { |
| 8056 int count = typeNames.length; |
| 8057 sourcedCompilationUnits = new List<CompilationUnitElement>(count); |
| 8058 for (int i = 0; i < count; i++) { |
| 8059 String typeName = typeNames[i]; |
| 8060 ClassElementImpl type = |
| 8061 new ClassElementImpl.forNode(AstFactory.identifier3(typeName)); |
| 8062 String fileName = "$typeName.dart"; |
| 8063 CompilationUnitElementImpl compilationUnit = |
| 8064 new CompilationUnitElementImpl(fileName); |
| 8065 compilationUnit.source = _createNamedSource(fileName); |
| 8066 compilationUnit.librarySource = definingCompilationUnitSource; |
| 8067 compilationUnit.types = <ClassElement>[type]; |
| 8068 sourcedCompilationUnits[i] = compilationUnit; |
| 8069 } |
| 8070 } |
| 8071 CompilationUnitElementImpl compilationUnit = |
| 8072 new CompilationUnitElementImpl(fileName); |
| 8073 compilationUnit.librarySource = |
| 8074 compilationUnit.source = definingCompilationUnitSource; |
| 8075 LibraryElementImpl library = new LibraryElementImpl.forNode( |
| 8076 context, AstFactory.libraryIdentifier2([libraryName])); |
| 8077 library.definingCompilationUnit = compilationUnit; |
| 8078 library.parts = sourcedCompilationUnits; |
| 8079 return library; |
| 8080 } |
| 8081 |
| 8082 Expression findTopLevelConstantExpression( |
| 8083 CompilationUnit compilationUnit, String name) => |
| 8084 findTopLevelDeclaration(compilationUnit, name).initializer; |
| 8085 |
| 8086 VariableDeclaration findTopLevelDeclaration( |
| 8087 CompilationUnit compilationUnit, String name) { |
| 8088 for (CompilationUnitMember member in compilationUnit.declarations) { |
| 8089 if (member is TopLevelVariableDeclaration) { |
| 8090 for (VariableDeclaration variable in member.variables.variables) { |
| 8091 if (variable.name.name == name) { |
| 8092 return variable; |
| 8093 } |
| 8094 } |
| 8095 } |
| 8096 } |
| 8097 return null; |
| 8098 // Not found |
| 8099 } |
| 8100 |
| 8101 /** |
| 8102 * In the rare cases we want to group several tests into single "test_" method
, so need a way to |
| 8103 * reset test instance to reuse it. |
| 8104 */ |
| 8105 void reset() { |
| 8106 analysisContext2 = AnalysisContextFactory.contextWithCore(); |
| 8107 } |
| 8108 |
| 8109 /** |
| 8110 * Reset the analysis context to have the given options applied. |
| 8111 * |
| 8112 * @param options the analysis options to be applied to the context |
| 8113 */ |
| 8114 void resetWithOptions(AnalysisOptions options) { |
| 8115 analysisContext2 = |
| 8116 AnalysisContextFactory.contextWithCoreAndOptions(options); |
| 8117 } |
| 8118 |
| 8119 /** |
| 8120 * Given a library and all of its parts, resolve the contents of the library a
nd the contents of |
| 8121 * the parts. This assumes that the sources for the library and its parts have
already been added |
| 8122 * to the content provider using the method [addNamedSource]. |
| 8123 * |
| 8124 * @param librarySource the source for the compilation unit that defines the l
ibrary |
| 8125 * @return the element representing the resolved library |
| 8126 * @throws AnalysisException if the analysis could not be performed |
| 8127 */ |
| 8128 LibraryElement resolve2(Source librarySource) => |
| 8129 analysisContext2.computeLibraryElement(librarySource); |
| 8130 |
| 8131 /** |
| 8132 * Return the resolved compilation unit corresponding to the given source in t
he given library. |
| 8133 * |
| 8134 * @param source the source of the compilation unit to be returned |
| 8135 * @param library the library in which the compilation unit is to be resolved |
| 8136 * @return the resolved compilation unit |
| 8137 * @throws Exception if the compilation unit could not be resolved |
| 8138 */ |
| 8139 CompilationUnit resolveCompilationUnit( |
| 8140 Source source, LibraryElement library) => |
| 8141 analysisContext2.resolveCompilationUnit(source, library); |
| 8142 |
| 8143 CompilationUnit resolveSource(String sourceText) => |
| 8144 resolveSource2("/test.dart", sourceText); |
| 8145 |
| 8146 CompilationUnit resolveSource2(String fileName, String sourceText) { |
| 8147 Source source = addNamedSource(fileName, sourceText); |
| 8148 LibraryElement library = analysisContext.computeLibraryElement(source); |
| 8149 return analysisContext.resolveCompilationUnit(source, library); |
| 8150 } |
| 8151 |
| 8152 Source resolveSources(List<String> sourceTexts) { |
| 8153 for (int i = 0; i < sourceTexts.length; i++) { |
| 8154 CompilationUnit unit = |
| 8155 resolveSource2("/lib${i + 1}.dart", sourceTexts[i]); |
| 8156 // reference the source if this is the last source |
| 8157 if (i + 1 == sourceTexts.length) { |
| 8158 return unit.element.source; |
| 8159 } |
| 8160 } |
| 8161 return null; |
| 8162 } |
| 8163 |
| 8164 void resolveWithAndWithoutExperimental( |
| 8165 List<String> strSources, |
| 8166 List<ErrorCode> codesWithoutExperimental, |
| 8167 List<ErrorCode> codesWithExperimental) { |
| 8168 // Setup analysis context as non-experimental |
| 8169 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 8170 // options.enableDeferredLoading = false; |
| 8171 resetWithOptions(options); |
| 8172 // Analysis and assertions |
| 8173 Source source = resolveSources(strSources); |
| 8174 assertErrors(source, codesWithoutExperimental); |
| 8175 verify([source]); |
| 8176 // Setup analysis context as experimental |
| 8177 reset(); |
| 8178 // Analysis and assertions |
| 8179 source = resolveSources(strSources); |
| 8180 assertErrors(source, codesWithExperimental); |
| 8181 verify([source]); |
| 8182 } |
| 8183 |
| 8184 void resolveWithErrors(List<String> strSources, List<ErrorCode> codes) { |
| 8185 // Analysis and assertions |
| 8186 Source source = resolveSources(strSources); |
| 8187 assertErrors(source, codes); |
| 8188 verify([source]); |
| 8189 } |
| 8190 |
| 8191 @override |
| 8192 void setUp() { |
| 8193 reset(); |
| 8194 } |
| 8195 |
| 8196 @override |
| 8197 void tearDown() { |
| 8198 analysisContext2 = null; |
| 8199 super.tearDown(); |
| 8200 } |
| 8201 |
| 8202 /** |
| 8203 * Verify that all of the identifiers in the compilation units associated with |
| 8204 * the given [sources] have been resolved. |
| 8205 */ |
| 8206 void verify(List<Source> sources) { |
| 8207 ResolutionVerifier verifier = new ResolutionVerifier(); |
| 8208 for (Source source in sources) { |
| 8209 List<Source> libraries = analysisContext2.getLibrariesContaining(source); |
| 8210 for (Source library in libraries) { |
| 8211 analysisContext2 |
| 8212 .resolveCompilationUnit2(source, library) |
| 8213 .accept(verifier); |
| 8214 } |
| 8215 } |
| 8216 verifier.assertResolved(); |
| 8217 } |
| 8218 |
| 8219 /** |
| 8220 * @param code the code that assigns the value to the variable "v", no matter
how. We check that |
| 8221 * "v" has expected static and propagated type. |
| 8222 */ |
| 8223 void _assertPropagatedAssignedType(String code, DartType expectedStaticType, |
| 8224 DartType expectedPropagatedType) { |
| 8225 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = "); |
| 8226 expect(identifier.staticType, same(expectedStaticType)); |
| 8227 expect(identifier.propagatedType, same(expectedPropagatedType)); |
| 8228 } |
| 8229 |
| 8230 /** |
| 8231 * @param code the code that iterates using variable "v". We check that |
| 8232 * "v" has expected static and propagated type. |
| 8233 */ |
| 8234 void _assertPropagatedIterationType(String code, DartType expectedStaticType, |
| 8235 DartType expectedPropagatedType) { |
| 8236 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v in "); |
| 8237 expect(identifier.staticType, same(expectedStaticType)); |
| 8238 expect(identifier.propagatedType, same(expectedPropagatedType)); |
| 8239 } |
| 8240 |
| 8241 /** |
| 8242 * Check the static and propagated types of the expression marked with "; // m
arker" comment. |
| 8243 * |
| 8244 * @param code source code to analyze, with the expression to check marked wit
h "// marker". |
| 8245 * @param expectedStaticType if non-null, check actual static type is equal to
this. |
| 8246 * @param expectedPropagatedType if non-null, check actual static type is equa
l to this. |
| 8247 * @throws Exception |
| 8248 */ |
| 8249 void _assertTypeOfMarkedExpression(String code, DartType expectedStaticType, |
| 8250 DartType expectedPropagatedType) { |
| 8251 SimpleIdentifier identifier = _findMarkedIdentifier(code, "; // marker"); |
| 8252 if (expectedStaticType != null) { |
| 8253 expect(identifier.staticType, expectedStaticType); |
| 8254 } |
| 8255 expect(identifier.propagatedType, expectedPropagatedType); |
| 8256 } |
| 8257 |
| 8258 /** |
| 8259 * Create a source object representing a file with the given [fileName] and |
| 8260 * give it an empty content. Return the source that was created. |
| 8261 */ |
| 8262 FileBasedSource _createNamedSource(String fileName) { |
| 8263 FileBasedSource source = |
| 8264 new FileBasedSource(FileUtilities2.createFile(fileName)); |
| 8265 analysisContext2.setContents(source, ""); |
| 8266 return source; |
| 8267 } |
| 8268 |
| 8269 /** |
| 8270 * Return the `SimpleIdentifier` marked by `marker`. The source code must have
no |
| 8271 * errors and be verifiable. |
| 8272 * |
| 8273 * @param code source code to analyze. |
| 8274 * @param marker marker identifying sought after expression in source code. |
| 8275 * @return expression marked by the marker. |
| 8276 * @throws Exception |
| 8277 */ |
| 8278 SimpleIdentifier _findMarkedIdentifier(String code, String marker) { |
| 8279 try { |
| 8280 Source source = addSource(code); |
| 8281 LibraryElement library = resolve2(source); |
| 8282 assertNoErrors(source); |
| 8283 verify([source]); |
| 8284 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 8285 // Could generalize this further by making [SimpleIdentifier.class] a |
| 8286 // parameter. |
| 8287 return EngineTestCase.findNode( |
| 8288 unit, code, marker, (node) => node is SimpleIdentifier); |
| 8289 } catch (exception) { |
| 8290 // Is there a better exception to throw here? The point is that an |
| 8291 // assertion failure here should be a failure, in both "test_*" and |
| 8292 // "fail_*" tests. However, an assertion failure is success for the |
| 8293 // purpose of "fail_*" tests, so without catching them here "fail_*" tests |
| 8294 // can succeed by failing for the wrong reason. |
| 8295 throw new JavaException("Unexexpected assertion failure: $exception"); |
| 8296 } |
| 8297 } |
| 8298 } |
| 8299 |
| 8300 class Scope_EnclosedScopeTest_test_define_duplicate extends Scope { |
| 8301 GatheringErrorListener listener; |
| 8302 |
| 8303 Scope_EnclosedScopeTest_test_define_duplicate(this.listener) : super(); |
| 8304 |
| 8305 @override |
| 8306 AnalysisErrorListener get errorListener => listener; |
| 8307 |
| 8308 @override |
| 8309 Element internalLookup(Identifier identifier, String name, |
| 8310 LibraryElement referencingLibrary) => |
| 8311 null; |
| 8312 } |
| 8313 |
| 8314 class Scope_EnclosedScopeTest_test_define_normal extends Scope { |
| 8315 GatheringErrorListener listener; |
| 8316 |
| 8317 Scope_EnclosedScopeTest_test_define_normal(this.listener) : super(); |
| 8318 |
| 8319 @override |
| 8320 AnalysisErrorListener get errorListener => listener; |
| 8321 |
| 8322 @override |
| 8323 Element internalLookup(Identifier identifier, String name, |
| 8324 LibraryElement referencingLibrary) => |
| 8325 null; |
| 8326 } |
| 8327 |
| 8328 @reflectiveTest |
| 8329 class ScopeTest extends ResolverTestCase { |
| 8330 void test_define_duplicate() { |
| 8331 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 8332 ScopeTest_TestScope scope = new ScopeTest_TestScope(errorListener); |
| 8333 VariableElement element1 = |
| 8334 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 8335 VariableElement element2 = |
| 8336 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 8337 scope.define(element1); |
| 8338 scope.define(element2); |
| 8339 errorListener.assertErrorsWithSeverities([ErrorSeverity.ERROR]); |
| 8340 } |
| 8341 |
| 8342 void test_define_normal() { |
| 8343 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 8344 ScopeTest_TestScope scope = new ScopeTest_TestScope(errorListener); |
| 8345 VariableElement element1 = |
| 8346 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 8347 VariableElement element2 = |
| 8348 ElementFactory.localVariableElement(AstFactory.identifier3("v2")); |
| 8349 scope.define(element1); |
| 8350 scope.define(element2); |
| 8351 errorListener.assertNoErrors(); |
| 8352 } |
| 8353 |
| 8354 void test_getErrorListener() { |
| 8355 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 8356 ScopeTest_TestScope scope = new ScopeTest_TestScope(errorListener); |
| 8357 expect(scope.errorListener, errorListener); |
| 8358 } |
| 8359 |
| 8360 void test_isPrivateName_nonPrivate() { |
| 8361 expect(Scope.isPrivateName("Public"), isFalse); |
| 8362 } |
| 8363 |
| 8364 void test_isPrivateName_private() { |
| 8365 expect(Scope.isPrivateName("_Private"), isTrue); |
| 8366 } |
| 8367 } |
| 8368 |
| 8369 /** |
| 8370 * A non-abstract subclass that can be used for testing purposes. |
| 8371 */ |
| 8372 class ScopeTest_TestScope extends Scope { |
| 8373 /** |
| 8374 * The listener that is to be informed when an error is encountered. |
| 8375 */ |
| 8376 final AnalysisErrorListener errorListener; |
| 8377 |
| 8378 ScopeTest_TestScope(this.errorListener); |
| 8379 |
| 8380 @override |
| 8381 Element internalLookup(Identifier identifier, String name, |
| 8382 LibraryElement referencingLibrary) => |
| 8383 localLookup(name, referencingLibrary); |
| 8384 } |
| 8385 |
| 8386 @reflectiveTest |
| 8387 class SimpleResolverTest extends ResolverTestCase { |
| 8388 void fail_getter_and_setter_fromMixins_property_access() { |
| 8389 // TODO(paulberry): it appears that auxiliaryElements isn't properly set on |
| 8390 // a SimpleIdentifier that's inside a property access. This bug should be |
| 8391 // fixed. |
| 8392 Source source = addSource(''' |
| 8393 class B {} |
| 8394 class M1 { |
| 8395 get x => null; |
| 8396 set x(value) {} |
| 8397 } |
| 8398 class M2 { |
| 8399 get x => null; |
| 8400 set x(value) {} |
| 8401 } |
| 8402 class C extends B with M1, M2 {} |
| 8403 void main() { |
| 8404 new C().x += 1; |
| 8405 } |
| 8406 '''); |
| 8407 LibraryElement library = resolve2(source); |
| 8408 assertNoErrors(source); |
| 8409 verify([source]); |
| 8410 // Verify that both the getter and setter for "x" in "new C().x" refer to |
| 8411 // the accessors defined in M2. |
| 8412 FunctionDeclaration main = |
| 8413 library.definingCompilationUnit.functions[0].computeNode(); |
| 8414 BlockFunctionBody body = main.functionExpression.body; |
| 8415 ExpressionStatement stmt = body.block.statements[0]; |
| 8416 AssignmentExpression assignment = stmt.expression; |
| 8417 PropertyAccess propertyAccess = assignment.leftHandSide; |
| 8418 expect( |
| 8419 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 8420 expect( |
| 8421 propertyAccess |
| 8422 .propertyName.auxiliaryElements.staticElement.enclosingElement.name, |
| 8423 'M2'); |
| 8424 } |
| 8425 |
| 8426 void fail_staticInvocation() { |
| 8427 Source source = addSource(r''' |
| 8428 class A { |
| 8429 static int get g => (a,b) => 0; |
| 8430 } |
| 8431 class B { |
| 8432 f() { |
| 8433 A.g(1,0); |
| 8434 } |
| 8435 }'''); |
| 8436 computeLibrarySourceErrors(source); |
| 8437 assertNoErrors(source); |
| 8438 verify([source]); |
| 8439 } |
| 8440 |
| 8441 void test_argumentResolution_required_matching() { |
| 8442 Source source = addSource(r''' |
| 8443 class A { |
| 8444 void f() { |
| 8445 g(1, 2, 3); |
| 8446 } |
| 8447 void g(a, b, c) {} |
| 8448 }'''); |
| 8449 _validateArgumentResolution(source, [0, 1, 2]); |
| 8450 } |
| 8451 |
| 8452 void test_argumentResolution_required_tooFew() { |
| 8453 Source source = addSource(r''' |
| 8454 class A { |
| 8455 void f() { |
| 8456 g(1, 2); |
| 8457 } |
| 8458 void g(a, b, c) {} |
| 8459 }'''); |
| 8460 _validateArgumentResolution(source, [0, 1]); |
| 8461 } |
| 8462 |
| 8463 void test_argumentResolution_required_tooMany() { |
| 8464 Source source = addSource(r''' |
| 8465 class A { |
| 8466 void f() { |
| 8467 g(1, 2, 3); |
| 8468 } |
| 8469 void g(a, b) {} |
| 8470 }'''); |
| 8471 _validateArgumentResolution(source, [0, 1, -1]); |
| 8472 } |
| 8473 |
| 8474 void test_argumentResolution_requiredAndNamed_extra() { |
| 8475 Source source = addSource(r''' |
| 8476 class A { |
| 8477 void f() { |
| 8478 g(1, 2, c: 3, d: 4); |
| 8479 } |
| 8480 void g(a, b, {c}) {} |
| 8481 }'''); |
| 8482 _validateArgumentResolution(source, [0, 1, 2, -1]); |
| 8483 } |
| 8484 |
| 8485 void test_argumentResolution_requiredAndNamed_matching() { |
| 8486 Source source = addSource(r''' |
| 8487 class A { |
| 8488 void f() { |
| 8489 g(1, 2, c: 3); |
| 8490 } |
| 8491 void g(a, b, {c}) {} |
| 8492 }'''); |
| 8493 _validateArgumentResolution(source, [0, 1, 2]); |
| 8494 } |
| 8495 |
| 8496 void test_argumentResolution_requiredAndNamed_missing() { |
| 8497 Source source = addSource(r''' |
| 8498 class A { |
| 8499 void f() { |
| 8500 g(1, 2, d: 3); |
| 8501 } |
| 8502 void g(a, b, {c, d}) {} |
| 8503 }'''); |
| 8504 _validateArgumentResolution(source, [0, 1, 3]); |
| 8505 } |
| 8506 |
| 8507 void test_argumentResolution_requiredAndPositional_fewer() { |
| 8508 Source source = addSource(r''' |
| 8509 class A { |
| 8510 void f() { |
| 8511 g(1, 2, 3); |
| 8512 } |
| 8513 void g(a, b, [c, d]) {} |
| 8514 }'''); |
| 8515 _validateArgumentResolution(source, [0, 1, 2]); |
| 8516 } |
| 8517 |
| 8518 void test_argumentResolution_requiredAndPositional_matching() { |
| 8519 Source source = addSource(r''' |
| 8520 class A { |
| 8521 void f() { |
| 8522 g(1, 2, 3, 4); |
| 8523 } |
| 8524 void g(a, b, [c, d]) {} |
| 8525 }'''); |
| 8526 _validateArgumentResolution(source, [0, 1, 2, 3]); |
| 8527 } |
| 8528 |
| 8529 void test_argumentResolution_requiredAndPositional_more() { |
| 8530 Source source = addSource(r''' |
| 8531 class A { |
| 8532 void f() { |
| 8533 g(1, 2, 3, 4); |
| 8534 } |
| 8535 void g(a, b, [c]) {} |
| 8536 }'''); |
| 8537 _validateArgumentResolution(source, [0, 1, 2, -1]); |
| 8538 } |
| 8539 |
| 8540 void test_argumentResolution_setter_propagated() { |
| 8541 Source source = addSource(r''' |
| 8542 main() { |
| 8543 var a = new A(); |
| 8544 a.sss = 0; |
| 8545 } |
| 8546 class A { |
| 8547 set sss(x) {} |
| 8548 }'''); |
| 8549 LibraryElement library = resolve2(source); |
| 8550 CompilationUnitElement unit = library.definingCompilationUnit; |
| 8551 // find "a.sss = 0" |
| 8552 AssignmentExpression assignment; |
| 8553 { |
| 8554 FunctionElement mainElement = unit.functions[0]; |
| 8555 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 8556 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 8557 ExpressionStatement expressionStatement = |
| 8558 statement as ExpressionStatement; |
| 8559 assignment = expressionStatement.expression as AssignmentExpression; |
| 8560 } |
| 8561 // get parameter |
| 8562 Expression rhs = assignment.rightHandSide; |
| 8563 expect(rhs.staticParameterElement, isNull); |
| 8564 ParameterElement parameter = rhs.propagatedParameterElement; |
| 8565 expect(parameter, isNotNull); |
| 8566 expect(parameter.displayName, "x"); |
| 8567 // validate |
| 8568 ClassElement classA = unit.types[0]; |
| 8569 PropertyAccessorElement setter = classA.accessors[0]; |
| 8570 expect(setter.parameters[0], same(parameter)); |
| 8571 } |
| 8572 |
| 8573 void test_argumentResolution_setter_propagated_propertyAccess() { |
| 8574 Source source = addSource(r''' |
| 8575 main() { |
| 8576 var a = new A(); |
| 8577 a.b.sss = 0; |
| 8578 } |
| 8579 class A { |
| 8580 B b = new B(); |
| 8581 } |
| 8582 class B { |
| 8583 set sss(x) {} |
| 8584 }'''); |
| 8585 LibraryElement library = resolve2(source); |
| 8586 CompilationUnitElement unit = library.definingCompilationUnit; |
| 8587 // find "a.b.sss = 0" |
| 8588 AssignmentExpression assignment; |
| 8589 { |
| 8590 FunctionElement mainElement = unit.functions[0]; |
| 8591 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 8592 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 8593 ExpressionStatement expressionStatement = |
| 8594 statement as ExpressionStatement; |
| 8595 assignment = expressionStatement.expression as AssignmentExpression; |
| 8596 } |
| 8597 // get parameter |
| 8598 Expression rhs = assignment.rightHandSide; |
| 8599 expect(rhs.staticParameterElement, isNull); |
| 8600 ParameterElement parameter = rhs.propagatedParameterElement; |
| 8601 expect(parameter, isNotNull); |
| 8602 expect(parameter.displayName, "x"); |
| 8603 // validate |
| 8604 ClassElement classB = unit.types[1]; |
| 8605 PropertyAccessorElement setter = classB.accessors[0]; |
| 8606 expect(setter.parameters[0], same(parameter)); |
| 8607 } |
| 8608 |
| 8609 void test_argumentResolution_setter_static() { |
| 8610 Source source = addSource(r''' |
| 8611 main() { |
| 8612 A a = new A(); |
| 8613 a.sss = 0; |
| 8614 } |
| 8615 class A { |
| 8616 set sss(x) {} |
| 8617 }'''); |
| 8618 LibraryElement library = resolve2(source); |
| 8619 CompilationUnitElement unit = library.definingCompilationUnit; |
| 8620 // find "a.sss = 0" |
| 8621 AssignmentExpression assignment; |
| 8622 { |
| 8623 FunctionElement mainElement = unit.functions[0]; |
| 8624 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 8625 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 8626 ExpressionStatement expressionStatement = |
| 8627 statement as ExpressionStatement; |
| 8628 assignment = expressionStatement.expression as AssignmentExpression; |
| 8629 } |
| 8630 // get parameter |
| 8631 Expression rhs = assignment.rightHandSide; |
| 8632 ParameterElement parameter = rhs.staticParameterElement; |
| 8633 expect(parameter, isNotNull); |
| 8634 expect(parameter.displayName, "x"); |
| 8635 // validate |
| 8636 ClassElement classA = unit.types[0]; |
| 8637 PropertyAccessorElement setter = classA.accessors[0]; |
| 8638 expect(setter.parameters[0], same(parameter)); |
| 8639 } |
| 8640 |
| 8641 void test_argumentResolution_setter_static_propertyAccess() { |
| 8642 Source source = addSource(r''' |
| 8643 main() { |
| 8644 A a = new A(); |
| 8645 a.b.sss = 0; |
| 8646 } |
| 8647 class A { |
| 8648 B b = new B(); |
| 8649 } |
| 8650 class B { |
| 8651 set sss(x) {} |
| 8652 }'''); |
| 8653 LibraryElement library = resolve2(source); |
| 8654 CompilationUnitElement unit = library.definingCompilationUnit; |
| 8655 // find "a.b.sss = 0" |
| 8656 AssignmentExpression assignment; |
| 8657 { |
| 8658 FunctionElement mainElement = unit.functions[0]; |
| 8659 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 8660 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 8661 ExpressionStatement expressionStatement = |
| 8662 statement as ExpressionStatement; |
| 8663 assignment = expressionStatement.expression as AssignmentExpression; |
| 8664 } |
| 8665 // get parameter |
| 8666 Expression rhs = assignment.rightHandSide; |
| 8667 ParameterElement parameter = rhs.staticParameterElement; |
| 8668 expect(parameter, isNotNull); |
| 8669 expect(parameter.displayName, "x"); |
| 8670 // validate |
| 8671 ClassElement classB = unit.types[1]; |
| 8672 PropertyAccessorElement setter = classB.accessors[0]; |
| 8673 expect(setter.parameters[0], same(parameter)); |
| 8674 } |
| 8675 |
| 8676 void test_breakTarget_labeled() { |
| 8677 // Verify that the target of the label is correctly found and is recorded |
| 8678 // as the unlabeled portion of the statement. |
| 8679 String text = r''' |
| 8680 void f() { |
| 8681 loop1: while (true) { |
| 8682 loop2: for (int i = 0; i < 10; i++) { |
| 8683 break loop1; |
| 8684 break loop2; |
| 8685 } |
| 8686 } |
| 8687 } |
| 8688 '''; |
| 8689 CompilationUnit unit = resolveSource(text); |
| 8690 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8691 unit, text, 'while (true)', (n) => n is WhileStatement); |
| 8692 ForStatement forStatement = |
| 8693 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 8694 BreakStatement break1 = EngineTestCase.findNode( |
| 8695 unit, text, 'break loop1', (n) => n is BreakStatement); |
| 8696 BreakStatement break2 = EngineTestCase.findNode( |
| 8697 unit, text, 'break loop2', (n) => n is BreakStatement); |
| 8698 expect(break1.target, same(whileStatement)); |
| 8699 expect(break2.target, same(forStatement)); |
| 8700 } |
| 8701 |
| 8702 void test_breakTarget_unlabeledBreakFromDo() { |
| 8703 String text = r''' |
| 8704 void f() { |
| 8705 do { |
| 8706 break; |
| 8707 } while (true); |
| 8708 } |
| 8709 '''; |
| 8710 CompilationUnit unit = resolveSource(text); |
| 8711 DoStatement doStatement = |
| 8712 EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement); |
| 8713 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8714 unit, text, 'break', (n) => n is BreakStatement); |
| 8715 expect(breakStatement.target, same(doStatement)); |
| 8716 } |
| 8717 |
| 8718 void test_breakTarget_unlabeledBreakFromFor() { |
| 8719 String text = r''' |
| 8720 void f() { |
| 8721 for (int i = 0; i < 10; i++) { |
| 8722 break; |
| 8723 } |
| 8724 } |
| 8725 '''; |
| 8726 CompilationUnit unit = resolveSource(text); |
| 8727 ForStatement forStatement = |
| 8728 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 8729 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8730 unit, text, 'break', (n) => n is BreakStatement); |
| 8731 expect(breakStatement.target, same(forStatement)); |
| 8732 } |
| 8733 |
| 8734 void test_breakTarget_unlabeledBreakFromForEach() { |
| 8735 String text = r''' |
| 8736 void f() { |
| 8737 for (x in []) { |
| 8738 break; |
| 8739 } |
| 8740 } |
| 8741 '''; |
| 8742 CompilationUnit unit = resolveSource(text); |
| 8743 ForEachStatement forStatement = EngineTestCase.findNode( |
| 8744 unit, text, 'for', (n) => n is ForEachStatement); |
| 8745 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8746 unit, text, 'break', (n) => n is BreakStatement); |
| 8747 expect(breakStatement.target, same(forStatement)); |
| 8748 } |
| 8749 |
| 8750 void test_breakTarget_unlabeledBreakFromSwitch() { |
| 8751 String text = r''' |
| 8752 void f() { |
| 8753 while (true) { |
| 8754 switch (0) { |
| 8755 case 0: |
| 8756 break; |
| 8757 } |
| 8758 } |
| 8759 } |
| 8760 '''; |
| 8761 CompilationUnit unit = resolveSource(text); |
| 8762 SwitchStatement switchStatement = EngineTestCase.findNode( |
| 8763 unit, text, 'switch', (n) => n is SwitchStatement); |
| 8764 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8765 unit, text, 'break', (n) => n is BreakStatement); |
| 8766 expect(breakStatement.target, same(switchStatement)); |
| 8767 } |
| 8768 |
| 8769 void test_breakTarget_unlabeledBreakFromWhile() { |
| 8770 String text = r''' |
| 8771 void f() { |
| 8772 while (true) { |
| 8773 break; |
| 8774 } |
| 8775 } |
| 8776 '''; |
| 8777 CompilationUnit unit = resolveSource(text); |
| 8778 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8779 unit, text, 'while', (n) => n is WhileStatement); |
| 8780 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8781 unit, text, 'break', (n) => n is BreakStatement); |
| 8782 expect(breakStatement.target, same(whileStatement)); |
| 8783 } |
| 8784 |
| 8785 void test_breakTarget_unlabeledBreakToOuterFunction() { |
| 8786 // Verify that unlabeled break statements can't resolve to loops in an |
| 8787 // outer function. |
| 8788 String text = r''' |
| 8789 void f() { |
| 8790 while (true) { |
| 8791 void g() { |
| 8792 break; |
| 8793 } |
| 8794 } |
| 8795 } |
| 8796 '''; |
| 8797 CompilationUnit unit = resolveSource(text); |
| 8798 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8799 unit, text, 'break', (n) => n is BreakStatement); |
| 8800 expect(breakStatement.target, isNull); |
| 8801 } |
| 8802 |
| 8803 void test_class_definesCall() { |
| 8804 Source source = addSource(r''' |
| 8805 class A { |
| 8806 int call(int x) { return x; } |
| 8807 } |
| 8808 int f(A a) { |
| 8809 return a(0); |
| 8810 }'''); |
| 8811 computeLibrarySourceErrors(source); |
| 8812 assertNoErrors(source); |
| 8813 verify([source]); |
| 8814 } |
| 8815 |
| 8816 void test_class_extends_implements() { |
| 8817 Source source = addSource(r''' |
| 8818 class A extends B implements C {} |
| 8819 class B {} |
| 8820 class C {}'''); |
| 8821 computeLibrarySourceErrors(source); |
| 8822 assertNoErrors(source); |
| 8823 verify([source]); |
| 8824 } |
| 8825 |
| 8826 void test_commentReference_class() { |
| 8827 Source source = addSource(r''' |
| 8828 f() {} |
| 8829 /** [A] [new A] [A.n] [new A.n] [m] [f] */ |
| 8830 class A { |
| 8831 A() {} |
| 8832 A.n() {} |
| 8833 m() {} |
| 8834 }'''); |
| 8835 computeLibrarySourceErrors(source); |
| 8836 assertNoErrors(source); |
| 8837 verify([source]); |
| 8838 } |
| 8839 |
| 8840 void test_commentReference_parameter() { |
| 8841 Source source = addSource(r''' |
| 8842 class A { |
| 8843 A() {} |
| 8844 A.n() {} |
| 8845 /** [e] [f] */ |
| 8846 m(e, f()) {} |
| 8847 }'''); |
| 8848 computeLibrarySourceErrors(source); |
| 8849 assertNoErrors(source); |
| 8850 verify([source]); |
| 8851 } |
| 8852 |
| 8853 void test_commentReference_singleLine() { |
| 8854 Source source = addSource(r''' |
| 8855 /// [A] |
| 8856 class A {}'''); |
| 8857 computeLibrarySourceErrors(source); |
| 8858 assertNoErrors(source); |
| 8859 verify([source]); |
| 8860 } |
| 8861 |
| 8862 void test_continueTarget_labeled() { |
| 8863 // Verify that the target of the label is correctly found and is recorded |
| 8864 // as the unlabeled portion of the statement. |
| 8865 String text = r''' |
| 8866 void f() { |
| 8867 loop1: while (true) { |
| 8868 loop2: for (int i = 0; i < 10; i++) { |
| 8869 continue loop1; |
| 8870 continue loop2; |
| 8871 } |
| 8872 } |
| 8873 } |
| 8874 '''; |
| 8875 CompilationUnit unit = resolveSource(text); |
| 8876 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8877 unit, text, 'while (true)', (n) => n is WhileStatement); |
| 8878 ForStatement forStatement = |
| 8879 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 8880 ContinueStatement continue1 = EngineTestCase.findNode( |
| 8881 unit, text, 'continue loop1', (n) => n is ContinueStatement); |
| 8882 ContinueStatement continue2 = EngineTestCase.findNode( |
| 8883 unit, text, 'continue loop2', (n) => n is ContinueStatement); |
| 8884 expect(continue1.target, same(whileStatement)); |
| 8885 expect(continue2.target, same(forStatement)); |
| 8886 } |
| 8887 |
| 8888 void test_continueTarget_unlabeledContinueFromDo() { |
| 8889 String text = r''' |
| 8890 void f() { |
| 8891 do { |
| 8892 continue; |
| 8893 } while (true); |
| 8894 } |
| 8895 '''; |
| 8896 CompilationUnit unit = resolveSource(text); |
| 8897 DoStatement doStatement = |
| 8898 EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement); |
| 8899 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8900 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8901 expect(continueStatement.target, same(doStatement)); |
| 8902 } |
| 8903 |
| 8904 void test_continueTarget_unlabeledContinueFromFor() { |
| 8905 String text = r''' |
| 8906 void f() { |
| 8907 for (int i = 0; i < 10; i++) { |
| 8908 continue; |
| 8909 } |
| 8910 } |
| 8911 '''; |
| 8912 CompilationUnit unit = resolveSource(text); |
| 8913 ForStatement forStatement = |
| 8914 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 8915 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8916 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8917 expect(continueStatement.target, same(forStatement)); |
| 8918 } |
| 8919 |
| 8920 void test_continueTarget_unlabeledContinueFromForEach() { |
| 8921 String text = r''' |
| 8922 void f() { |
| 8923 for (x in []) { |
| 8924 continue; |
| 8925 } |
| 8926 } |
| 8927 '''; |
| 8928 CompilationUnit unit = resolveSource(text); |
| 8929 ForEachStatement forStatement = EngineTestCase.findNode( |
| 8930 unit, text, 'for', (n) => n is ForEachStatement); |
| 8931 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8932 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8933 expect(continueStatement.target, same(forStatement)); |
| 8934 } |
| 8935 |
| 8936 void test_continueTarget_unlabeledContinueFromWhile() { |
| 8937 String text = r''' |
| 8938 void f() { |
| 8939 while (true) { |
| 8940 continue; |
| 8941 } |
| 8942 } |
| 8943 '''; |
| 8944 CompilationUnit unit = resolveSource(text); |
| 8945 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8946 unit, text, 'while', (n) => n is WhileStatement); |
| 8947 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8948 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8949 expect(continueStatement.target, same(whileStatement)); |
| 8950 } |
| 8951 |
| 8952 void test_continueTarget_unlabeledContinueSkipsSwitch() { |
| 8953 String text = r''' |
| 8954 void f() { |
| 8955 while (true) { |
| 8956 switch (0) { |
| 8957 case 0: |
| 8958 continue; |
| 8959 } |
| 8960 } |
| 8961 } |
| 8962 '''; |
| 8963 CompilationUnit unit = resolveSource(text); |
| 8964 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8965 unit, text, 'while', (n) => n is WhileStatement); |
| 8966 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8967 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8968 expect(continueStatement.target, same(whileStatement)); |
| 8969 } |
| 8970 |
| 8971 void test_continueTarget_unlabeledContinueToOuterFunction() { |
| 8972 // Verify that unlabeled continue statements can't resolve to loops in an |
| 8973 // outer function. |
| 8974 String text = r''' |
| 8975 void f() { |
| 8976 while (true) { |
| 8977 void g() { |
| 8978 continue; |
| 8979 } |
| 8980 } |
| 8981 } |
| 8982 '''; |
| 8983 CompilationUnit unit = resolveSource(text); |
| 8984 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8985 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8986 expect(continueStatement.target, isNull); |
| 8987 } |
| 8988 |
| 8989 void test_empty() { |
| 8990 Source source = addSource(""); |
| 8991 computeLibrarySourceErrors(source); |
| 8992 assertNoErrors(source); |
| 8993 verify([source]); |
| 8994 } |
| 8995 |
| 8996 void test_entryPoint_exported() { |
| 8997 addNamedSource( |
| 8998 "/two.dart", |
| 8999 r''' |
| 9000 library two; |
| 9001 main() {}'''); |
| 9002 Source source = addNamedSource( |
| 9003 "/one.dart", |
| 9004 r''' |
| 9005 library one; |
| 9006 export 'two.dart';'''); |
| 9007 LibraryElement library = resolve2(source); |
| 9008 expect(library, isNotNull); |
| 9009 FunctionElement main = library.entryPoint; |
| 9010 expect(main, isNotNull); |
| 9011 expect(main.library, isNot(same(library))); |
| 9012 assertNoErrors(source); |
| 9013 verify([source]); |
| 9014 } |
| 9015 |
| 9016 void test_entryPoint_local() { |
| 9017 Source source = addNamedSource( |
| 9018 "/one.dart", |
| 9019 r''' |
| 9020 library one; |
| 9021 main() {}'''); |
| 9022 LibraryElement library = resolve2(source); |
| 9023 expect(library, isNotNull); |
| 9024 FunctionElement main = library.entryPoint; |
| 9025 expect(main, isNotNull); |
| 9026 expect(main.library, same(library)); |
| 9027 assertNoErrors(source); |
| 9028 verify([source]); |
| 9029 } |
| 9030 |
| 9031 void test_entryPoint_none() { |
| 9032 Source source = addNamedSource("/one.dart", "library one;"); |
| 9033 LibraryElement library = resolve2(source); |
| 9034 expect(library, isNotNull); |
| 9035 expect(library.entryPoint, isNull); |
| 9036 assertNoErrors(source); |
| 9037 verify([source]); |
| 9038 } |
| 9039 |
| 9040 void test_enum_externalLibrary() { |
| 9041 addNamedSource( |
| 9042 "/my_lib.dart", |
| 9043 r''' |
| 9044 library my_lib; |
| 9045 enum EEE {A, B, C}'''); |
| 9046 Source source = addSource(r''' |
| 9047 import 'my_lib.dart'; |
| 9048 main() { |
| 9049 EEE e = null; |
| 9050 }'''); |
| 9051 computeLibrarySourceErrors(source); |
| 9052 assertNoErrors(source); |
| 9053 verify([source]); |
| 9054 } |
| 9055 |
| 9056 void test_extractedMethodAsConstant() { |
| 9057 Source source = addSource(r''' |
| 9058 abstract class Comparable<T> { |
| 9059 int compareTo(T other); |
| 9060 static int compare(Comparable a, Comparable b) => a.compareTo(b); |
| 9061 } |
| 9062 class A { |
| 9063 void sort([compare = Comparable.compare]) {} |
| 9064 }'''); |
| 9065 computeLibrarySourceErrors(source); |
| 9066 assertNoErrors(source); |
| 9067 verify([source]); |
| 9068 } |
| 9069 |
| 9070 void test_fieldFormalParameter() { |
| 9071 Source source = addSource(r''' |
| 9072 class A { |
| 9073 int x; |
| 9074 A(this.x) {} |
| 9075 }'''); |
| 9076 computeLibrarySourceErrors(source); |
| 9077 assertNoErrors(source); |
| 9078 verify([source]); |
| 9079 } |
| 9080 |
| 9081 void test_forEachLoops_nonConflicting() { |
| 9082 Source source = addSource(r''' |
| 9083 f() { |
| 9084 List list = [1,2,3]; |
| 9085 for (int x in list) {} |
| 9086 for (int x in list) {} |
| 9087 }'''); |
| 9088 computeLibrarySourceErrors(source); |
| 9089 assertNoErrors(source); |
| 9090 verify([source]); |
| 9091 } |
| 9092 |
| 9093 void test_forLoops_nonConflicting() { |
| 9094 Source source = addSource(r''' |
| 9095 f() { |
| 9096 for (int i = 0; i < 3; i++) { |
| 9097 } |
| 9098 for (int i = 0; i < 3; i++) { |
| 9099 } |
| 9100 }'''); |
| 9101 computeLibrarySourceErrors(source); |
| 9102 assertNoErrors(source); |
| 9103 verify([source]); |
| 9104 } |
| 9105 |
| 9106 void test_functionTypeAlias() { |
| 9107 Source source = addSource(r''' |
| 9108 typedef bool P(e); |
| 9109 class A { |
| 9110 P p; |
| 9111 m(e) { |
| 9112 if (p(e)) {} |
| 9113 } |
| 9114 }'''); |
| 9115 computeLibrarySourceErrors(source); |
| 9116 assertNoErrors(source); |
| 9117 verify([source]); |
| 9118 } |
| 9119 |
| 9120 void test_getter_and_setter_fromMixins_bare_identifier() { |
| 9121 Source source = addSource(''' |
| 9122 class B {} |
| 9123 class M1 { |
| 9124 get x => null; |
| 9125 set x(value) {} |
| 9126 } |
| 9127 class M2 { |
| 9128 get x => null; |
| 9129 set x(value) {} |
| 9130 } |
| 9131 class C extends B with M1, M2 { |
| 9132 void f() { |
| 9133 x += 1; |
| 9134 } |
| 9135 } |
| 9136 '''); |
| 9137 LibraryElement library = resolve2(source); |
| 9138 assertNoErrors(source); |
| 9139 verify([source]); |
| 9140 // Verify that both the getter and setter for "x" in C.f() refer to the |
| 9141 // accessors defined in M2. |
| 9142 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 9143 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 9144 BlockFunctionBody body = f.body; |
| 9145 ExpressionStatement stmt = body.block.statements[0]; |
| 9146 AssignmentExpression assignment = stmt.expression; |
| 9147 SimpleIdentifier leftHandSide = assignment.leftHandSide; |
| 9148 expect(leftHandSide.staticElement.enclosingElement.name, 'M2'); |
| 9149 expect(leftHandSide.auxiliaryElements.staticElement.enclosingElement.name, |
| 9150 'M2'); |
| 9151 } |
| 9152 |
| 9153 void test_getter_fromMixins_bare_identifier() { |
| 9154 Source source = addSource(''' |
| 9155 class B {} |
| 9156 class M1 { |
| 9157 get x => null; |
| 9158 } |
| 9159 class M2 { |
| 9160 get x => null; |
| 9161 } |
| 9162 class C extends B with M1, M2 { |
| 9163 f() { |
| 9164 return x; |
| 9165 } |
| 9166 } |
| 9167 '''); |
| 9168 LibraryElement library = resolve2(source); |
| 9169 assertNoErrors(source); |
| 9170 verify([source]); |
| 9171 // Verify that the getter for "x" in C.f() refers to the getter defined in |
| 9172 // M2. |
| 9173 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 9174 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 9175 BlockFunctionBody body = f.body; |
| 9176 ReturnStatement stmt = body.block.statements[0]; |
| 9177 SimpleIdentifier x = stmt.expression; |
| 9178 expect(x.staticElement.enclosingElement.name, 'M2'); |
| 9179 } |
| 9180 |
| 9181 void test_getter_fromMixins_property_access() { |
| 9182 Source source = addSource(''' |
| 9183 class B {} |
| 9184 class M1 { |
| 9185 get x => null; |
| 9186 } |
| 9187 class M2 { |
| 9188 get x => null; |
| 9189 } |
| 9190 class C extends B with M1, M2 {} |
| 9191 void main() { |
| 9192 var y = new C().x; |
| 9193 } |
| 9194 '''); |
| 9195 LibraryElement library = resolve2(source); |
| 9196 assertNoErrors(source); |
| 9197 verify([source]); |
| 9198 // Verify that the getter for "x" in "new C().x" refers to the getter |
| 9199 // defined in M2. |
| 9200 FunctionDeclaration main = |
| 9201 library.definingCompilationUnit.functions[0].computeNode(); |
| 9202 BlockFunctionBody body = main.functionExpression.body; |
| 9203 VariableDeclarationStatement stmt = body.block.statements[0]; |
| 9204 PropertyAccess propertyAccess = stmt.variables.variables[0].initializer; |
| 9205 expect( |
| 9206 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 9207 } |
| 9208 |
| 9209 void test_getterAndSetterWithDifferentTypes() { |
| 9210 Source source = addSource(r''' |
| 9211 class A { |
| 9212 int get f => 0; |
| 9213 void set f(String s) {} |
| 9214 } |
| 9215 g (A a) { |
| 9216 a.f = a.f.toString(); |
| 9217 }'''); |
| 9218 computeLibrarySourceErrors(source); |
| 9219 assertErrors( |
| 9220 source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]); |
| 9221 verify([source]); |
| 9222 } |
| 9223 |
| 9224 void test_hasReferenceToSuper() { |
| 9225 Source source = addSource(r''' |
| 9226 class A {} |
| 9227 class B {toString() => super.toString();}'''); |
| 9228 LibraryElement library = resolve2(source); |
| 9229 expect(library, isNotNull); |
| 9230 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9231 expect(unit, isNotNull); |
| 9232 List<ClassElement> classes = unit.types; |
| 9233 expect(classes, hasLength(2)); |
| 9234 expect(classes[0].hasReferenceToSuper, isFalse); |
| 9235 expect(classes[1].hasReferenceToSuper, isTrue); |
| 9236 assertNoErrors(source); |
| 9237 verify([source]); |
| 9238 } |
| 9239 |
| 9240 void test_import_hide() { |
| 9241 addNamedSource( |
| 9242 "/lib1.dart", |
| 9243 r''' |
| 9244 library lib1; |
| 9245 set foo(value) {} |
| 9246 class A {}'''); |
| 9247 addNamedSource( |
| 9248 "/lib2.dart", |
| 9249 r''' |
| 9250 library lib2; |
| 9251 set foo(value) {}'''); |
| 9252 Source source = addNamedSource( |
| 9253 "/lib3.dart", |
| 9254 r''' |
| 9255 import 'lib1.dart' hide foo; |
| 9256 import 'lib2.dart'; |
| 9257 |
| 9258 main() { |
| 9259 foo = 0; |
| 9260 } |
| 9261 A a;'''); |
| 9262 computeLibrarySourceErrors(source); |
| 9263 assertNoErrors(source); |
| 9264 verify([source]); |
| 9265 } |
| 9266 |
| 9267 void test_import_prefix() { |
| 9268 addNamedSource( |
| 9269 "/two.dart", |
| 9270 r''' |
| 9271 library two; |
| 9272 f(int x) { |
| 9273 return x * x; |
| 9274 }'''); |
| 9275 Source source = addNamedSource( |
| 9276 "/one.dart", |
| 9277 r''' |
| 9278 library one; |
| 9279 import 'two.dart' as _two; |
| 9280 main() { |
| 9281 _two.f(0); |
| 9282 }'''); |
| 9283 computeLibrarySourceErrors(source); |
| 9284 assertNoErrors(source); |
| 9285 verify([source]); |
| 9286 } |
| 9287 |
| 9288 void test_import_spaceInUri() { |
| 9289 addNamedSource( |
| 9290 "/sub folder/lib.dart", |
| 9291 r''' |
| 9292 library lib; |
| 9293 foo() {}'''); |
| 9294 Source source = addNamedSource( |
| 9295 "/app.dart", |
| 9296 r''' |
| 9297 import 'sub folder/lib.dart'; |
| 9298 |
| 9299 main() { |
| 9300 foo(); |
| 9301 }'''); |
| 9302 computeLibrarySourceErrors(source); |
| 9303 assertNoErrors(source); |
| 9304 verify([source]); |
| 9305 } |
| 9306 |
| 9307 void test_indexExpression_typeParameters() { |
| 9308 Source source = addSource(r''' |
| 9309 f() { |
| 9310 List<int> a; |
| 9311 a[0]; |
| 9312 List<List<int>> b; |
| 9313 b[0][0]; |
| 9314 List<List<List<int>>> c; |
| 9315 c[0][0][0]; |
| 9316 }'''); |
| 9317 computeLibrarySourceErrors(source); |
| 9318 assertNoErrors(source); |
| 9319 verify([source]); |
| 9320 } |
| 9321 |
| 9322 void test_indexExpression_typeParameters_invalidAssignmentWarning() { |
| 9323 Source source = addSource(r''' |
| 9324 f() { |
| 9325 List<List<int>> b; |
| 9326 b[0][0] = 'hi'; |
| 9327 }'''); |
| 9328 computeLibrarySourceErrors(source); |
| 9329 assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); |
| 9330 verify([source]); |
| 9331 } |
| 9332 |
| 9333 void test_indirectOperatorThroughCall() { |
| 9334 Source source = addSource(r''' |
| 9335 class A { |
| 9336 B call() { return new B(); } |
| 9337 } |
| 9338 |
| 9339 class B { |
| 9340 int operator [](int i) { return i; } |
| 9341 } |
| 9342 |
| 9343 A f = new A(); |
| 9344 |
| 9345 g(int x) {} |
| 9346 |
| 9347 main() { |
| 9348 g(f()[0]); |
| 9349 }'''); |
| 9350 computeLibrarySourceErrors(source); |
| 9351 assertNoErrors(source); |
| 9352 verify([source]); |
| 9353 } |
| 9354 |
| 9355 void test_invoke_dynamicThroughGetter() { |
| 9356 Source source = addSource(r''' |
| 9357 class A { |
| 9358 List get X => [() => 0]; |
| 9359 m(A a) { |
| 9360 X.last; |
| 9361 } |
| 9362 }'''); |
| 9363 computeLibrarySourceErrors(source); |
| 9364 assertNoErrors(source); |
| 9365 verify([source]); |
| 9366 } |
| 9367 |
| 9368 void test_isValidMixin_badSuperclass() { |
| 9369 Source source = addSource(r''' |
| 9370 class A extends B {} |
| 9371 class B {}'''); |
| 9372 LibraryElement library = resolve2(source); |
| 9373 expect(library, isNotNull); |
| 9374 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9375 expect(unit, isNotNull); |
| 9376 List<ClassElement> classes = unit.types; |
| 9377 expect(classes, hasLength(2)); |
| 9378 expect(classes[0].isValidMixin, isFalse); |
| 9379 assertNoErrors(source); |
| 9380 verify([source]); |
| 9381 } |
| 9382 |
| 9383 void test_isValidMixin_constructor() { |
| 9384 Source source = addSource(r''' |
| 9385 class A { |
| 9386 A() {} |
| 9387 }'''); |
| 9388 LibraryElement library = resolve2(source); |
| 9389 expect(library, isNotNull); |
| 9390 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9391 expect(unit, isNotNull); |
| 9392 List<ClassElement> classes = unit.types; |
| 9393 expect(classes, hasLength(1)); |
| 9394 expect(classes[0].isValidMixin, isFalse); |
| 9395 assertNoErrors(source); |
| 9396 verify([source]); |
| 9397 } |
| 9398 |
| 9399 void test_isValidMixin_super() { |
| 9400 Source source = addSource(r''' |
| 9401 class A { |
| 9402 toString() { |
| 9403 return super.toString(); |
| 9404 } |
| 9405 }'''); |
| 9406 LibraryElement library = resolve2(source); |
| 9407 expect(library, isNotNull); |
| 9408 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9409 expect(unit, isNotNull); |
| 9410 List<ClassElement> classes = unit.types; |
| 9411 expect(classes, hasLength(1)); |
| 9412 expect(classes[0].isValidMixin, isFalse); |
| 9413 assertNoErrors(source); |
| 9414 verify([source]); |
| 9415 } |
| 9416 |
| 9417 void test_isValidMixin_valid() { |
| 9418 Source source = addSource("class A {}"); |
| 9419 LibraryElement library = resolve2(source); |
| 9420 expect(library, isNotNull); |
| 9421 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9422 expect(unit, isNotNull); |
| 9423 List<ClassElement> classes = unit.types; |
| 9424 expect(classes, hasLength(1)); |
| 9425 expect(classes[0].isValidMixin, isTrue); |
| 9426 assertNoErrors(source); |
| 9427 verify([source]); |
| 9428 } |
| 9429 |
| 9430 void test_labels_switch() { |
| 9431 Source source = addSource(r''' |
| 9432 void doSwitch(int target) { |
| 9433 switch (target) { |
| 9434 l0: case 0: |
| 9435 continue l1; |
| 9436 l1: case 1: |
| 9437 continue l0; |
| 9438 default: |
| 9439 continue l1; |
| 9440 } |
| 9441 }'''); |
| 9442 LibraryElement library = resolve2(source); |
| 9443 expect(library, isNotNull); |
| 9444 assertNoErrors(source); |
| 9445 verify([source]); |
| 9446 } |
| 9447 |
| 9448 void test_localVariable_types_invoked() { |
| 9449 Source source = addSource(r''' |
| 9450 const A = null; |
| 9451 main() { |
| 9452 var myVar = (int p) => 'foo'; |
| 9453 myVar(42); |
| 9454 }'''); |
| 9455 LibraryElement library = resolve2(source); |
| 9456 expect(library, isNotNull); |
| 9457 CompilationUnit unit = |
| 9458 analysisContext.resolveCompilationUnit(source, library); |
| 9459 expect(unit, isNotNull); |
| 9460 List<bool> found = [false]; |
| 9461 List<CaughtException> thrownException = new List<CaughtException>(1); |
| 9462 unit.accept(new _SimpleResolverTest_localVariable_types_invoked( |
| 9463 this, found, thrownException)); |
| 9464 if (thrownException[0] != null) { |
| 9465 throw new AnalysisException( |
| 9466 "Exception", new CaughtException(thrownException[0], null)); |
| 9467 } |
| 9468 expect(found[0], isTrue); |
| 9469 } |
| 9470 |
| 9471 void test_metadata_class() { |
| 9472 Source source = addSource(r''' |
| 9473 const A = null; |
| 9474 @A class C<A> {}'''); |
| 9475 LibraryElement library = resolve2(source); |
| 9476 expect(library, isNotNull); |
| 9477 CompilationUnitElement unitElement = library.definingCompilationUnit; |
| 9478 expect(unitElement, isNotNull); |
| 9479 List<ClassElement> classes = unitElement.types; |
| 9480 expect(classes, hasLength(1)); |
| 9481 List<ElementAnnotation> annotations = classes[0].metadata; |
| 9482 expect(annotations, hasLength(1)); |
| 9483 assertNoErrors(source); |
| 9484 verify([source]); |
| 9485 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 9486 NodeList<CompilationUnitMember> declarations = unit.declarations; |
| 9487 expect(declarations, hasLength(2)); |
| 9488 Element expectedElement = (declarations[0] as TopLevelVariableDeclaration) |
| 9489 .variables |
| 9490 .variables[0].name.staticElement; |
| 9491 EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement, |
| 9492 PropertyInducingElement, expectedElement); |
| 9493 expectedElement = (expectedElement as PropertyInducingElement).getter; |
| 9494 Element actualElement = |
| 9495 (declarations[1] as ClassDeclaration).metadata[0].name.staticElement; |
| 9496 expect(actualElement, same(expectedElement)); |
| 9497 } |
| 9498 |
| 9499 void test_metadata_field() { |
| 9500 Source source = addSource(r''' |
| 9501 const A = null; |
| 9502 class C { |
| 9503 @A int f; |
| 9504 }'''); |
| 9505 LibraryElement library = resolve2(source); |
| 9506 expect(library, isNotNull); |
| 9507 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9508 expect(unit, isNotNull); |
| 9509 List<ClassElement> classes = unit.types; |
| 9510 expect(classes, hasLength(1)); |
| 9511 FieldElement field = classes[0].fields[0]; |
| 9512 List<ElementAnnotation> annotations = field.metadata; |
| 9513 expect(annotations, hasLength(1)); |
| 9514 assertNoErrors(source); |
| 9515 verify([source]); |
| 9516 } |
| 9517 |
| 9518 void test_metadata_fieldFormalParameter() { |
| 9519 Source source = addSource(r''' |
| 9520 const A = null; |
| 9521 class C { |
| 9522 int f; |
| 9523 C(@A this.f); |
| 9524 }'''); |
| 9525 LibraryElement library = resolve2(source); |
| 9526 expect(library, isNotNull); |
| 9527 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9528 expect(unit, isNotNull); |
| 9529 List<ClassElement> classes = unit.types; |
| 9530 expect(classes, hasLength(1)); |
| 9531 List<ConstructorElement> constructors = classes[0].constructors; |
| 9532 expect(constructors, hasLength(1)); |
| 9533 List<ParameterElement> parameters = constructors[0].parameters; |
| 9534 expect(parameters, hasLength(1)); |
| 9535 List<ElementAnnotation> annotations = parameters[0].metadata; |
| 9536 expect(annotations, hasLength(1)); |
| 9537 assertNoErrors(source); |
| 9538 verify([source]); |
| 9539 } |
| 9540 |
| 9541 void test_metadata_function() { |
| 9542 Source source = addSource(r''' |
| 9543 const A = null; |
| 9544 @A f() {}'''); |
| 9545 LibraryElement library = resolve2(source); |
| 9546 expect(library, isNotNull); |
| 9547 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9548 expect(unit, isNotNull); |
| 9549 List<FunctionElement> functions = unit.functions; |
| 9550 expect(functions, hasLength(1)); |
| 9551 List<ElementAnnotation> annotations = functions[0].metadata; |
| 9552 expect(annotations, hasLength(1)); |
| 9553 assertNoErrors(source); |
| 9554 verify([source]); |
| 9555 } |
| 9556 |
| 9557 void test_metadata_functionTypedParameter() { |
| 9558 Source source = addSource(r''' |
| 9559 const A = null; |
| 9560 f(@A int p(int x)) {}'''); |
| 9561 LibraryElement library = resolve2(source); |
| 9562 expect(library, isNotNull); |
| 9563 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9564 expect(unit, isNotNull); |
| 9565 List<FunctionElement> functions = unit.functions; |
| 9566 expect(functions, hasLength(1)); |
| 9567 List<ParameterElement> parameters = functions[0].parameters; |
| 9568 expect(parameters, hasLength(1)); |
| 9569 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 9570 expect(annotations1, hasLength(1)); |
| 9571 assertNoErrors(source); |
| 9572 verify([source]); |
| 9573 } |
| 9574 |
| 9575 void test_metadata_libraryDirective() { |
| 9576 Source source = addSource(r''' |
| 9577 @A library lib; |
| 9578 const A = null;'''); |
| 9579 LibraryElement library = resolve2(source); |
| 9580 expect(library, isNotNull); |
| 9581 List<ElementAnnotation> annotations = library.metadata; |
| 9582 expect(annotations, hasLength(1)); |
| 9583 assertNoErrors(source); |
| 9584 verify([source]); |
| 9585 } |
| 9586 |
| 9587 void test_metadata_method() { |
| 9588 Source source = addSource(r''' |
| 9589 const A = null; |
| 9590 class C { |
| 9591 @A void m() {} |
| 9592 }'''); |
| 9593 LibraryElement library = resolve2(source); |
| 9594 expect(library, isNotNull); |
| 9595 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9596 expect(unit, isNotNull); |
| 9597 List<ClassElement> classes = unit.types; |
| 9598 expect(classes, hasLength(1)); |
| 9599 MethodElement method = classes[0].methods[0]; |
| 9600 List<ElementAnnotation> annotations = method.metadata; |
| 9601 expect(annotations, hasLength(1)); |
| 9602 assertNoErrors(source); |
| 9603 verify([source]); |
| 9604 } |
| 9605 |
| 9606 void test_metadata_namedParameter() { |
| 9607 Source source = addSource(r''' |
| 9608 const A = null; |
| 9609 f({@A int p : 0}) {}'''); |
| 9610 LibraryElement library = resolve2(source); |
| 9611 expect(library, isNotNull); |
| 9612 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9613 expect(unit, isNotNull); |
| 9614 List<FunctionElement> functions = unit.functions; |
| 9615 expect(functions, hasLength(1)); |
| 9616 List<ParameterElement> parameters = functions[0].parameters; |
| 9617 expect(parameters, hasLength(1)); |
| 9618 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 9619 expect(annotations1, hasLength(1)); |
| 9620 assertNoErrors(source); |
| 9621 verify([source]); |
| 9622 } |
| 9623 |
| 9624 void test_metadata_positionalParameter() { |
| 9625 Source source = addSource(r''' |
| 9626 const A = null; |
| 9627 f([@A int p = 0]) {}'''); |
| 9628 LibraryElement library = resolve2(source); |
| 9629 expect(library, isNotNull); |
| 9630 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9631 expect(unit, isNotNull); |
| 9632 List<FunctionElement> functions = unit.functions; |
| 9633 expect(functions, hasLength(1)); |
| 9634 List<ParameterElement> parameters = functions[0].parameters; |
| 9635 expect(parameters, hasLength(1)); |
| 9636 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 9637 expect(annotations1, hasLength(1)); |
| 9638 assertNoErrors(source); |
| 9639 verify([source]); |
| 9640 } |
| 9641 |
| 9642 void test_metadata_simpleParameter() { |
| 9643 Source source = addSource(r''' |
| 9644 const A = null; |
| 9645 f(@A p1, @A int p2) {}'''); |
| 9646 LibraryElement library = resolve2(source); |
| 9647 expect(library, isNotNull); |
| 9648 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9649 expect(unit, isNotNull); |
| 9650 List<FunctionElement> functions = unit.functions; |
| 9651 expect(functions, hasLength(1)); |
| 9652 List<ParameterElement> parameters = functions[0].parameters; |
| 9653 expect(parameters, hasLength(2)); |
| 9654 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 9655 expect(annotations1, hasLength(1)); |
| 9656 List<ElementAnnotation> annotations2 = parameters[1].metadata; |
| 9657 expect(annotations2, hasLength(1)); |
| 9658 assertNoErrors(source); |
| 9659 verify([source]); |
| 9660 } |
| 9661 |
| 9662 void test_metadata_typedef() { |
| 9663 Source source = addSource(r''' |
| 9664 const A = null; |
| 9665 @A typedef F<A>();'''); |
| 9666 LibraryElement library = resolve2(source); |
| 9667 expect(library, isNotNull); |
| 9668 CompilationUnitElement unitElement = library.definingCompilationUnit; |
| 9669 expect(unitElement, isNotNull); |
| 9670 List<FunctionTypeAliasElement> aliases = unitElement.functionTypeAliases; |
| 9671 expect(aliases, hasLength(1)); |
| 9672 List<ElementAnnotation> annotations = aliases[0].metadata; |
| 9673 expect(annotations, hasLength(1)); |
| 9674 assertNoErrors(source); |
| 9675 verify([source]); |
| 9676 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 9677 NodeList<CompilationUnitMember> declarations = unit.declarations; |
| 9678 expect(declarations, hasLength(2)); |
| 9679 Element expectedElement = (declarations[0] as TopLevelVariableDeclaration) |
| 9680 .variables |
| 9681 .variables[0].name.staticElement; |
| 9682 EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement, |
| 9683 PropertyInducingElement, expectedElement); |
| 9684 expectedElement = (expectedElement as PropertyInducingElement).getter; |
| 9685 Element actualElement = |
| 9686 (declarations[1] as FunctionTypeAlias).metadata[0].name.staticElement; |
| 9687 expect(actualElement, same(expectedElement)); |
| 9688 } |
| 9689 |
| 9690 void test_method_fromMixin() { |
| 9691 Source source = addSource(r''' |
| 9692 class B { |
| 9693 bar() => 1; |
| 9694 } |
| 9695 class A { |
| 9696 foo() => 2; |
| 9697 } |
| 9698 |
| 9699 class C extends B with A { |
| 9700 bar() => super.bar(); |
| 9701 foo() => super.foo(); |
| 9702 }'''); |
| 9703 computeLibrarySourceErrors(source); |
| 9704 assertNoErrors(source); |
| 9705 verify([source]); |
| 9706 } |
| 9707 |
| 9708 void test_method_fromMixins() { |
| 9709 Source source = addSource(''' |
| 9710 class B {} |
| 9711 class M1 { |
| 9712 void f() {} |
| 9713 } |
| 9714 class M2 { |
| 9715 void f() {} |
| 9716 } |
| 9717 class C extends B with M1, M2 {} |
| 9718 void main() { |
| 9719 new C().f(); |
| 9720 } |
| 9721 '''); |
| 9722 LibraryElement library = resolve2(source); |
| 9723 assertNoErrors(source); |
| 9724 verify([source]); |
| 9725 // Verify that the "f" in "new C().f()" refers to the "f" defined in M2. |
| 9726 FunctionDeclaration main = |
| 9727 library.definingCompilationUnit.functions[0].computeNode(); |
| 9728 BlockFunctionBody body = main.functionExpression.body; |
| 9729 ExpressionStatement stmt = body.block.statements[0]; |
| 9730 MethodInvocation expr = stmt.expression; |
| 9731 expect(expr.methodName.staticElement.enclosingElement.name, 'M2'); |
| 9732 } |
| 9733 |
| 9734 void test_method_fromMixins_bare_identifier() { |
| 9735 Source source = addSource(''' |
| 9736 class B {} |
| 9737 class M1 { |
| 9738 void f() {} |
| 9739 } |
| 9740 class M2 { |
| 9741 void f() {} |
| 9742 } |
| 9743 class C extends B with M1, M2 { |
| 9744 void g() { |
| 9745 f(); |
| 9746 } |
| 9747 } |
| 9748 '''); |
| 9749 LibraryElement library = resolve2(source); |
| 9750 assertNoErrors(source); |
| 9751 verify([source]); |
| 9752 // Verify that the call to f() in C.g() refers to the method defined in M2. |
| 9753 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 9754 MethodDeclaration g = classC.getMethod('g').computeNode(); |
| 9755 BlockFunctionBody body = g.body; |
| 9756 ExpressionStatement stmt = body.block.statements[0]; |
| 9757 MethodInvocation invocation = stmt.expression; |
| 9758 SimpleIdentifier methodName = invocation.methodName; |
| 9759 expect(methodName.staticElement.enclosingElement.name, 'M2'); |
| 9760 } |
| 9761 |
| 9762 void test_method_fromMixins_invked_from_outside_class() { |
| 9763 Source source = addSource(''' |
| 9764 class B {} |
| 9765 class M1 { |
| 9766 void f() {} |
| 9767 } |
| 9768 class M2 { |
| 9769 void f() {} |
| 9770 } |
| 9771 class C extends B with M1, M2 {} |
| 9772 void main() { |
| 9773 new C().f(); |
| 9774 } |
| 9775 '''); |
| 9776 LibraryElement library = resolve2(source); |
| 9777 assertNoErrors(source); |
| 9778 verify([source]); |
| 9779 // Verify that the call to f() in "new C().f()" refers to the method |
| 9780 // defined in M2. |
| 9781 FunctionDeclaration main = |
| 9782 library.definingCompilationUnit.functions[0].computeNode(); |
| 9783 BlockFunctionBody body = main.functionExpression.body; |
| 9784 ExpressionStatement stmt = body.block.statements[0]; |
| 9785 MethodInvocation invocation = stmt.expression; |
| 9786 expect(invocation.methodName.staticElement.enclosingElement.name, 'M2'); |
| 9787 } |
| 9788 |
| 9789 void test_method_fromSuperclassMixin() { |
| 9790 Source source = addSource(r''' |
| 9791 class A { |
| 9792 void m1() {} |
| 9793 } |
| 9794 class B extends Object with A { |
| 9795 } |
| 9796 class C extends B { |
| 9797 } |
| 9798 f(C c) { |
| 9799 c.m1(); |
| 9800 }'''); |
| 9801 computeLibrarySourceErrors(source); |
| 9802 assertNoErrors(source); |
| 9803 verify([source]); |
| 9804 } |
| 9805 |
| 9806 void test_methodCascades() { |
| 9807 Source source = addSource(r''' |
| 9808 class A { |
| 9809 void m1() {} |
| 9810 void m2() {} |
| 9811 void m() { |
| 9812 A a = new A(); |
| 9813 a..m1() |
| 9814 ..m2(); |
| 9815 } |
| 9816 }'''); |
| 9817 computeLibrarySourceErrors(source); |
| 9818 assertNoErrors(source); |
| 9819 verify([source]); |
| 9820 } |
| 9821 |
| 9822 void test_methodCascades_withSetter() { |
| 9823 Source source = addSource(r''' |
| 9824 class A { |
| 9825 String name; |
| 9826 void m1() {} |
| 9827 void m2() {} |
| 9828 void m() { |
| 9829 A a = new A(); |
| 9830 a..m1() |
| 9831 ..name = 'name' |
| 9832 ..m2(); |
| 9833 } |
| 9834 }'''); |
| 9835 computeLibrarySourceErrors(source); |
| 9836 // failing with error code: INVOCATION_OF_NON_FUNCTION |
| 9837 assertNoErrors(source); |
| 9838 verify([source]); |
| 9839 } |
| 9840 |
| 9841 void test_resolveAgainstNull() { |
| 9842 Source source = addSource(r''' |
| 9843 f(var p) { |
| 9844 return null == p; |
| 9845 }'''); |
| 9846 computeLibrarySourceErrors(source); |
| 9847 assertNoErrors(source); |
| 9848 } |
| 9849 |
| 9850 void test_setter_fromMixins_bare_identifier() { |
| 9851 Source source = addSource(''' |
| 9852 class B {} |
| 9853 class M1 { |
| 9854 set x(value) {} |
| 9855 } |
| 9856 class M2 { |
| 9857 set x(value) {} |
| 9858 } |
| 9859 class C extends B with M1, M2 { |
| 9860 void f() { |
| 9861 x = 1; |
| 9862 } |
| 9863 } |
| 9864 '''); |
| 9865 LibraryElement library = resolve2(source); |
| 9866 assertNoErrors(source); |
| 9867 verify([source]); |
| 9868 // Verify that the setter for "x" in C.f() refers to the setter defined in |
| 9869 // M2. |
| 9870 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 9871 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 9872 BlockFunctionBody body = f.body; |
| 9873 ExpressionStatement stmt = body.block.statements[0]; |
| 9874 AssignmentExpression assignment = stmt.expression; |
| 9875 SimpleIdentifier leftHandSide = assignment.leftHandSide; |
| 9876 expect(leftHandSide.staticElement.enclosingElement.name, 'M2'); |
| 9877 } |
| 9878 |
| 9879 void test_setter_fromMixins_property_access() { |
| 9880 Source source = addSource(''' |
| 9881 class B {} |
| 9882 class M1 { |
| 9883 set x(value) {} |
| 9884 } |
| 9885 class M2 { |
| 9886 set x(value) {} |
| 9887 } |
| 9888 class C extends B with M1, M2 {} |
| 9889 void main() { |
| 9890 new C().x = 1; |
| 9891 } |
| 9892 '''); |
| 9893 LibraryElement library = resolve2(source); |
| 9894 assertNoErrors(source); |
| 9895 verify([source]); |
| 9896 // Verify that the setter for "x" in "new C().x" refers to the setter |
| 9897 // defined in M2. |
| 9898 FunctionDeclaration main = |
| 9899 library.definingCompilationUnit.functions[0].computeNode(); |
| 9900 BlockFunctionBody body = main.functionExpression.body; |
| 9901 ExpressionStatement stmt = body.block.statements[0]; |
| 9902 AssignmentExpression assignment = stmt.expression; |
| 9903 PropertyAccess propertyAccess = assignment.leftHandSide; |
| 9904 expect( |
| 9905 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 9906 } |
| 9907 |
| 9908 void test_setter_inherited() { |
| 9909 Source source = addSource(r''' |
| 9910 class A { |
| 9911 int get x => 0; |
| 9912 set x(int p) {} |
| 9913 } |
| 9914 class B extends A { |
| 9915 int get x => super.x == null ? 0 : super.x; |
| 9916 int f() => x = 1; |
| 9917 }'''); |
| 9918 computeLibrarySourceErrors(source); |
| 9919 assertNoErrors(source); |
| 9920 verify([source]); |
| 9921 } |
| 9922 |
| 9923 void test_setter_static() { |
| 9924 Source source = addSource(r''' |
| 9925 set s(x) { |
| 9926 } |
| 9927 |
| 9928 main() { |
| 9929 s = 123; |
| 9930 }'''); |
| 9931 computeLibrarySourceErrors(source); |
| 9932 assertNoErrors(source); |
| 9933 verify([source]); |
| 9934 } |
| 9935 |
| 9936 /** |
| 9937 * Resolve the given source and verify that the arguments in a specific method
invocation were |
| 9938 * correctly resolved. |
| 9939 * |
| 9940 * The source is expected to be source for a compilation unit, the first decla
ration is expected |
| 9941 * to be a class, the first member of which is expected to be a method with a
block body, and the |
| 9942 * first statement in the body is expected to be an expression statement whose
expression is a |
| 9943 * method invocation. It is the arguments to that method invocation that are t
ested. The method |
| 9944 * invocation can contain errors. |
| 9945 * |
| 9946 * The arguments were resolved correctly if the number of expressions in the l
ist matches the |
| 9947 * length of the array of indices and if, for each index in the array of indic
es, the parameter to |
| 9948 * which the argument expression was resolved is the parameter in the invoked
method's list of |
| 9949 * parameters at that index. Arguments that should not be resolved to a parame
ter because of an |
| 9950 * error can be denoted by including a negative index in the array of indices. |
| 9951 * |
| 9952 * @param source the source to be resolved |
| 9953 * @param indices the array of indices used to associate arguments with parame
ters |
| 9954 * @throws Exception if the source could not be resolved or if the structure o
f the source is not |
| 9955 * valid |
| 9956 */ |
| 9957 void _validateArgumentResolution(Source source, List<int> indices) { |
| 9958 LibraryElement library = resolve2(source); |
| 9959 expect(library, isNotNull); |
| 9960 ClassElement classElement = library.definingCompilationUnit.types[0]; |
| 9961 List<ParameterElement> parameters = classElement.methods[1].parameters; |
| 9962 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 9963 expect(unit, isNotNull); |
| 9964 ClassDeclaration classDeclaration = |
| 9965 unit.declarations[0] as ClassDeclaration; |
| 9966 MethodDeclaration methodDeclaration = |
| 9967 classDeclaration.members[0] as MethodDeclaration; |
| 9968 Block block = (methodDeclaration.body as BlockFunctionBody).block; |
| 9969 ExpressionStatement statement = block.statements[0] as ExpressionStatement; |
| 9970 MethodInvocation invocation = statement.expression as MethodInvocation; |
| 9971 NodeList<Expression> arguments = invocation.argumentList.arguments; |
| 9972 int argumentCount = arguments.length; |
| 9973 expect(argumentCount, indices.length); |
| 9974 for (int i = 0; i < argumentCount; i++) { |
| 9975 Expression argument = arguments[i]; |
| 9976 ParameterElement element = argument.staticParameterElement; |
| 9977 int index = indices[i]; |
| 9978 if (index < 0) { |
| 9979 expect(element, isNull); |
| 9980 } else { |
| 9981 expect(element, same(parameters[index])); |
| 9982 } |
| 9983 } |
| 9984 } |
| 9985 } |
| 9986 |
| 9987 class SourceContainer_ChangeSetTest_test_toString implements SourceContainer { |
| 9988 @override |
| 9989 bool contains(Source source) => false; |
| 9990 } |
| 9991 |
| 9992 /** |
| 9993 * Like [StaticTypeAnalyzerTest], but as end-to-end tests. |
| 9994 */ |
| 9995 @reflectiveTest |
| 9996 class StaticTypeAnalyzer2Test extends _StaticTypeAnalyzer2TestShared { |
| 9997 void test_FunctionExpressionInvocation_block() { |
| 9998 String code = r''' |
| 9999 main() { |
| 10000 var foo = (() { return 1; })(); |
| 10001 } |
| 10002 '''; |
| 10003 _resolveTestUnit(code); |
| 10004 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 10005 VariableDeclaration declaration = |
| 10006 identifier.getAncestor((node) => node is VariableDeclaration); |
| 10007 expect(declaration.initializer.staticType.isDynamic, isTrue); |
| 10008 expect(declaration.initializer.propagatedType, isNull); |
| 10009 } |
| 10010 |
| 10011 void test_FunctionExpressionInvocation_curried() { |
| 10012 String code = r''' |
| 10013 typedef int F(); |
| 10014 F f() => null; |
| 10015 main() { |
| 10016 var foo = f()(); |
| 10017 } |
| 10018 '''; |
| 10019 _resolveTestUnit(code); |
| 10020 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 10021 VariableDeclaration declaration = |
| 10022 identifier.getAncestor((node) => node is VariableDeclaration); |
| 10023 expect(declaration.initializer.staticType.name, 'int'); |
| 10024 expect(declaration.initializer.propagatedType, isNull); |
| 10025 } |
| 10026 |
| 10027 void test_FunctionExpressionInvocation_expression() { |
| 10028 String code = r''' |
| 10029 main() { |
| 10030 var foo = (() => 1)(); |
| 10031 } |
| 10032 '''; |
| 10033 _resolveTestUnit(code); |
| 10034 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 10035 VariableDeclaration declaration = |
| 10036 identifier.getAncestor((node) => node is VariableDeclaration); |
| 10037 expect(declaration.initializer.staticType.name, 'int'); |
| 10038 expect(declaration.initializer.propagatedType, isNull); |
| 10039 } |
| 10040 |
| 10041 void test_MethodInvocation_nameType_localVariable() { |
| 10042 String code = r""" |
| 10043 typedef Foo(); |
| 10044 main() { |
| 10045 Foo foo; |
| 10046 foo(); |
| 10047 } |
| 10048 """; |
| 10049 _resolveTestUnit(code); |
| 10050 // "foo" should be resolved to the "Foo" type |
| 10051 SimpleIdentifier identifier = _findIdentifier("foo();"); |
| 10052 DartType type = identifier.staticType; |
| 10053 expect(type, new isInstanceOf<FunctionType>()); |
| 10054 } |
| 10055 |
| 10056 void test_MethodInvocation_nameType_parameter_FunctionTypeAlias() { |
| 10057 String code = r""" |
| 10058 typedef Foo(); |
| 10059 main(Foo foo) { |
| 10060 foo(); |
| 10061 } |
| 10062 """; |
| 10063 _resolveTestUnit(code); |
| 10064 // "foo" should be resolved to the "Foo" type |
| 10065 SimpleIdentifier identifier = _findIdentifier("foo();"); |
| 10066 DartType type = identifier.staticType; |
| 10067 expect(type, new isInstanceOf<FunctionType>()); |
| 10068 } |
| 10069 |
| 10070 void test_MethodInvocation_nameType_parameter_propagatedType() { |
| 10071 String code = r""" |
| 10072 typedef Foo(); |
| 10073 main(p) { |
| 10074 if (p is Foo) { |
| 10075 p(); |
| 10076 } |
| 10077 } |
| 10078 """; |
| 10079 _resolveTestUnit(code); |
| 10080 SimpleIdentifier identifier = _findIdentifier("p()"); |
| 10081 expect(identifier.staticType, DynamicTypeImpl.instance); |
| 10082 { |
| 10083 FunctionType type = identifier.propagatedType; |
| 10084 expect(type, isNotNull); |
| 10085 expect(type.name, 'Foo'); |
| 10086 } |
| 10087 } |
| 10088 } |
| 10089 |
| 10090 @reflectiveTest |
| 10091 class StaticTypeAnalyzerTest extends EngineTestCase { |
| 10092 /** |
| 10093 * The error listener to which errors will be reported. |
| 10094 */ |
| 10095 GatheringErrorListener _listener; |
| 10096 |
| 10097 /** |
| 10098 * The resolver visitor used to create the analyzer. |
| 10099 */ |
| 10100 ResolverVisitor _visitor; |
| 10101 |
| 10102 /** |
| 10103 * The analyzer being used to analyze the test cases. |
| 10104 */ |
| 10105 StaticTypeAnalyzer _analyzer; |
| 10106 |
| 10107 /** |
| 10108 * The type provider used to access the types. |
| 10109 */ |
| 10110 TestTypeProvider _typeProvider; |
| 10111 |
| 10112 void fail_visitFunctionExpressionInvocation() { |
| 10113 fail("Not yet tested"); |
| 10114 _listener.assertNoErrors(); |
| 10115 } |
| 10116 |
| 10117 void fail_visitMethodInvocation() { |
| 10118 fail("Not yet tested"); |
| 10119 _listener.assertNoErrors(); |
| 10120 } |
| 10121 |
| 10122 void fail_visitSimpleIdentifier() { |
| 10123 fail("Not yet tested"); |
| 10124 _listener.assertNoErrors(); |
| 10125 } |
| 10126 |
| 10127 @override |
| 10128 void setUp() { |
| 10129 _listener = new GatheringErrorListener(); |
| 10130 _typeProvider = new TestTypeProvider(); |
| 10131 _analyzer = _createAnalyzer(); |
| 10132 } |
| 10133 |
| 10134 void test_flatten_derived() { |
| 10135 // class Derived<T> extends Future<T> { ... } |
| 10136 ClassElementImpl derivedClass = |
| 10137 ElementFactory.classElement2('Derived', ['T']); |
| 10138 derivedClass.supertype = _typeProvider.futureType |
| 10139 .substitute4([derivedClass.typeParameters[0].type]); |
| 10140 InterfaceType intType = _typeProvider.intType; |
| 10141 DartType dynamicType = _typeProvider.dynamicType; |
| 10142 InterfaceType derivedIntType = derivedClass.type.substitute4([intType]); |
| 10143 // flatten(Derived) = dynamic |
| 10144 InterfaceType derivedDynamicType = |
| 10145 derivedClass.type.substitute4([dynamicType]); |
| 10146 expect(_flatten(derivedDynamicType), dynamicType); |
| 10147 // flatten(Derived<int>) = int |
| 10148 expect(_flatten(derivedIntType), intType); |
| 10149 // flatten(Derived<Derived>) = Derived |
| 10150 expect(_flatten(derivedClass.type.substitute4([derivedDynamicType])), |
| 10151 derivedDynamicType); |
| 10152 // flatten(Derived<Derived<int>>) = Derived<int> |
| 10153 expect(_flatten(derivedClass.type.substitute4([derivedIntType])), |
| 10154 derivedIntType); |
| 10155 } |
| 10156 |
| 10157 void test_flatten_inhibit_recursion() { |
| 10158 // class A extends B |
| 10159 // class B extends A |
| 10160 ClassElementImpl classA = ElementFactory.classElement2('A', []); |
| 10161 ClassElementImpl classB = ElementFactory.classElement2('B', []); |
| 10162 classA.supertype = classB.type; |
| 10163 classB.supertype = classA.type; |
| 10164 // flatten(A) = A and flatten(B) = B, since neither class contains Future |
| 10165 // in its class hierarchy. Even though there is a loop in the class |
| 10166 // hierarchy, flatten() should terminate. |
| 10167 expect(_flatten(classA.type), classA.type); |
| 10168 expect(_flatten(classB.type), classB.type); |
| 10169 } |
| 10170 |
| 10171 void test_flatten_related_derived_types() { |
| 10172 InterfaceType intType = _typeProvider.intType; |
| 10173 InterfaceType numType = _typeProvider.numType; |
| 10174 // class Derived<T> extends Future<T> |
| 10175 ClassElementImpl derivedClass = |
| 10176 ElementFactory.classElement2('Derived', ['T']); |
| 10177 derivedClass.supertype = _typeProvider.futureType |
| 10178 .substitute4([derivedClass.typeParameters[0].type]); |
| 10179 InterfaceType derivedType = derivedClass.type; |
| 10180 // class A extends Derived<int> implements Derived<num> { ... } |
| 10181 ClassElementImpl classA = |
| 10182 ElementFactory.classElement('A', derivedType.substitute4([intType])); |
| 10183 classA.interfaces = <InterfaceType>[ |
| 10184 derivedType.substitute4([numType]) |
| 10185 ]; |
| 10186 // class B extends Future<num> implements Future<int> { ... } |
| 10187 ClassElementImpl classB = |
| 10188 ElementFactory.classElement('B', derivedType.substitute4([numType])); |
| 10189 classB.interfaces = <InterfaceType>[ |
| 10190 derivedType.substitute4([intType]) |
| 10191 ]; |
| 10192 // flatten(A) = flatten(B) = int, since int is more specific than num. |
| 10193 // The code in flatten() that inhibits infinite recursion shouldn't be |
| 10194 // fooled by the fact that Derived appears twice in the type hierarchy. |
| 10195 expect(_flatten(classA.type), intType); |
| 10196 expect(_flatten(classB.type), intType); |
| 10197 } |
| 10198 |
| 10199 void test_flatten_related_types() { |
| 10200 InterfaceType futureType = _typeProvider.futureType; |
| 10201 InterfaceType intType = _typeProvider.intType; |
| 10202 InterfaceType numType = _typeProvider.numType; |
| 10203 // class A extends Future<int> implements Future<num> { ... } |
| 10204 ClassElementImpl classA = |
| 10205 ElementFactory.classElement('A', futureType.substitute4([intType])); |
| 10206 classA.interfaces = <InterfaceType>[ |
| 10207 futureType.substitute4([numType]) |
| 10208 ]; |
| 10209 // class B extends Future<num> implements Future<int> { ... } |
| 10210 ClassElementImpl classB = |
| 10211 ElementFactory.classElement('B', futureType.substitute4([numType])); |
| 10212 classB.interfaces = <InterfaceType>[ |
| 10213 futureType.substitute4([intType]) |
| 10214 ]; |
| 10215 // flatten(A) = flatten(B) = int, since int is more specific than num. |
| 10216 expect(_flatten(classA.type), intType); |
| 10217 expect(_flatten(classB.type), intType); |
| 10218 } |
| 10219 |
| 10220 void test_flatten_simple() { |
| 10221 InterfaceType intType = _typeProvider.intType; |
| 10222 DartType dynamicType = _typeProvider.dynamicType; |
| 10223 InterfaceType futureDynamicType = _typeProvider.futureDynamicType; |
| 10224 InterfaceType futureIntType = |
| 10225 _typeProvider.futureType.substitute4([intType]); |
| 10226 InterfaceType futureFutureDynamicType = |
| 10227 _typeProvider.futureType.substitute4([futureDynamicType]); |
| 10228 InterfaceType futureFutureIntType = |
| 10229 _typeProvider.futureType.substitute4([futureIntType]); |
| 10230 // flatten(int) = int |
| 10231 expect(_flatten(intType), intType); |
| 10232 // flatten(dynamic) = dynamic |
| 10233 expect(_flatten(dynamicType), dynamicType); |
| 10234 // flatten(Future) = dynamic |
| 10235 expect(_flatten(futureDynamicType), dynamicType); |
| 10236 // flatten(Future<int>) = int |
| 10237 expect(_flatten(futureIntType), intType); |
| 10238 // flatten(Future<Future>) = dynamic |
| 10239 expect(_flatten(futureFutureDynamicType), dynamicType); |
| 10240 // flatten(Future<Future<int>>) = int |
| 10241 expect(_flatten(futureFutureIntType), intType); |
| 10242 } |
| 10243 |
| 10244 void test_flatten_unrelated_types() { |
| 10245 InterfaceType futureType = _typeProvider.futureType; |
| 10246 InterfaceType intType = _typeProvider.intType; |
| 10247 InterfaceType stringType = _typeProvider.stringType; |
| 10248 // class A extends Future<int> implements Future<String> { ... } |
| 10249 ClassElementImpl classA = |
| 10250 ElementFactory.classElement('A', futureType.substitute4([intType])); |
| 10251 classA.interfaces = <InterfaceType>[ |
| 10252 futureType.substitute4([stringType]) |
| 10253 ]; |
| 10254 // class B extends Future<String> implements Future<int> { ... } |
| 10255 ClassElementImpl classB = |
| 10256 ElementFactory.classElement('B', futureType.substitute4([stringType])); |
| 10257 classB.interfaces = <InterfaceType>[ |
| 10258 futureType.substitute4([intType]) |
| 10259 ]; |
| 10260 // flatten(A) = A and flatten(B) = B, since neither string nor int is more |
| 10261 // specific than the other. |
| 10262 expect(_flatten(classA.type), classA.type); |
| 10263 expect(_flatten(classB.type), classB.type); |
| 10264 } |
| 10265 |
| 10266 void test_visitAdjacentStrings() { |
| 10267 // "a" "b" |
| 10268 Expression node = AstFactory |
| 10269 .adjacentStrings([_resolvedString("a"), _resolvedString("b")]); |
| 10270 expect(_analyze(node), same(_typeProvider.stringType)); |
| 10271 _listener.assertNoErrors(); |
| 10272 } |
| 10273 |
| 10274 void test_visitAsExpression() { |
| 10275 // class A { ... this as B ... } |
| 10276 // class B extends A {} |
| 10277 ClassElement superclass = ElementFactory.classElement2("A"); |
| 10278 InterfaceType superclassType = superclass.type; |
| 10279 ClassElement subclass = ElementFactory.classElement("B", superclassType); |
| 10280 Expression node = AstFactory.asExpression( |
| 10281 AstFactory.thisExpression(), AstFactory.typeName(subclass)); |
| 10282 expect(_analyze3(node, superclassType), same(subclass.type)); |
| 10283 _listener.assertNoErrors(); |
| 10284 } |
| 10285 |
| 10286 void test_visitAssignmentExpression_compound() { |
| 10287 // i += 1 |
| 10288 InterfaceType numType = _typeProvider.numType; |
| 10289 SimpleIdentifier identifier = _resolvedVariable(_typeProvider.intType, "i"); |
| 10290 AssignmentExpression node = AstFactory.assignmentExpression( |
| 10291 identifier, TokenType.PLUS_EQ, _resolvedInteger(1)); |
| 10292 MethodElement plusMethod = getMethod(numType, "+"); |
| 10293 node.staticElement = plusMethod; |
| 10294 expect(_analyze(node), same(numType)); |
| 10295 _listener.assertNoErrors(); |
| 10296 } |
| 10297 |
| 10298 void test_visitAssignmentExpression_compoundIfNull_differentTypes() { |
| 10299 // double d; d ??= 0 |
| 10300 Expression node = AstFactory.assignmentExpression( |
| 10301 _resolvedVariable(_typeProvider.doubleType, 'd'), |
| 10302 TokenType.QUESTION_QUESTION_EQ, |
| 10303 _resolvedInteger(0)); |
| 10304 expect(_analyze(node), same(_typeProvider.numType)); |
| 10305 _listener.assertNoErrors(); |
| 10306 } |
| 10307 |
| 10308 void test_visitAssignmentExpression_compoundIfNull_sameTypes() { |
| 10309 // int i; i ??= 0 |
| 10310 Expression node = AstFactory.assignmentExpression( |
| 10311 _resolvedVariable(_typeProvider.intType, 'i'), |
| 10312 TokenType.QUESTION_QUESTION_EQ, |
| 10313 _resolvedInteger(0)); |
| 10314 expect(_analyze(node), same(_typeProvider.intType)); |
| 10315 _listener.assertNoErrors(); |
| 10316 } |
| 10317 |
| 10318 void test_visitAssignmentExpression_simple() { |
| 10319 // i = 0 |
| 10320 InterfaceType intType = _typeProvider.intType; |
| 10321 Expression node = AstFactory.assignmentExpression( |
| 10322 _resolvedVariable(intType, "i"), TokenType.EQ, _resolvedInteger(0)); |
| 10323 expect(_analyze(node), same(intType)); |
| 10324 _listener.assertNoErrors(); |
| 10325 } |
| 10326 |
| 10327 void test_visitAwaitExpression_flattened() { |
| 10328 // await e, where e has type Future<Future<int>> |
| 10329 InterfaceType intType = _typeProvider.intType; |
| 10330 InterfaceType futureIntType = |
| 10331 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10332 InterfaceType futureFutureIntType = |
| 10333 _typeProvider.futureType.substitute4(<DartType>[futureIntType]); |
| 10334 Expression node = |
| 10335 AstFactory.awaitExpression(_resolvedVariable(futureFutureIntType, 'e')); |
| 10336 expect(_analyze(node), same(intType)); |
| 10337 _listener.assertNoErrors(); |
| 10338 } |
| 10339 |
| 10340 void test_visitAwaitExpression_simple() { |
| 10341 // await e, where e has type Future<int> |
| 10342 InterfaceType intType = _typeProvider.intType; |
| 10343 InterfaceType futureIntType = |
| 10344 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10345 Expression node = |
| 10346 AstFactory.awaitExpression(_resolvedVariable(futureIntType, 'e')); |
| 10347 expect(_analyze(node), same(intType)); |
| 10348 _listener.assertNoErrors(); |
| 10349 } |
| 10350 |
| 10351 void test_visitBinaryExpression_equals() { |
| 10352 // 2 == 3 |
| 10353 Expression node = AstFactory.binaryExpression( |
| 10354 _resolvedInteger(2), TokenType.EQ_EQ, _resolvedInteger(3)); |
| 10355 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10356 _listener.assertNoErrors(); |
| 10357 } |
| 10358 |
| 10359 void test_visitBinaryExpression_ifNull() { |
| 10360 // 1 ?? 1.5 |
| 10361 Expression node = AstFactory.binaryExpression( |
| 10362 _resolvedInteger(1), TokenType.QUESTION_QUESTION, _resolvedDouble(1.5)); |
| 10363 expect(_analyze(node), same(_typeProvider.numType)); |
| 10364 _listener.assertNoErrors(); |
| 10365 } |
| 10366 |
| 10367 void test_visitBinaryExpression_logicalAnd() { |
| 10368 // false && true |
| 10369 Expression node = AstFactory.binaryExpression( |
| 10370 AstFactory.booleanLiteral(false), |
| 10371 TokenType.AMPERSAND_AMPERSAND, |
| 10372 AstFactory.booleanLiteral(true)); |
| 10373 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10374 _listener.assertNoErrors(); |
| 10375 } |
| 10376 |
| 10377 void test_visitBinaryExpression_logicalOr() { |
| 10378 // false || true |
| 10379 Expression node = AstFactory.binaryExpression( |
| 10380 AstFactory.booleanLiteral(false), |
| 10381 TokenType.BAR_BAR, |
| 10382 AstFactory.booleanLiteral(true)); |
| 10383 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10384 _listener.assertNoErrors(); |
| 10385 } |
| 10386 |
| 10387 void test_visitBinaryExpression_minusID_propagated() { |
| 10388 // a - b |
| 10389 BinaryExpression node = AstFactory.binaryExpression( |
| 10390 _propagatedVariable(_typeProvider.intType, 'a'), |
| 10391 TokenType.MINUS, |
| 10392 _propagatedVariable(_typeProvider.doubleType, 'b')); |
| 10393 node.propagatedElement = getMethod(_typeProvider.numType, "+"); |
| 10394 _analyze(node); |
| 10395 expect(node.propagatedType, same(_typeProvider.doubleType)); |
| 10396 _listener.assertNoErrors(); |
| 10397 } |
| 10398 |
| 10399 void test_visitBinaryExpression_notEquals() { |
| 10400 // 2 != 3 |
| 10401 Expression node = AstFactory.binaryExpression( |
| 10402 _resolvedInteger(2), TokenType.BANG_EQ, _resolvedInteger(3)); |
| 10403 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10404 _listener.assertNoErrors(); |
| 10405 } |
| 10406 |
| 10407 void test_visitBinaryExpression_plusID() { |
| 10408 // 1 + 2.0 |
| 10409 BinaryExpression node = AstFactory.binaryExpression( |
| 10410 _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0)); |
| 10411 node.staticElement = getMethod(_typeProvider.numType, "+"); |
| 10412 expect(_analyze(node), same(_typeProvider.doubleType)); |
| 10413 _listener.assertNoErrors(); |
| 10414 } |
| 10415 |
| 10416 void test_visitBinaryExpression_plusII() { |
| 10417 // 1 + 2 |
| 10418 BinaryExpression node = AstFactory.binaryExpression( |
| 10419 _resolvedInteger(1), TokenType.PLUS, _resolvedInteger(2)); |
| 10420 node.staticElement = getMethod(_typeProvider.numType, "+"); |
| 10421 expect(_analyze(node), same(_typeProvider.intType)); |
| 10422 _listener.assertNoErrors(); |
| 10423 } |
| 10424 |
| 10425 void test_visitBinaryExpression_plusII_propagated() { |
| 10426 // a + b |
| 10427 BinaryExpression node = AstFactory.binaryExpression( |
| 10428 _propagatedVariable(_typeProvider.intType, 'a'), |
| 10429 TokenType.PLUS, |
| 10430 _propagatedVariable(_typeProvider.intType, 'b')); |
| 10431 node.propagatedElement = getMethod(_typeProvider.numType, "+"); |
| 10432 _analyze(node); |
| 10433 expect(node.propagatedType, same(_typeProvider.intType)); |
| 10434 _listener.assertNoErrors(); |
| 10435 } |
| 10436 |
| 10437 void test_visitBinaryExpression_slash() { |
| 10438 // 2 / 2 |
| 10439 BinaryExpression node = AstFactory.binaryExpression( |
| 10440 _resolvedInteger(2), TokenType.SLASH, _resolvedInteger(2)); |
| 10441 node.staticElement = getMethod(_typeProvider.numType, "/"); |
| 10442 expect(_analyze(node), same(_typeProvider.doubleType)); |
| 10443 _listener.assertNoErrors(); |
| 10444 } |
| 10445 |
| 10446 void test_visitBinaryExpression_star_notSpecial() { |
| 10447 // class A { |
| 10448 // A operator *(double value); |
| 10449 // } |
| 10450 // (a as A) * 2.0 |
| 10451 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 10452 InterfaceType typeA = classA.type; |
| 10453 MethodElement operator = |
| 10454 ElementFactory.methodElement("*", typeA, [_typeProvider.doubleType]); |
| 10455 classA.methods = <MethodElement>[operator]; |
| 10456 BinaryExpression node = AstFactory.binaryExpression( |
| 10457 AstFactory.asExpression( |
| 10458 AstFactory.identifier3("a"), AstFactory.typeName(classA)), |
| 10459 TokenType.PLUS, |
| 10460 _resolvedDouble(2.0)); |
| 10461 node.staticElement = operator; |
| 10462 expect(_analyze(node), same(typeA)); |
| 10463 _listener.assertNoErrors(); |
| 10464 } |
| 10465 |
| 10466 void test_visitBinaryExpression_starID() { |
| 10467 // 1 * 2.0 |
| 10468 BinaryExpression node = AstFactory.binaryExpression( |
| 10469 _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0)); |
| 10470 node.staticElement = getMethod(_typeProvider.numType, "*"); |
| 10471 expect(_analyze(node), same(_typeProvider.doubleType)); |
| 10472 _listener.assertNoErrors(); |
| 10473 } |
| 10474 |
| 10475 void test_visitBooleanLiteral_false() { |
| 10476 // false |
| 10477 Expression node = AstFactory.booleanLiteral(false); |
| 10478 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10479 _listener.assertNoErrors(); |
| 10480 } |
| 10481 |
| 10482 void test_visitBooleanLiteral_true() { |
| 10483 // true |
| 10484 Expression node = AstFactory.booleanLiteral(true); |
| 10485 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10486 _listener.assertNoErrors(); |
| 10487 } |
| 10488 |
| 10489 void test_visitCascadeExpression() { |
| 10490 // a..length |
| 10491 Expression node = AstFactory.cascadeExpression( |
| 10492 _resolvedString("a"), [AstFactory.propertyAccess2(null, "length")]); |
| 10493 expect(_analyze(node), same(_typeProvider.stringType)); |
| 10494 _listener.assertNoErrors(); |
| 10495 } |
| 10496 |
| 10497 void test_visitConditionalExpression_differentTypes() { |
| 10498 // true ? 1.0 : 0 |
| 10499 Expression node = AstFactory.conditionalExpression( |
| 10500 AstFactory.booleanLiteral(true), |
| 10501 _resolvedDouble(1.0), |
| 10502 _resolvedInteger(0)); |
| 10503 expect(_analyze(node), same(_typeProvider.numType)); |
| 10504 _listener.assertNoErrors(); |
| 10505 } |
| 10506 |
| 10507 void test_visitConditionalExpression_sameTypes() { |
| 10508 // true ? 1 : 0 |
| 10509 Expression node = AstFactory.conditionalExpression( |
| 10510 AstFactory.booleanLiteral(true), |
| 10511 _resolvedInteger(1), |
| 10512 _resolvedInteger(0)); |
| 10513 expect(_analyze(node), same(_typeProvider.intType)); |
| 10514 _listener.assertNoErrors(); |
| 10515 } |
| 10516 |
| 10517 void test_visitDoubleLiteral() { |
| 10518 // 4.33 |
| 10519 Expression node = AstFactory.doubleLiteral(4.33); |
| 10520 expect(_analyze(node), same(_typeProvider.doubleType)); |
| 10521 _listener.assertNoErrors(); |
| 10522 } |
| 10523 |
| 10524 void test_visitFunctionExpression_async_block() { |
| 10525 // () async {} |
| 10526 BlockFunctionBody body = AstFactory.blockFunctionBody2(); |
| 10527 body.keyword = TokenFactory.tokenFromString('async'); |
| 10528 FunctionExpression node = |
| 10529 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10530 DartType resultType = _analyze(node); |
| 10531 _assertFunctionType( |
| 10532 _typeProvider.futureDynamicType, null, null, null, resultType); |
| 10533 _listener.assertNoErrors(); |
| 10534 } |
| 10535 |
| 10536 void test_visitFunctionExpression_async_expression() { |
| 10537 // () async => e, where e has type int |
| 10538 InterfaceType intType = _typeProvider.intType; |
| 10539 InterfaceType futureIntType = |
| 10540 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10541 Expression expression = _resolvedVariable(intType, 'e'); |
| 10542 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); |
| 10543 body.keyword = TokenFactory.tokenFromString('async'); |
| 10544 FunctionExpression node = |
| 10545 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10546 DartType resultType = _analyze(node); |
| 10547 _assertFunctionType(futureIntType, null, null, null, resultType); |
| 10548 _listener.assertNoErrors(); |
| 10549 } |
| 10550 |
| 10551 void test_visitFunctionExpression_async_expression_flatten() { |
| 10552 // () async => e, where e has type Future<int> |
| 10553 InterfaceType intType = _typeProvider.intType; |
| 10554 InterfaceType futureIntType = |
| 10555 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10556 Expression expression = _resolvedVariable(futureIntType, 'e'); |
| 10557 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); |
| 10558 body.keyword = TokenFactory.tokenFromString('async'); |
| 10559 FunctionExpression node = |
| 10560 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10561 DartType resultType = _analyze(node); |
| 10562 _assertFunctionType(futureIntType, null, null, null, resultType); |
| 10563 _listener.assertNoErrors(); |
| 10564 } |
| 10565 |
| 10566 void test_visitFunctionExpression_async_expression_flatten_twice() { |
| 10567 // () async => e, where e has type Future<Future<int>> |
| 10568 InterfaceType intType = _typeProvider.intType; |
| 10569 InterfaceType futureIntType = |
| 10570 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10571 InterfaceType futureFutureIntType = |
| 10572 _typeProvider.futureType.substitute4(<DartType>[futureIntType]); |
| 10573 Expression expression = _resolvedVariable(futureFutureIntType, 'e'); |
| 10574 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); |
| 10575 body.keyword = TokenFactory.tokenFromString('async'); |
| 10576 FunctionExpression node = |
| 10577 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10578 DartType resultType = _analyze(node); |
| 10579 _assertFunctionType(futureIntType, null, null, null, resultType); |
| 10580 _listener.assertNoErrors(); |
| 10581 } |
| 10582 |
| 10583 void test_visitFunctionExpression_generator_async() { |
| 10584 // () async* {} |
| 10585 BlockFunctionBody body = AstFactory.blockFunctionBody2(); |
| 10586 body.keyword = TokenFactory.tokenFromString('async'); |
| 10587 body.star = TokenFactory.tokenFromType(TokenType.STAR); |
| 10588 FunctionExpression node = |
| 10589 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10590 DartType resultType = _analyze(node); |
| 10591 _assertFunctionType( |
| 10592 _typeProvider.streamDynamicType, null, null, null, resultType); |
| 10593 _listener.assertNoErrors(); |
| 10594 } |
| 10595 |
| 10596 void test_visitFunctionExpression_generator_sync() { |
| 10597 // () sync* {} |
| 10598 BlockFunctionBody body = AstFactory.blockFunctionBody2(); |
| 10599 body.keyword = TokenFactory.tokenFromString('sync'); |
| 10600 body.star = TokenFactory.tokenFromType(TokenType.STAR); |
| 10601 FunctionExpression node = |
| 10602 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10603 DartType resultType = _analyze(node); |
| 10604 _assertFunctionType( |
| 10605 _typeProvider.iterableDynamicType, null, null, null, resultType); |
| 10606 _listener.assertNoErrors(); |
| 10607 } |
| 10608 |
| 10609 void test_visitFunctionExpression_named_block() { |
| 10610 // ({p1 : 0, p2 : 0}) {} |
| 10611 DartType dynamicType = _typeProvider.dynamicType; |
| 10612 FormalParameter p1 = AstFactory.namedFormalParameter( |
| 10613 AstFactory.simpleFormalParameter3("p1"), _resolvedInteger(0)); |
| 10614 _setType(p1, dynamicType); |
| 10615 FormalParameter p2 = AstFactory.namedFormalParameter( |
| 10616 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10617 _setType(p2, dynamicType); |
| 10618 FunctionExpression node = _resolvedFunctionExpression( |
| 10619 AstFactory.formalParameterList([p1, p2]), |
| 10620 AstFactory.blockFunctionBody2()); |
| 10621 _analyze5(p1); |
| 10622 _analyze5(p2); |
| 10623 DartType resultType = _analyze(node); |
| 10624 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); |
| 10625 expectedNamedTypes["p1"] = dynamicType; |
| 10626 expectedNamedTypes["p2"] = dynamicType; |
| 10627 _assertFunctionType( |
| 10628 dynamicType, null, null, expectedNamedTypes, resultType); |
| 10629 _listener.assertNoErrors(); |
| 10630 } |
| 10631 |
| 10632 void test_visitFunctionExpression_named_expression() { |
| 10633 // ({p : 0}) -> 0; |
| 10634 DartType dynamicType = _typeProvider.dynamicType; |
| 10635 FormalParameter p = AstFactory.namedFormalParameter( |
| 10636 AstFactory.simpleFormalParameter3("p"), _resolvedInteger(0)); |
| 10637 _setType(p, dynamicType); |
| 10638 FunctionExpression node = _resolvedFunctionExpression( |
| 10639 AstFactory.formalParameterList([p]), |
| 10640 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10641 _analyze5(p); |
| 10642 DartType resultType = _analyze(node); |
| 10643 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); |
| 10644 expectedNamedTypes["p"] = dynamicType; |
| 10645 _assertFunctionType( |
| 10646 _typeProvider.intType, null, null, expectedNamedTypes, resultType); |
| 10647 _listener.assertNoErrors(); |
| 10648 } |
| 10649 |
| 10650 void test_visitFunctionExpression_normal_block() { |
| 10651 // (p1, p2) {} |
| 10652 DartType dynamicType = _typeProvider.dynamicType; |
| 10653 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10654 _setType(p1, dynamicType); |
| 10655 FormalParameter p2 = AstFactory.simpleFormalParameter3("p2"); |
| 10656 _setType(p2, dynamicType); |
| 10657 FunctionExpression node = _resolvedFunctionExpression( |
| 10658 AstFactory.formalParameterList([p1, p2]), |
| 10659 AstFactory.blockFunctionBody2()); |
| 10660 _analyze5(p1); |
| 10661 _analyze5(p2); |
| 10662 DartType resultType = _analyze(node); |
| 10663 _assertFunctionType(dynamicType, <DartType>[dynamicType, dynamicType], null, |
| 10664 null, resultType); |
| 10665 _listener.assertNoErrors(); |
| 10666 } |
| 10667 |
| 10668 void test_visitFunctionExpression_normal_expression() { |
| 10669 // (p1, p2) -> 0 |
| 10670 DartType dynamicType = _typeProvider.dynamicType; |
| 10671 FormalParameter p = AstFactory.simpleFormalParameter3("p"); |
| 10672 _setType(p, dynamicType); |
| 10673 FunctionExpression node = _resolvedFunctionExpression( |
| 10674 AstFactory.formalParameterList([p]), |
| 10675 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10676 _analyze5(p); |
| 10677 DartType resultType = _analyze(node); |
| 10678 _assertFunctionType( |
| 10679 _typeProvider.intType, <DartType>[dynamicType], null, null, resultType); |
| 10680 _listener.assertNoErrors(); |
| 10681 } |
| 10682 |
| 10683 void test_visitFunctionExpression_normalAndNamed_block() { |
| 10684 // (p1, {p2 : 0}) {} |
| 10685 DartType dynamicType = _typeProvider.dynamicType; |
| 10686 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10687 _setType(p1, dynamicType); |
| 10688 FormalParameter p2 = AstFactory.namedFormalParameter( |
| 10689 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10690 _setType(p2, dynamicType); |
| 10691 FunctionExpression node = _resolvedFunctionExpression( |
| 10692 AstFactory.formalParameterList([p1, p2]), |
| 10693 AstFactory.blockFunctionBody2()); |
| 10694 _analyze5(p2); |
| 10695 DartType resultType = _analyze(node); |
| 10696 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); |
| 10697 expectedNamedTypes["p2"] = dynamicType; |
| 10698 _assertFunctionType(dynamicType, <DartType>[dynamicType], null, |
| 10699 expectedNamedTypes, resultType); |
| 10700 _listener.assertNoErrors(); |
| 10701 } |
| 10702 |
| 10703 void test_visitFunctionExpression_normalAndNamed_expression() { |
| 10704 // (p1, {p2 : 0}) -> 0 |
| 10705 DartType dynamicType = _typeProvider.dynamicType; |
| 10706 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10707 _setType(p1, dynamicType); |
| 10708 FormalParameter p2 = AstFactory.namedFormalParameter( |
| 10709 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10710 _setType(p2, dynamicType); |
| 10711 FunctionExpression node = _resolvedFunctionExpression( |
| 10712 AstFactory.formalParameterList([p1, p2]), |
| 10713 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10714 _analyze5(p2); |
| 10715 DartType resultType = _analyze(node); |
| 10716 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); |
| 10717 expectedNamedTypes["p2"] = dynamicType; |
| 10718 _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], null, |
| 10719 expectedNamedTypes, resultType); |
| 10720 _listener.assertNoErrors(); |
| 10721 } |
| 10722 |
| 10723 void test_visitFunctionExpression_normalAndPositional_block() { |
| 10724 // (p1, [p2 = 0]) {} |
| 10725 DartType dynamicType = _typeProvider.dynamicType; |
| 10726 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10727 _setType(p1, dynamicType); |
| 10728 FormalParameter p2 = AstFactory.positionalFormalParameter( |
| 10729 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10730 _setType(p2, dynamicType); |
| 10731 FunctionExpression node = _resolvedFunctionExpression( |
| 10732 AstFactory.formalParameterList([p1, p2]), |
| 10733 AstFactory.blockFunctionBody2()); |
| 10734 _analyze5(p1); |
| 10735 _analyze5(p2); |
| 10736 DartType resultType = _analyze(node); |
| 10737 _assertFunctionType(dynamicType, <DartType>[dynamicType], |
| 10738 <DartType>[dynamicType], null, resultType); |
| 10739 _listener.assertNoErrors(); |
| 10740 } |
| 10741 |
| 10742 void test_visitFunctionExpression_normalAndPositional_expression() { |
| 10743 // (p1, [p2 = 0]) -> 0 |
| 10744 DartType dynamicType = _typeProvider.dynamicType; |
| 10745 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10746 _setType(p1, dynamicType); |
| 10747 FormalParameter p2 = AstFactory.positionalFormalParameter( |
| 10748 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10749 _setType(p2, dynamicType); |
| 10750 FunctionExpression node = _resolvedFunctionExpression( |
| 10751 AstFactory.formalParameterList([p1, p2]), |
| 10752 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10753 _analyze5(p1); |
| 10754 _analyze5(p2); |
| 10755 DartType resultType = _analyze(node); |
| 10756 _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], |
| 10757 <DartType>[dynamicType], null, resultType); |
| 10758 _listener.assertNoErrors(); |
| 10759 } |
| 10760 |
| 10761 void test_visitFunctionExpression_positional_block() { |
| 10762 // ([p1 = 0, p2 = 0]) {} |
| 10763 DartType dynamicType = _typeProvider.dynamicType; |
| 10764 FormalParameter p1 = AstFactory.positionalFormalParameter( |
| 10765 AstFactory.simpleFormalParameter3("p1"), _resolvedInteger(0)); |
| 10766 _setType(p1, dynamicType); |
| 10767 FormalParameter p2 = AstFactory.positionalFormalParameter( |
| 10768 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10769 _setType(p2, dynamicType); |
| 10770 FunctionExpression node = _resolvedFunctionExpression( |
| 10771 AstFactory.formalParameterList([p1, p2]), |
| 10772 AstFactory.blockFunctionBody2()); |
| 10773 _analyze5(p1); |
| 10774 _analyze5(p2); |
| 10775 DartType resultType = _analyze(node); |
| 10776 _assertFunctionType(dynamicType, null, <DartType>[dynamicType, dynamicType], |
| 10777 null, resultType); |
| 10778 _listener.assertNoErrors(); |
| 10779 } |
| 10780 |
| 10781 void test_visitFunctionExpression_positional_expression() { |
| 10782 // ([p1 = 0, p2 = 0]) -> 0 |
| 10783 DartType dynamicType = _typeProvider.dynamicType; |
| 10784 FormalParameter p = AstFactory.positionalFormalParameter( |
| 10785 AstFactory.simpleFormalParameter3("p"), _resolvedInteger(0)); |
| 10786 _setType(p, dynamicType); |
| 10787 FunctionExpression node = _resolvedFunctionExpression( |
| 10788 AstFactory.formalParameterList([p]), |
| 10789 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10790 _analyze5(p); |
| 10791 DartType resultType = _analyze(node); |
| 10792 _assertFunctionType( |
| 10793 _typeProvider.intType, null, <DartType>[dynamicType], null, resultType); |
| 10794 _listener.assertNoErrors(); |
| 10795 } |
| 10796 |
| 10797 void test_visitIndexExpression_getter() { |
| 10798 // List a; |
| 10799 // a[2] |
| 10800 InterfaceType listType = _typeProvider.listType; |
| 10801 SimpleIdentifier identifier = _resolvedVariable(listType, "a"); |
| 10802 IndexExpression node = |
| 10803 AstFactory.indexExpression(identifier, _resolvedInteger(2)); |
| 10804 MethodElement indexMethod = listType.element.methods[0]; |
| 10805 node.staticElement = indexMethod; |
| 10806 expect(_analyze(node), same(listType.typeArguments[0])); |
| 10807 _listener.assertNoErrors(); |
| 10808 } |
| 10809 |
| 10810 void test_visitIndexExpression_setter() { |
| 10811 // List a; |
| 10812 // a[2] = 0 |
| 10813 InterfaceType listType = _typeProvider.listType; |
| 10814 SimpleIdentifier identifier = _resolvedVariable(listType, "a"); |
| 10815 IndexExpression node = |
| 10816 AstFactory.indexExpression(identifier, _resolvedInteger(2)); |
| 10817 MethodElement indexMethod = listType.element.methods[1]; |
| 10818 node.staticElement = indexMethod; |
| 10819 AstFactory.assignmentExpression(node, TokenType.EQ, AstFactory.integer(0)); |
| 10820 expect(_analyze(node), same(listType.typeArguments[0])); |
| 10821 _listener.assertNoErrors(); |
| 10822 } |
| 10823 |
| 10824 void test_visitIndexExpression_typeParameters() { |
| 10825 // List<int> list = ... |
| 10826 // list[0] |
| 10827 InterfaceType intType = _typeProvider.intType; |
| 10828 InterfaceType listType = _typeProvider.listType; |
| 10829 // (int) -> E |
| 10830 MethodElement methodElement = getMethod(listType, "[]"); |
| 10831 // "list" has type List<int> |
| 10832 SimpleIdentifier identifier = AstFactory.identifier3("list"); |
| 10833 InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]); |
| 10834 identifier.staticType = listOfIntType; |
| 10835 // list[0] has MethodElement element (int) -> E |
| 10836 IndexExpression indexExpression = |
| 10837 AstFactory.indexExpression(identifier, AstFactory.integer(0)); |
| 10838 MethodElement indexMethod = MethodMember.from(methodElement, listOfIntType); |
| 10839 indexExpression.staticElement = indexMethod; |
| 10840 // analyze and assert result of the index expression |
| 10841 expect(_analyze(indexExpression), same(intType)); |
| 10842 _listener.assertNoErrors(); |
| 10843 } |
| 10844 |
| 10845 void test_visitIndexExpression_typeParameters_inSetterContext() { |
| 10846 // List<int> list = ... |
| 10847 // list[0] = 0; |
| 10848 InterfaceType intType = _typeProvider.intType; |
| 10849 InterfaceType listType = _typeProvider.listType; |
| 10850 // (int, E) -> void |
| 10851 MethodElement methodElement = getMethod(listType, "[]="); |
| 10852 // "list" has type List<int> |
| 10853 SimpleIdentifier identifier = AstFactory.identifier3("list"); |
| 10854 InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]); |
| 10855 identifier.staticType = listOfIntType; |
| 10856 // list[0] has MethodElement element (int) -> E |
| 10857 IndexExpression indexExpression = |
| 10858 AstFactory.indexExpression(identifier, AstFactory.integer(0)); |
| 10859 MethodElement indexMethod = MethodMember.from(methodElement, listOfIntType); |
| 10860 indexExpression.staticElement = indexMethod; |
| 10861 // list[0] should be in a setter context |
| 10862 AstFactory.assignmentExpression( |
| 10863 indexExpression, TokenType.EQ, AstFactory.integer(0)); |
| 10864 // analyze and assert result of the index expression |
| 10865 expect(_analyze(indexExpression), same(intType)); |
| 10866 _listener.assertNoErrors(); |
| 10867 } |
| 10868 |
| 10869 void test_visitInstanceCreationExpression_named() { |
| 10870 // new C.m() |
| 10871 ClassElementImpl classElement = ElementFactory.classElement2("C"); |
| 10872 String constructorName = "m"; |
| 10873 ConstructorElementImpl constructor = |
| 10874 ElementFactory.constructorElement2(classElement, constructorName); |
| 10875 constructor.returnType = classElement.type; |
| 10876 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); |
| 10877 constructor.type = constructorType; |
| 10878 classElement.constructors = <ConstructorElement>[constructor]; |
| 10879 InstanceCreationExpression node = AstFactory.instanceCreationExpression2( |
| 10880 null, |
| 10881 AstFactory.typeName(classElement), |
| 10882 [AstFactory.identifier3(constructorName)]); |
| 10883 node.staticElement = constructor; |
| 10884 expect(_analyze(node), same(classElement.type)); |
| 10885 _listener.assertNoErrors(); |
| 10886 } |
| 10887 |
| 10888 void test_visitInstanceCreationExpression_typeParameters() { |
| 10889 // new C<I>() |
| 10890 ClassElementImpl elementC = ElementFactory.classElement2("C", ["E"]); |
| 10891 ClassElementImpl elementI = ElementFactory.classElement2("I"); |
| 10892 ConstructorElementImpl constructor = |
| 10893 ElementFactory.constructorElement2(elementC, null); |
| 10894 elementC.constructors = <ConstructorElement>[constructor]; |
| 10895 constructor.returnType = elementC.type; |
| 10896 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); |
| 10897 constructor.type = constructorType; |
| 10898 TypeName typeName = |
| 10899 AstFactory.typeName(elementC, [AstFactory.typeName(elementI)]); |
| 10900 typeName.type = elementC.type.substitute4(<DartType>[elementI.type]); |
| 10901 InstanceCreationExpression node = |
| 10902 AstFactory.instanceCreationExpression2(null, typeName); |
| 10903 node.staticElement = constructor; |
| 10904 InterfaceType interfaceType = _analyze(node) as InterfaceType; |
| 10905 List<DartType> typeArgs = interfaceType.typeArguments; |
| 10906 expect(typeArgs.length, 1); |
| 10907 expect(typeArgs[0], elementI.type); |
| 10908 _listener.assertNoErrors(); |
| 10909 } |
| 10910 |
| 10911 void test_visitInstanceCreationExpression_unnamed() { |
| 10912 // new C() |
| 10913 ClassElementImpl classElement = ElementFactory.classElement2("C"); |
| 10914 ConstructorElementImpl constructor = |
| 10915 ElementFactory.constructorElement2(classElement, null); |
| 10916 constructor.returnType = classElement.type; |
| 10917 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); |
| 10918 constructor.type = constructorType; |
| 10919 classElement.constructors = <ConstructorElement>[constructor]; |
| 10920 InstanceCreationExpression node = AstFactory.instanceCreationExpression2( |
| 10921 null, AstFactory.typeName(classElement)); |
| 10922 node.staticElement = constructor; |
| 10923 expect(_analyze(node), same(classElement.type)); |
| 10924 _listener.assertNoErrors(); |
| 10925 } |
| 10926 |
| 10927 void test_visitIntegerLiteral() { |
| 10928 // 42 |
| 10929 Expression node = _resolvedInteger(42); |
| 10930 expect(_analyze(node), same(_typeProvider.intType)); |
| 10931 _listener.assertNoErrors(); |
| 10932 } |
| 10933 |
| 10934 void test_visitIsExpression_negated() { |
| 10935 // a is! String |
| 10936 Expression node = AstFactory.isExpression( |
| 10937 _resolvedString("a"), true, AstFactory.typeName4("String")); |
| 10938 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10939 _listener.assertNoErrors(); |
| 10940 } |
| 10941 |
| 10942 void test_visitIsExpression_notNegated() { |
| 10943 // a is String |
| 10944 Expression node = AstFactory.isExpression( |
| 10945 _resolvedString("a"), false, AstFactory.typeName4("String")); |
| 10946 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10947 _listener.assertNoErrors(); |
| 10948 } |
| 10949 |
| 10950 void test_visitListLiteral_empty() { |
| 10951 // [] |
| 10952 Expression node = AstFactory.listLiteral(); |
| 10953 DartType resultType = _analyze(node); |
| 10954 _assertType2( |
| 10955 _typeProvider.listType |
| 10956 .substitute4(<DartType>[_typeProvider.dynamicType]), |
| 10957 resultType); |
| 10958 _listener.assertNoErrors(); |
| 10959 } |
| 10960 |
| 10961 void test_visitListLiteral_nonEmpty() { |
| 10962 // [0] |
| 10963 Expression node = AstFactory.listLiteral([_resolvedInteger(0)]); |
| 10964 DartType resultType = _analyze(node); |
| 10965 _assertType2( |
| 10966 _typeProvider.listType |
| 10967 .substitute4(<DartType>[_typeProvider.dynamicType]), |
| 10968 resultType); |
| 10969 _listener.assertNoErrors(); |
| 10970 } |
| 10971 |
| 10972 void test_visitMapLiteral_empty() { |
| 10973 // {} |
| 10974 Expression node = AstFactory.mapLiteral2(); |
| 10975 DartType resultType = _analyze(node); |
| 10976 _assertType2( |
| 10977 _typeProvider.mapType.substitute4( |
| 10978 <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]), |
| 10979 resultType); |
| 10980 _listener.assertNoErrors(); |
| 10981 } |
| 10982 |
| 10983 void test_visitMapLiteral_nonEmpty() { |
| 10984 // {"k" : 0} |
| 10985 Expression node = AstFactory |
| 10986 .mapLiteral2([AstFactory.mapLiteralEntry("k", _resolvedInteger(0))]); |
| 10987 DartType resultType = _analyze(node); |
| 10988 _assertType2( |
| 10989 _typeProvider.mapType.substitute4( |
| 10990 <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]), |
| 10991 resultType); |
| 10992 _listener.assertNoErrors(); |
| 10993 } |
| 10994 |
| 10995 void test_visitMethodInvocation_then() { |
| 10996 // then() |
| 10997 Expression node = AstFactory.methodInvocation(null, "then"); |
| 10998 _analyze(node); |
| 10999 _listener.assertNoErrors(); |
| 11000 } |
| 11001 |
| 11002 void test_visitNamedExpression() { |
| 11003 // n: a |
| 11004 Expression node = AstFactory.namedExpression2("n", _resolvedString("a")); |
| 11005 expect(_analyze(node), same(_typeProvider.stringType)); |
| 11006 _listener.assertNoErrors(); |
| 11007 } |
| 11008 |
| 11009 void test_visitNullLiteral() { |
| 11010 // null |
| 11011 Expression node = AstFactory.nullLiteral(); |
| 11012 expect(_analyze(node), same(_typeProvider.bottomType)); |
| 11013 _listener.assertNoErrors(); |
| 11014 } |
| 11015 |
| 11016 void test_visitParenthesizedExpression() { |
| 11017 // (0) |
| 11018 Expression node = AstFactory.parenthesizedExpression(_resolvedInteger(0)); |
| 11019 expect(_analyze(node), same(_typeProvider.intType)); |
| 11020 _listener.assertNoErrors(); |
| 11021 } |
| 11022 |
| 11023 void test_visitPostfixExpression_minusMinus() { |
| 11024 // 0-- |
| 11025 PostfixExpression node = AstFactory.postfixExpression( |
| 11026 _resolvedInteger(0), TokenType.MINUS_MINUS); |
| 11027 expect(_analyze(node), same(_typeProvider.intType)); |
| 11028 _listener.assertNoErrors(); |
| 11029 } |
| 11030 |
| 11031 void test_visitPostfixExpression_plusPlus() { |
| 11032 // 0++ |
| 11033 PostfixExpression node = |
| 11034 AstFactory.postfixExpression(_resolvedInteger(0), TokenType.PLUS_PLUS); |
| 11035 expect(_analyze(node), same(_typeProvider.intType)); |
| 11036 _listener.assertNoErrors(); |
| 11037 } |
| 11038 |
| 11039 void test_visitPrefixedIdentifier_getter() { |
| 11040 DartType boolType = _typeProvider.boolType; |
| 11041 PropertyAccessorElementImpl getter = |
| 11042 ElementFactory.getterElement("b", false, boolType); |
| 11043 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); |
| 11044 node.identifier.staticElement = getter; |
| 11045 expect(_analyze(node), same(boolType)); |
| 11046 _listener.assertNoErrors(); |
| 11047 } |
| 11048 |
| 11049 void test_visitPrefixedIdentifier_setter() { |
| 11050 DartType boolType = _typeProvider.boolType; |
| 11051 FieldElementImpl field = |
| 11052 ElementFactory.fieldElement("b", false, false, false, boolType); |
| 11053 PropertyAccessorElement setter = field.setter; |
| 11054 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); |
| 11055 node.identifier.staticElement = setter; |
| 11056 expect(_analyze(node), same(boolType)); |
| 11057 _listener.assertNoErrors(); |
| 11058 } |
| 11059 |
| 11060 void test_visitPrefixedIdentifier_variable() { |
| 11061 VariableElementImpl variable = ElementFactory.localVariableElement2("b"); |
| 11062 variable.type = _typeProvider.boolType; |
| 11063 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); |
| 11064 node.identifier.staticElement = variable; |
| 11065 expect(_analyze(node), same(_typeProvider.boolType)); |
| 11066 _listener.assertNoErrors(); |
| 11067 } |
| 11068 |
| 11069 void test_visitPrefixExpression_bang() { |
| 11070 // !0 |
| 11071 PrefixExpression node = |
| 11072 AstFactory.prefixExpression(TokenType.BANG, _resolvedInteger(0)); |
| 11073 expect(_analyze(node), same(_typeProvider.boolType)); |
| 11074 _listener.assertNoErrors(); |
| 11075 } |
| 11076 |
| 11077 void test_visitPrefixExpression_minus() { |
| 11078 // -0 |
| 11079 PrefixExpression node = |
| 11080 AstFactory.prefixExpression(TokenType.MINUS, _resolvedInteger(0)); |
| 11081 MethodElement minusMethod = getMethod(_typeProvider.numType, "-"); |
| 11082 node.staticElement = minusMethod; |
| 11083 expect(_analyze(node), same(_typeProvider.numType)); |
| 11084 _listener.assertNoErrors(); |
| 11085 } |
| 11086 |
| 11087 void test_visitPrefixExpression_minusMinus() { |
| 11088 // --0 |
| 11089 PrefixExpression node = |
| 11090 AstFactory.prefixExpression(TokenType.MINUS_MINUS, _resolvedInteger(0)); |
| 11091 MethodElement minusMethod = getMethod(_typeProvider.numType, "-"); |
| 11092 node.staticElement = minusMethod; |
| 11093 expect(_analyze(node), same(_typeProvider.intType)); |
| 11094 _listener.assertNoErrors(); |
| 11095 } |
| 11096 |
| 11097 void test_visitPrefixExpression_not() { |
| 11098 // !true |
| 11099 Expression node = AstFactory.prefixExpression( |
| 11100 TokenType.BANG, AstFactory.booleanLiteral(true)); |
| 11101 expect(_analyze(node), same(_typeProvider.boolType)); |
| 11102 _listener.assertNoErrors(); |
| 11103 } |
| 11104 |
| 11105 void test_visitPrefixExpression_plusPlus() { |
| 11106 // ++0 |
| 11107 PrefixExpression node = |
| 11108 AstFactory.prefixExpression(TokenType.PLUS_PLUS, _resolvedInteger(0)); |
| 11109 MethodElement plusMethod = getMethod(_typeProvider.numType, "+"); |
| 11110 node.staticElement = plusMethod; |
| 11111 expect(_analyze(node), same(_typeProvider.intType)); |
| 11112 _listener.assertNoErrors(); |
| 11113 } |
| 11114 |
| 11115 void test_visitPrefixExpression_tilde() { |
| 11116 // ~0 |
| 11117 PrefixExpression node = |
| 11118 AstFactory.prefixExpression(TokenType.TILDE, _resolvedInteger(0)); |
| 11119 MethodElement tildeMethod = getMethod(_typeProvider.intType, "~"); |
| 11120 node.staticElement = tildeMethod; |
| 11121 expect(_analyze(node), same(_typeProvider.intType)); |
| 11122 _listener.assertNoErrors(); |
| 11123 } |
| 11124 |
| 11125 void test_visitPropertyAccess_propagated_getter() { |
| 11126 DartType boolType = _typeProvider.boolType; |
| 11127 PropertyAccessorElementImpl getter = |
| 11128 ElementFactory.getterElement("b", false, boolType); |
| 11129 PropertyAccess node = |
| 11130 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); |
| 11131 node.propertyName.propagatedElement = getter; |
| 11132 expect(_analyze2(node, false), same(boolType)); |
| 11133 _listener.assertNoErrors(); |
| 11134 } |
| 11135 |
| 11136 void test_visitPropertyAccess_propagated_setter() { |
| 11137 DartType boolType = _typeProvider.boolType; |
| 11138 FieldElementImpl field = |
| 11139 ElementFactory.fieldElement("b", false, false, false, boolType); |
| 11140 PropertyAccessorElement setter = field.setter; |
| 11141 PropertyAccess node = |
| 11142 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); |
| 11143 node.propertyName.propagatedElement = setter; |
| 11144 expect(_analyze2(node, false), same(boolType)); |
| 11145 _listener.assertNoErrors(); |
| 11146 } |
| 11147 |
| 11148 void test_visitPropertyAccess_static_getter() { |
| 11149 DartType boolType = _typeProvider.boolType; |
| 11150 PropertyAccessorElementImpl getter = |
| 11151 ElementFactory.getterElement("b", false, boolType); |
| 11152 PropertyAccess node = |
| 11153 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); |
| 11154 node.propertyName.staticElement = getter; |
| 11155 expect(_analyze(node), same(boolType)); |
| 11156 _listener.assertNoErrors(); |
| 11157 } |
| 11158 |
| 11159 void test_visitPropertyAccess_static_setter() { |
| 11160 DartType boolType = _typeProvider.boolType; |
| 11161 FieldElementImpl field = |
| 11162 ElementFactory.fieldElement("b", false, false, false, boolType); |
| 11163 PropertyAccessorElement setter = field.setter; |
| 11164 PropertyAccess node = |
| 11165 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); |
| 11166 node.propertyName.staticElement = setter; |
| 11167 expect(_analyze(node), same(boolType)); |
| 11168 _listener.assertNoErrors(); |
| 11169 } |
| 11170 |
| 11171 void test_visitSimpleIdentifier_dynamic() { |
| 11172 // "dynamic" |
| 11173 SimpleIdentifier identifier = AstFactory.identifier3('dynamic'); |
| 11174 DynamicElementImpl element = DynamicElementImpl.instance; |
| 11175 identifier.staticElement = element; |
| 11176 identifier.staticType = _typeProvider.typeType; |
| 11177 expect(_analyze(identifier), same(_typeProvider.typeType)); |
| 11178 _listener.assertNoErrors(); |
| 11179 } |
| 11180 |
| 11181 void test_visitSimpleStringLiteral() { |
| 11182 // "a" |
| 11183 Expression node = _resolvedString("a"); |
| 11184 expect(_analyze(node), same(_typeProvider.stringType)); |
| 11185 _listener.assertNoErrors(); |
| 11186 } |
| 11187 |
| 11188 void test_visitStringInterpolation() { |
| 11189 // "a${'b'}c" |
| 11190 Expression node = AstFactory.string([ |
| 11191 AstFactory.interpolationString("a", "a"), |
| 11192 AstFactory.interpolationExpression(_resolvedString("b")), |
| 11193 AstFactory.interpolationString("c", "c") |
| 11194 ]); |
| 11195 expect(_analyze(node), same(_typeProvider.stringType)); |
| 11196 _listener.assertNoErrors(); |
| 11197 } |
| 11198 |
| 11199 void test_visitSuperExpression() { |
| 11200 // super |
| 11201 InterfaceType superType = ElementFactory.classElement2("A").type; |
| 11202 InterfaceType thisType = ElementFactory.classElement("B", superType).type; |
| 11203 Expression node = AstFactory.superExpression(); |
| 11204 expect(_analyze3(node, thisType), same(thisType)); |
| 11205 _listener.assertNoErrors(); |
| 11206 } |
| 11207 |
| 11208 void test_visitSymbolLiteral() { |
| 11209 expect(_analyze(AstFactory.symbolLiteral(["a"])), |
| 11210 same(_typeProvider.symbolType)); |
| 11211 } |
| 11212 |
| 11213 void test_visitThisExpression() { |
| 11214 // this |
| 11215 InterfaceType thisType = ElementFactory |
| 11216 .classElement("B", ElementFactory.classElement2("A").type) |
| 11217 .type; |
| 11218 Expression node = AstFactory.thisExpression(); |
| 11219 expect(_analyze3(node, thisType), same(thisType)); |
| 11220 _listener.assertNoErrors(); |
| 11221 } |
| 11222 |
| 11223 void test_visitThrowExpression_withoutValue() { |
| 11224 // throw |
| 11225 Expression node = AstFactory.throwExpression(); |
| 11226 expect(_analyze(node), same(_typeProvider.bottomType)); |
| 11227 _listener.assertNoErrors(); |
| 11228 } |
| 11229 |
| 11230 void test_visitThrowExpression_withValue() { |
| 11231 // throw 0 |
| 11232 Expression node = AstFactory.throwExpression2(_resolvedInteger(0)); |
| 11233 expect(_analyze(node), same(_typeProvider.bottomType)); |
| 11234 _listener.assertNoErrors(); |
| 11235 } |
| 11236 |
| 11237 /** |
| 11238 * Return the type associated with the given expression after the static type
analyzer has |
| 11239 * computed a type for it. |
| 11240 * |
| 11241 * @param node the expression with which the type is associated |
| 11242 * @return the type associated with the expression |
| 11243 */ |
| 11244 DartType _analyze(Expression node) => _analyze4(node, null, true); |
| 11245 |
| 11246 /** |
| 11247 * Return the type associated with the given expression after the static or pr
opagated type |
| 11248 * analyzer has computed a type for it. |
| 11249 * |
| 11250 * @param node the expression with which the type is associated |
| 11251 * @param useStaticType `true` if the static type is being requested, and `fal
se` if |
| 11252 * the propagated type is being requested |
| 11253 * @return the type associated with the expression |
| 11254 */ |
| 11255 DartType _analyze2(Expression node, bool useStaticType) => |
| 11256 _analyze4(node, null, useStaticType); |
| 11257 |
| 11258 /** |
| 11259 * Return the type associated with the given expression after the static type
analyzer has |
| 11260 * computed a type for it. |
| 11261 * |
| 11262 * @param node the expression with which the type is associated |
| 11263 * @param thisType the type of 'this' |
| 11264 * @return the type associated with the expression |
| 11265 */ |
| 11266 DartType _analyze3(Expression node, InterfaceType thisType) => |
| 11267 _analyze4(node, thisType, true); |
| 11268 |
| 11269 /** |
| 11270 * Return the type associated with the given expression after the static type
analyzer has |
| 11271 * computed a type for it. |
| 11272 * |
| 11273 * @param node the expression with which the type is associated |
| 11274 * @param thisType the type of 'this' |
| 11275 * @param useStaticType `true` if the static type is being requested, and `fal
se` if |
| 11276 * the propagated type is being requested |
| 11277 * @return the type associated with the expression |
| 11278 */ |
| 11279 DartType _analyze4( |
| 11280 Expression node, InterfaceType thisType, bool useStaticType) { |
| 11281 try { |
| 11282 _analyzer.thisType = thisType; |
| 11283 } catch (exception) { |
| 11284 throw new IllegalArgumentException( |
| 11285 "Could not set type of 'this'", exception); |
| 11286 } |
| 11287 node.accept(_analyzer); |
| 11288 if (useStaticType) { |
| 11289 return node.staticType; |
| 11290 } else { |
| 11291 return node.propagatedType; |
| 11292 } |
| 11293 } |
| 11294 |
| 11295 /** |
| 11296 * Return the type associated with the given parameter after the static type a
nalyzer has computed |
| 11297 * a type for it. |
| 11298 * |
| 11299 * @param node the parameter with which the type is associated |
| 11300 * @return the type associated with the parameter |
| 11301 */ |
| 11302 DartType _analyze5(FormalParameter node) { |
| 11303 node.accept(_analyzer); |
| 11304 return (node.identifier.staticElement as ParameterElement).type; |
| 11305 } |
| 11306 |
| 11307 /** |
| 11308 * Assert that the actual type is a function type with the expected characteri
stics. |
| 11309 * |
| 11310 * @param expectedReturnType the expected return type of the function |
| 11311 * @param expectedNormalTypes the expected types of the normal parameters |
| 11312 * @param expectedOptionalTypes the expected types of the optional parameters |
| 11313 * @param expectedNamedTypes the expected types of the named parameters |
| 11314 * @param actualType the type being tested |
| 11315 */ |
| 11316 void _assertFunctionType( |
| 11317 DartType expectedReturnType, |
| 11318 List<DartType> expectedNormalTypes, |
| 11319 List<DartType> expectedOptionalTypes, |
| 11320 Map<String, DartType> expectedNamedTypes, |
| 11321 DartType actualType) { |
| 11322 EngineTestCase.assertInstanceOf( |
| 11323 (obj) => obj is FunctionType, FunctionType, actualType); |
| 11324 FunctionType functionType = actualType as FunctionType; |
| 11325 List<DartType> normalTypes = functionType.normalParameterTypes; |
| 11326 if (expectedNormalTypes == null) { |
| 11327 expect(normalTypes, hasLength(0)); |
| 11328 } else { |
| 11329 int expectedCount = expectedNormalTypes.length; |
| 11330 expect(normalTypes, hasLength(expectedCount)); |
| 11331 for (int i = 0; i < expectedCount; i++) { |
| 11332 expect(normalTypes[i], same(expectedNormalTypes[i])); |
| 11333 } |
| 11334 } |
| 11335 List<DartType> optionalTypes = functionType.optionalParameterTypes; |
| 11336 if (expectedOptionalTypes == null) { |
| 11337 expect(optionalTypes, hasLength(0)); |
| 11338 } else { |
| 11339 int expectedCount = expectedOptionalTypes.length; |
| 11340 expect(optionalTypes, hasLength(expectedCount)); |
| 11341 for (int i = 0; i < expectedCount; i++) { |
| 11342 expect(optionalTypes[i], same(expectedOptionalTypes[i])); |
| 11343 } |
| 11344 } |
| 11345 Map<String, DartType> namedTypes = functionType.namedParameterTypes; |
| 11346 if (expectedNamedTypes == null) { |
| 11347 expect(namedTypes, hasLength(0)); |
| 11348 } else { |
| 11349 expect(namedTypes, hasLength(expectedNamedTypes.length)); |
| 11350 expectedNamedTypes.forEach((String name, DartType type) { |
| 11351 expect(namedTypes[name], same(type)); |
| 11352 }); |
| 11353 } |
| 11354 expect(functionType.returnType, equals(expectedReturnType)); |
| 11355 } |
| 11356 |
| 11357 void _assertType( |
| 11358 InterfaceTypeImpl expectedType, InterfaceTypeImpl actualType) { |
| 11359 expect(actualType.displayName, expectedType.displayName); |
| 11360 expect(actualType.element, expectedType.element); |
| 11361 List<DartType> expectedArguments = expectedType.typeArguments; |
| 11362 int length = expectedArguments.length; |
| 11363 List<DartType> actualArguments = actualType.typeArguments; |
| 11364 expect(actualArguments, hasLength(length)); |
| 11365 for (int i = 0; i < length; i++) { |
| 11366 _assertType2(expectedArguments[i], actualArguments[i]); |
| 11367 } |
| 11368 } |
| 11369 |
| 11370 void _assertType2(DartType expectedType, DartType actualType) { |
| 11371 if (expectedType is InterfaceTypeImpl) { |
| 11372 EngineTestCase.assertInstanceOf( |
| 11373 (obj) => obj is InterfaceTypeImpl, InterfaceTypeImpl, actualType); |
| 11374 _assertType(expectedType, actualType as InterfaceTypeImpl); |
| 11375 } |
| 11376 // TODO(brianwilkerson) Compare other kinds of types then make this a shared |
| 11377 // utility method. |
| 11378 } |
| 11379 |
| 11380 /** |
| 11381 * Create the analyzer used by the tests. |
| 11382 * |
| 11383 * @return the analyzer to be used by the tests |
| 11384 */ |
| 11385 StaticTypeAnalyzer _createAnalyzer() { |
| 11386 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 11387 FileBasedSource source = |
| 11388 new FileBasedSource(FileUtilities2.createFile("/lib.dart")); |
| 11389 CompilationUnitElementImpl definingCompilationUnit = |
| 11390 new CompilationUnitElementImpl("lib.dart"); |
| 11391 definingCompilationUnit.librarySource = |
| 11392 definingCompilationUnit.source = source; |
| 11393 LibraryElementImpl definingLibrary = |
| 11394 new LibraryElementImpl.forNode(context, null); |
| 11395 definingLibrary.definingCompilationUnit = definingCompilationUnit; |
| 11396 Library library = new Library(context, _listener, source); |
| 11397 library.libraryElement = definingLibrary; |
| 11398 _visitor = new ResolverVisitor( |
| 11399 library.libraryElement, source, _typeProvider, library.errorListener, |
| 11400 nameScope: library.libraryScope, |
| 11401 inheritanceManager: library.inheritanceManager); |
| 11402 _visitor.overrideManager.enterScope(); |
| 11403 try { |
| 11404 return _visitor.typeAnalyzer; |
| 11405 } catch (exception) { |
| 11406 throw new IllegalArgumentException( |
| 11407 "Could not create analyzer", exception); |
| 11408 } |
| 11409 } |
| 11410 |
| 11411 DartType _flatten(DartType type) => |
| 11412 StaticTypeAnalyzer.flattenFutures(_typeProvider, type); |
| 11413 |
| 11414 /** |
| 11415 * Return a simple identifier that has been resolved to a variable element wit
h the given type. |
| 11416 * |
| 11417 * @param type the type of the variable being represented |
| 11418 * @param variableName the name of the variable |
| 11419 * @return a simple identifier that has been resolved to a variable element wi
th the given type |
| 11420 */ |
| 11421 SimpleIdentifier _propagatedVariable( |
| 11422 InterfaceType type, String variableName) { |
| 11423 SimpleIdentifier identifier = AstFactory.identifier3(variableName); |
| 11424 VariableElementImpl element = |
| 11425 ElementFactory.localVariableElement(identifier); |
| 11426 element.type = type; |
| 11427 identifier.staticType = _typeProvider.dynamicType; |
| 11428 identifier.propagatedElement = element; |
| 11429 identifier.propagatedType = type; |
| 11430 return identifier; |
| 11431 } |
| 11432 |
| 11433 /** |
| 11434 * Return an integer literal that has been resolved to the correct type. |
| 11435 * |
| 11436 * @param value the value of the literal |
| 11437 * @return an integer literal that has been resolved to the correct type |
| 11438 */ |
| 11439 DoubleLiteral _resolvedDouble(double value) { |
| 11440 DoubleLiteral literal = AstFactory.doubleLiteral(value); |
| 11441 literal.staticType = _typeProvider.doubleType; |
| 11442 return literal; |
| 11443 } |
| 11444 |
| 11445 /** |
| 11446 * Create a function expression that has an element associated with it, where
the element has an |
| 11447 * incomplete type associated with it (just like the one |
| 11448 * [ElementBuilder.visitFunctionExpression] would have built if we had |
| 11449 * run it). |
| 11450 * |
| 11451 * @param parameters the parameters to the function |
| 11452 * @param body the body of the function |
| 11453 * @return a resolved function expression |
| 11454 */ |
| 11455 FunctionExpression _resolvedFunctionExpression( |
| 11456 FormalParameterList parameters, FunctionBody body) { |
| 11457 List<ParameterElement> parameterElements = new List<ParameterElement>(); |
| 11458 for (FormalParameter parameter in parameters.parameters) { |
| 11459 ParameterElementImpl element = |
| 11460 new ParameterElementImpl.forNode(parameter.identifier); |
| 11461 element.parameterKind = parameter.kind; |
| 11462 element.type = _typeProvider.dynamicType; |
| 11463 parameter.identifier.staticElement = element; |
| 11464 parameterElements.add(element); |
| 11465 } |
| 11466 FunctionExpression node = AstFactory.functionExpression2(parameters, body); |
| 11467 FunctionElementImpl element = new FunctionElementImpl.forNode(null); |
| 11468 element.parameters = parameterElements; |
| 11469 element.type = new FunctionTypeImpl(element); |
| 11470 node.element = element; |
| 11471 return node; |
| 11472 } |
| 11473 |
| 11474 /** |
| 11475 * Return an integer literal that has been resolved to the correct type. |
| 11476 * |
| 11477 * @param value the value of the literal |
| 11478 * @return an integer literal that has been resolved to the correct type |
| 11479 */ |
| 11480 IntegerLiteral _resolvedInteger(int value) { |
| 11481 IntegerLiteral literal = AstFactory.integer(value); |
| 11482 literal.staticType = _typeProvider.intType; |
| 11483 return literal; |
| 11484 } |
| 11485 |
| 11486 /** |
| 11487 * Return a string literal that has been resolved to the correct type. |
| 11488 * |
| 11489 * @param value the value of the literal |
| 11490 * @return a string literal that has been resolved to the correct type |
| 11491 */ |
| 11492 SimpleStringLiteral _resolvedString(String value) { |
| 11493 SimpleStringLiteral string = AstFactory.string2(value); |
| 11494 string.staticType = _typeProvider.stringType; |
| 11495 return string; |
| 11496 } |
| 11497 |
| 11498 /** |
| 11499 * Return a simple identifier that has been resolved to a variable element wit
h the given type. |
| 11500 * |
| 11501 * @param type the type of the variable being represented |
| 11502 * @param variableName the name of the variable |
| 11503 * @return a simple identifier that has been resolved to a variable element wi
th the given type |
| 11504 */ |
| 11505 SimpleIdentifier _resolvedVariable(InterfaceType type, String variableName) { |
| 11506 SimpleIdentifier identifier = AstFactory.identifier3(variableName); |
| 11507 VariableElementImpl element = |
| 11508 ElementFactory.localVariableElement(identifier); |
| 11509 element.type = type; |
| 11510 identifier.staticElement = element; |
| 11511 identifier.staticType = type; |
| 11512 return identifier; |
| 11513 } |
| 11514 |
| 11515 /** |
| 11516 * Set the type of the given parameter to the given type. |
| 11517 * |
| 11518 * @param parameter the parameter whose type is to be set |
| 11519 * @param type the new type of the given parameter |
| 11520 */ |
| 11521 void _setType(FormalParameter parameter, DartType type) { |
| 11522 SimpleIdentifier identifier = parameter.identifier; |
| 11523 Element element = identifier.staticElement; |
| 11524 if (element is! ParameterElement) { |
| 11525 element = new ParameterElementImpl.forNode(identifier); |
| 11526 identifier.staticElement = element; |
| 11527 } |
| 11528 (element as ParameterElementImpl).type = type; |
| 11529 } |
| 11530 } |
| 11531 |
| 11532 /** |
| 11533 * Instances of the class `StaticTypeVerifier` verify that all of the nodes in a
n AST |
| 11534 * structure that should have a static type associated with them do have a stati
c type. |
| 11535 */ |
| 11536 class StaticTypeVerifier extends GeneralizingAstVisitor<Object> { |
| 11537 /** |
| 11538 * A list containing all of the AST Expression nodes that were not resolved. |
| 11539 */ |
| 11540 List<Expression> _unresolvedExpressions = new List<Expression>(); |
| 11541 |
| 11542 /** |
| 11543 * A list containing all of the AST Expression nodes for which a propagated ty
pe was computed but |
| 11544 * where that type was not more specific than the static type. |
| 11545 */ |
| 11546 List<Expression> _invalidlyPropagatedExpressions = new List<Expression>(); |
| 11547 |
| 11548 /** |
| 11549 * A list containing all of the AST TypeName nodes that were not resolved. |
| 11550 */ |
| 11551 List<TypeName> _unresolvedTypes = new List<TypeName>(); |
| 11552 |
| 11553 /** |
| 11554 * Counter for the number of Expression nodes visited that are resolved. |
| 11555 */ |
| 11556 int _resolvedExpressionCount = 0; |
| 11557 |
| 11558 /** |
| 11559 * Counter for the number of Expression nodes visited that have propagated typ
e information. |
| 11560 */ |
| 11561 int _propagatedExpressionCount = 0; |
| 11562 |
| 11563 /** |
| 11564 * Counter for the number of TypeName nodes visited that are resolved. |
| 11565 */ |
| 11566 int _resolvedTypeCount = 0; |
| 11567 |
| 11568 /** |
| 11569 * Assert that all of the visited nodes have a static type associated with the
m. |
| 11570 */ |
| 11571 void assertResolved() { |
| 11572 if (!_unresolvedExpressions.isEmpty || !_unresolvedTypes.isEmpty) { |
| 11573 StringBuffer buffer = new StringBuffer(); |
| 11574 int unresolvedTypeCount = _unresolvedTypes.length; |
| 11575 if (unresolvedTypeCount > 0) { |
| 11576 buffer.write("Failed to resolve "); |
| 11577 buffer.write(unresolvedTypeCount); |
| 11578 buffer.write(" of "); |
| 11579 buffer.write(_resolvedTypeCount + unresolvedTypeCount); |
| 11580 buffer.writeln(" type names:"); |
| 11581 for (TypeName identifier in _unresolvedTypes) { |
| 11582 buffer.write(" "); |
| 11583 buffer.write(identifier.toString()); |
| 11584 buffer.write(" ("); |
| 11585 buffer.write(_getFileName(identifier)); |
| 11586 buffer.write(" : "); |
| 11587 buffer.write(identifier.offset); |
| 11588 buffer.writeln(")"); |
| 11589 } |
| 11590 } |
| 11591 int unresolvedExpressionCount = _unresolvedExpressions.length; |
| 11592 if (unresolvedExpressionCount > 0) { |
| 11593 buffer.writeln("Failed to resolve "); |
| 11594 buffer.write(unresolvedExpressionCount); |
| 11595 buffer.write(" of "); |
| 11596 buffer.write(_resolvedExpressionCount + unresolvedExpressionCount); |
| 11597 buffer.writeln(" expressions:"); |
| 11598 for (Expression expression in _unresolvedExpressions) { |
| 11599 buffer.write(" "); |
| 11600 buffer.write(expression.toString()); |
| 11601 buffer.write(" ("); |
| 11602 buffer.write(_getFileName(expression)); |
| 11603 buffer.write(" : "); |
| 11604 buffer.write(expression.offset); |
| 11605 buffer.writeln(")"); |
| 11606 } |
| 11607 } |
| 11608 int invalidlyPropagatedExpressionCount = |
| 11609 _invalidlyPropagatedExpressions.length; |
| 11610 if (invalidlyPropagatedExpressionCount > 0) { |
| 11611 buffer.writeln("Incorrectly propagated "); |
| 11612 buffer.write(invalidlyPropagatedExpressionCount); |
| 11613 buffer.write(" of "); |
| 11614 buffer.write(_propagatedExpressionCount); |
| 11615 buffer.writeln(" expressions:"); |
| 11616 for (Expression expression in _invalidlyPropagatedExpressions) { |
| 11617 buffer.write(" "); |
| 11618 buffer.write(expression.toString()); |
| 11619 buffer.write(" ["); |
| 11620 buffer.write(expression.staticType.displayName); |
| 11621 buffer.write(", "); |
| 11622 buffer.write(expression.propagatedType.displayName); |
| 11623 buffer.writeln("]"); |
| 11624 buffer.write(" "); |
| 11625 buffer.write(_getFileName(expression)); |
| 11626 buffer.write(" : "); |
| 11627 buffer.write(expression.offset); |
| 11628 buffer.writeln(")"); |
| 11629 } |
| 11630 } |
| 11631 fail(buffer.toString()); |
| 11632 } |
| 11633 } |
| 11634 |
| 11635 @override |
| 11636 Object visitBreakStatement(BreakStatement node) => null; |
| 11637 |
| 11638 @override |
| 11639 Object visitCommentReference(CommentReference node) => null; |
| 11640 |
| 11641 @override |
| 11642 Object visitContinueStatement(ContinueStatement node) => null; |
| 11643 |
| 11644 @override |
| 11645 Object visitExportDirective(ExportDirective node) => null; |
| 11646 |
| 11647 @override |
| 11648 Object visitExpression(Expression node) { |
| 11649 node.visitChildren(this); |
| 11650 DartType staticType = node.staticType; |
| 11651 if (staticType == null) { |
| 11652 _unresolvedExpressions.add(node); |
| 11653 } else { |
| 11654 _resolvedExpressionCount++; |
| 11655 DartType propagatedType = node.propagatedType; |
| 11656 if (propagatedType != null) { |
| 11657 _propagatedExpressionCount++; |
| 11658 if (!propagatedType.isMoreSpecificThan(staticType)) { |
| 11659 _invalidlyPropagatedExpressions.add(node); |
| 11660 } |
| 11661 } |
| 11662 } |
| 11663 return null; |
| 11664 } |
| 11665 |
| 11666 @override |
| 11667 Object visitImportDirective(ImportDirective node) => null; |
| 11668 |
| 11669 @override |
| 11670 Object visitLabel(Label node) => null; |
| 11671 |
| 11672 @override |
| 11673 Object visitLibraryIdentifier(LibraryIdentifier node) => null; |
| 11674 |
| 11675 @override |
| 11676 Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 11677 // In cases where we have a prefixed identifier where the prefix is dynamic, |
| 11678 // we don't want to assert that the node will have a type. |
| 11679 if (node.staticType == null && node.prefix.staticType.isDynamic) { |
| 11680 return null; |
| 11681 } |
| 11682 return super.visitPrefixedIdentifier(node); |
| 11683 } |
| 11684 |
| 11685 @override |
| 11686 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 11687 // In cases where identifiers are being used for something other than an |
| 11688 // expressions, then they can be ignored. |
| 11689 AstNode parent = node.parent; |
| 11690 if (parent is MethodInvocation && identical(node, parent.methodName)) { |
| 11691 return null; |
| 11692 } else if (parent is RedirectingConstructorInvocation && |
| 11693 identical(node, parent.constructorName)) { |
| 11694 return null; |
| 11695 } else if (parent is SuperConstructorInvocation && |
| 11696 identical(node, parent.constructorName)) { |
| 11697 return null; |
| 11698 } else if (parent is ConstructorName && identical(node, parent.name)) { |
| 11699 return null; |
| 11700 } else if (parent is ConstructorFieldInitializer && |
| 11701 identical(node, parent.fieldName)) { |
| 11702 return null; |
| 11703 } else if (node.staticElement is PrefixElement) { |
| 11704 // Prefixes don't have a type. |
| 11705 return null; |
| 11706 } |
| 11707 return super.visitSimpleIdentifier(node); |
| 11708 } |
| 11709 |
| 11710 @override |
| 11711 Object visitTypeName(TypeName node) { |
| 11712 // Note: do not visit children from this node, the child SimpleIdentifier in |
| 11713 // TypeName (i.e. "String") does not have a static type defined. |
| 11714 if (node.type == null) { |
| 11715 _unresolvedTypes.add(node); |
| 11716 } else { |
| 11717 _resolvedTypeCount++; |
| 11718 } |
| 11719 return null; |
| 11720 } |
| 11721 |
| 11722 String _getFileName(AstNode node) { |
| 11723 // TODO (jwren) there are two copies of this method, one here and one in |
| 11724 // ResolutionVerifier, they should be resolved into a single method |
| 11725 if (node != null) { |
| 11726 AstNode root = node.root; |
| 11727 if (root is CompilationUnit) { |
| 11728 CompilationUnit rootCU = root; |
| 11729 if (rootCU.element != null) { |
| 11730 return rootCU.element.source.fullName; |
| 11731 } else { |
| 11732 return "<unknown file- CompilationUnit.getElement() returned null>"; |
| 11733 } |
| 11734 } else { |
| 11735 return "<unknown file- CompilationUnit.getRoot() is not a CompilationUni
t>"; |
| 11736 } |
| 11737 } |
| 11738 return "<unknown file- ASTNode is null>"; |
| 11739 } |
| 11740 } |
| 11741 |
| 11742 /** |
| 11743 * The class `StrictModeTest` contains tests to ensure that the correct errors a
nd warnings |
| 11744 * are reported when the analysis engine is run in strict mode. |
| 11745 */ |
| 11746 @reflectiveTest |
| 11747 class StrictModeTest extends ResolverTestCase { |
| 11748 void fail_for() { |
| 11749 Source source = addSource(r''' |
| 11750 int f(List<int> list) { |
| 11751 num sum = 0; |
| 11752 for (num i = 0; i < list.length; i++) { |
| 11753 sum += list[i]; |
| 11754 } |
| 11755 }'''); |
| 11756 computeLibrarySourceErrors(source); |
| 11757 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11758 } |
| 11759 |
| 11760 @override |
| 11761 void setUp() { |
| 11762 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 11763 options.hint = false; |
| 11764 resetWithOptions(options); |
| 11765 } |
| 11766 |
| 11767 void test_assert_is() { |
| 11768 Source source = addSource(r''' |
| 11769 int f(num n) { |
| 11770 assert (n is int); |
| 11771 return n & 0x0F; |
| 11772 }'''); |
| 11773 computeLibrarySourceErrors(source); |
| 11774 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11775 } |
| 11776 |
| 11777 void test_conditional_and_is() { |
| 11778 Source source = addSource(r''' |
| 11779 int f(num n) { |
| 11780 return (n is int && n > 0) ? n & 0x0F : 0; |
| 11781 }'''); |
| 11782 computeLibrarySourceErrors(source); |
| 11783 assertNoErrors(source); |
| 11784 } |
| 11785 |
| 11786 void test_conditional_is() { |
| 11787 Source source = addSource(r''' |
| 11788 int f(num n) { |
| 11789 return (n is int) ? n & 0x0F : 0; |
| 11790 }'''); |
| 11791 computeLibrarySourceErrors(source); |
| 11792 assertNoErrors(source); |
| 11793 } |
| 11794 |
| 11795 void test_conditional_isNot() { |
| 11796 Source source = addSource(r''' |
| 11797 int f(num n) { |
| 11798 return (n is! int) ? 0 : n & 0x0F; |
| 11799 }'''); |
| 11800 computeLibrarySourceErrors(source); |
| 11801 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11802 } |
| 11803 |
| 11804 void test_conditional_or_is() { |
| 11805 Source source = addSource(r''' |
| 11806 int f(num n) { |
| 11807 return (n is! int || n < 0) ? 0 : n & 0x0F; |
| 11808 }'''); |
| 11809 computeLibrarySourceErrors(source); |
| 11810 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11811 } |
| 11812 |
| 11813 void test_forEach() { |
| 11814 Source source = addSource(r''' |
| 11815 int f(List<int> list) { |
| 11816 num sum = 0; |
| 11817 for (num n in list) { |
| 11818 sum += n & 0x0F; |
| 11819 } |
| 11820 }'''); |
| 11821 computeLibrarySourceErrors(source); |
| 11822 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11823 } |
| 11824 |
| 11825 void test_if_and_is() { |
| 11826 Source source = addSource(r''' |
| 11827 int f(num n) { |
| 11828 if (n is int && n > 0) { |
| 11829 return n & 0x0F; |
| 11830 } |
| 11831 return 0; |
| 11832 }'''); |
| 11833 computeLibrarySourceErrors(source); |
| 11834 assertNoErrors(source); |
| 11835 } |
| 11836 |
| 11837 void test_if_is() { |
| 11838 Source source = addSource(r''' |
| 11839 int f(num n) { |
| 11840 if (n is int) { |
| 11841 return n & 0x0F; |
| 11842 } |
| 11843 return 0; |
| 11844 }'''); |
| 11845 computeLibrarySourceErrors(source); |
| 11846 assertNoErrors(source); |
| 11847 } |
| 11848 |
| 11849 void test_if_isNot() { |
| 11850 Source source = addSource(r''' |
| 11851 int f(num n) { |
| 11852 if (n is! int) { |
| 11853 return 0; |
| 11854 } else { |
| 11855 return n & 0x0F; |
| 11856 } |
| 11857 }'''); |
| 11858 computeLibrarySourceErrors(source); |
| 11859 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11860 } |
| 11861 |
| 11862 void test_if_isNot_abrupt() { |
| 11863 Source source = addSource(r''' |
| 11864 int f(num n) { |
| 11865 if (n is! int) { |
| 11866 return 0; |
| 11867 } |
| 11868 return n & 0x0F; |
| 11869 }'''); |
| 11870 computeLibrarySourceErrors(source); |
| 11871 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11872 } |
| 11873 |
| 11874 void test_if_or_is() { |
| 11875 Source source = addSource(r''' |
| 11876 int f(num n) { |
| 11877 if (n is! int || n < 0) { |
| 11878 return 0; |
| 11879 } else { |
| 11880 return n & 0x0F; |
| 11881 } |
| 11882 }'''); |
| 11883 computeLibrarySourceErrors(source); |
| 11884 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11885 } |
| 11886 |
| 11887 void test_localVar() { |
| 11888 Source source = addSource(r''' |
| 11889 int f() { |
| 11890 num n = 1234; |
| 11891 return n & 0x0F; |
| 11892 }'''); |
| 11893 computeLibrarySourceErrors(source); |
| 11894 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11895 } |
| 11896 } |
| 11897 |
| 11898 /** |
| 11899 * Strong mode static analyzer end to end tests |
| 11900 */ |
| 11901 @reflectiveTest |
| 11902 class StrongModeStaticTypeAnalyzer2Test extends _StaticTypeAnalyzer2TestShared { |
| 11903 void setUp() { |
| 11904 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 11905 options.strongMode = true; |
| 11906 resetWithOptions(options); |
| 11907 } |
| 11908 |
| 11909 void test_dynamicObjectGetter_hashCode() { |
| 11910 String code = r''' |
| 11911 main() { |
| 11912 dynamic a = null; |
| 11913 var foo = a.hashCode; |
| 11914 } |
| 11915 '''; |
| 11916 _resolveTestUnit(code); |
| 11917 |
| 11918 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 11919 VariableDeclaration declaration = |
| 11920 identifier.getAncestor((node) => node is VariableDeclaration); |
| 11921 expect(declaration.initializer.staticType.name, 'int'); |
| 11922 expect(declaration.initializer.propagatedType, isNull); |
| 11923 } |
| 11924 |
| 11925 void test_dynamicObjectMethod_toString() { |
| 11926 String code = r''' |
| 11927 main() { |
| 11928 dynamic a = null; |
| 11929 var foo = a.toString(); |
| 11930 } |
| 11931 '''; |
| 11932 _resolveTestUnit(code); |
| 11933 |
| 11934 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 11935 VariableDeclaration declaration = |
| 11936 identifier.getAncestor((node) => node is VariableDeclaration); |
| 11937 expect(declaration.initializer.staticType.name, 'String'); |
| 11938 expect(declaration.initializer.propagatedType, isNull); |
| 11939 } |
| 11940 |
| 11941 void test_pseudoGeneric_max_doubleDouble() { |
| 11942 String code = r''' |
| 11943 import 'dart:math'; |
| 11944 main() { |
| 11945 var foo = max(1.0, 2.0); |
| 11946 } |
| 11947 '''; |
| 11948 _resolveTestUnit(code); |
| 11949 |
| 11950 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 11951 VariableDeclaration declaration = |
| 11952 identifier.getAncestor((node) => node is VariableDeclaration); |
| 11953 expect(declaration.initializer.staticType.name, 'double'); |
| 11954 expect(declaration.initializer.propagatedType, isNull); |
| 11955 } |
| 11956 |
| 11957 void test_pseudoGeneric_max_doubleInt() { |
| 11958 String code = r''' |
| 11959 import 'dart:math'; |
| 11960 main() { |
| 11961 var foo = max(1.0, 2); |
| 11962 } |
| 11963 '''; |
| 11964 _resolveTestUnit(code); |
| 11965 |
| 11966 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 11967 VariableDeclaration declaration = |
| 11968 identifier.getAncestor((node) => node is VariableDeclaration); |
| 11969 expect(declaration.initializer.staticType.name, 'num'); |
| 11970 expect(declaration.initializer.propagatedType, isNull); |
| 11971 } |
| 11972 |
| 11973 void test_pseudoGeneric_max_intDouble() { |
| 11974 String code = r''' |
| 11975 import 'dart:math'; |
| 11976 main() { |
| 11977 var foo = max(1, 2.0); |
| 11978 } |
| 11979 '''; |
| 11980 _resolveTestUnit(code); |
| 11981 |
| 11982 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 11983 VariableDeclaration declaration = |
| 11984 identifier.getAncestor((node) => node is VariableDeclaration); |
| 11985 expect(declaration.initializer.staticType.name, 'num'); |
| 11986 expect(declaration.initializer.propagatedType, isNull); |
| 11987 } |
| 11988 |
| 11989 void test_pseudoGeneric_max_intInt() { |
| 11990 String code = r''' |
| 11991 import 'dart:math'; |
| 11992 main() { |
| 11993 var foo = max(1, 2); |
| 11994 } |
| 11995 '''; |
| 11996 _resolveTestUnit(code); |
| 11997 |
| 11998 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 11999 VariableDeclaration declaration = |
| 12000 identifier.getAncestor((node) => node is VariableDeclaration); |
| 12001 expect(declaration.initializer.staticType.name, 'int'); |
| 12002 expect(declaration.initializer.propagatedType, isNull); |
| 12003 } |
| 12004 |
| 12005 void test_pseudoGeneric_then() { |
| 12006 String code = r''' |
| 12007 import 'dart:async'; |
| 12008 String toString(int x) => x.toString(); |
| 12009 main() { |
| 12010 Future<int> bar = null; |
| 12011 var foo = bar.then(toString); |
| 12012 } |
| 12013 '''; |
| 12014 _resolveTestUnit(code); |
| 12015 |
| 12016 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 12017 VariableDeclaration declaration = |
| 12018 identifier.getAncestor((node) => node is VariableDeclaration); |
| 12019 |
| 12020 expect(declaration.initializer.staticType.toString(), "Future<String>"); |
| 12021 expect(declaration.initializer.propagatedType, isNull); |
| 12022 } |
| 12023 |
| 12024 void test_ternaryOperator_null_left() { |
| 12025 String code = r''' |
| 12026 main() { |
| 12027 var foo = (true) ? null : 3; |
| 12028 } |
| 12029 '''; |
| 12030 _resolveTestUnit(code); |
| 12031 |
| 12032 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 12033 VariableDeclaration declaration = |
| 12034 identifier.getAncestor((node) => node is VariableDeclaration); |
| 12035 expect(declaration.initializer.staticType.name, 'int'); |
| 12036 expect(declaration.initializer.propagatedType, isNull); |
| 12037 } |
| 12038 |
| 12039 void test_ternaryOperator_null_right() { |
| 12040 String code = r''' |
| 12041 main() { |
| 12042 var foo = (true) ? 3 : null; |
| 12043 } |
| 12044 '''; |
| 12045 _resolveTestUnit(code); |
| 12046 |
| 12047 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 12048 VariableDeclaration declaration = |
| 12049 identifier.getAncestor((node) => node is VariableDeclaration); |
| 12050 expect(declaration.initializer.staticType.name, 'int'); |
| 12051 expect(declaration.initializer.propagatedType, isNull); |
| 12052 } |
| 12053 } |
| 12054 |
| 12055 @reflectiveTest |
| 12056 class StrongModeTypePropagationTest extends ResolverTestCase { |
| 12057 @override |
| 12058 void setUp() { |
| 12059 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 12060 options.strongMode = true; |
| 12061 resetWithOptions(options); |
| 12062 } |
| 12063 |
| 12064 void test_foreachInference_dynamic_disabled() { |
| 12065 String code = r''' |
| 12066 main() { |
| 12067 var list = <int>[]; |
| 12068 for (dynamic v in list) { |
| 12069 v; // marker |
| 12070 } |
| 12071 }'''; |
| 12072 _assertPropagatedIterationType( |
| 12073 code, typeProvider.dynamicType, typeProvider.intType); |
| 12074 _assertTypeOfMarkedExpression( |
| 12075 code, typeProvider.dynamicType, typeProvider.intType); |
| 12076 } |
| 12077 |
| 12078 void test_foreachInference_reusedVar_disabled() { |
| 12079 String code = r''' |
| 12080 main() { |
| 12081 var list = <int>[]; |
| 12082 var v; |
| 12083 for (v in list) { |
| 12084 v; // marker |
| 12085 } |
| 12086 }'''; |
| 12087 _assertPropagatedIterationType( |
| 12088 code, typeProvider.dynamicType, typeProvider.intType); |
| 12089 _assertTypeOfMarkedExpression( |
| 12090 code, typeProvider.dynamicType, typeProvider.intType); |
| 12091 } |
| 12092 |
| 12093 void test_foreachInference_var() { |
| 12094 String code = r''' |
| 12095 main() { |
| 12096 var list = <int>[]; |
| 12097 for (var v in list) { |
| 12098 v; // marker |
| 12099 } |
| 12100 }'''; |
| 12101 _assertPropagatedIterationType(code, typeProvider.intType, null); |
| 12102 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12103 } |
| 12104 |
| 12105 void test_foreachInference_var_iterable() { |
| 12106 String code = r''' |
| 12107 main() { |
| 12108 Iterable<int> list = <int>[]; |
| 12109 for (var v in list) { |
| 12110 v; // marker |
| 12111 } |
| 12112 }'''; |
| 12113 _assertPropagatedIterationType(code, typeProvider.intType, null); |
| 12114 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12115 } |
| 12116 |
| 12117 void test_foreachInference_var_stream() { |
| 12118 String code = r''' |
| 12119 import 'dart:async'; |
| 12120 main() async { |
| 12121 Stream<int> stream = null; |
| 12122 await for (var v in stream) { |
| 12123 v; // marker |
| 12124 } |
| 12125 }'''; |
| 12126 _assertPropagatedIterationType(code, typeProvider.intType, null); |
| 12127 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12128 } |
| 12129 |
| 12130 void test_localVariableInference_bottom_disabled() { |
| 12131 String code = r''' |
| 12132 main() { |
| 12133 var v = null; |
| 12134 v; // marker |
| 12135 }'''; |
| 12136 _assertPropagatedAssignedType(code, typeProvider.dynamicType, null); |
| 12137 _assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null); |
| 12138 } |
| 12139 |
| 12140 void test_localVariableInference_constant() { |
| 12141 String code = r''' |
| 12142 main() { |
| 12143 var v = 3; |
| 12144 v; // marker |
| 12145 }'''; |
| 12146 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12147 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12148 } |
| 12149 |
| 12150 void test_localVariableInference_declaredType_disabled() { |
| 12151 String code = r''' |
| 12152 main() { |
| 12153 dynamic v = 3; |
| 12154 v; // marker |
| 12155 }'''; |
| 12156 _assertPropagatedAssignedType( |
| 12157 code, typeProvider.dynamicType, typeProvider.intType); |
| 12158 _assertTypeOfMarkedExpression( |
| 12159 code, typeProvider.dynamicType, typeProvider.intType); |
| 12160 } |
| 12161 |
| 12162 void test_localVariableInference_noInitializer_disabled() { |
| 12163 String code = r''' |
| 12164 main() { |
| 12165 var v; |
| 12166 v = 3; |
| 12167 v; // marker |
| 12168 }'''; |
| 12169 _assertPropagatedAssignedType( |
| 12170 code, typeProvider.dynamicType, typeProvider.intType); |
| 12171 _assertTypeOfMarkedExpression( |
| 12172 code, typeProvider.dynamicType, typeProvider.intType); |
| 12173 } |
| 12174 |
| 12175 void test_localVariableInference_transitive_field_inferred_lexical() { |
| 12176 if (!AnalysisEngine.instance.useTaskModel) { |
| 12177 return; |
| 12178 } |
| 12179 String code = r''' |
| 12180 class A { |
| 12181 final x = 3; |
| 12182 f() { |
| 12183 var v = x; |
| 12184 return v; // marker |
| 12185 } |
| 12186 } |
| 12187 main() { |
| 12188 } |
| 12189 '''; |
| 12190 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12191 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12192 } |
| 12193 |
| 12194 void test_localVariableInference_transitive_field_inferred_reversed() { |
| 12195 if (!AnalysisEngine.instance.useTaskModel) { |
| 12196 return; |
| 12197 } |
| 12198 String code = r''' |
| 12199 class A { |
| 12200 f() { |
| 12201 var v = x; |
| 12202 return v; // marker |
| 12203 } |
| 12204 final x = 3; |
| 12205 } |
| 12206 main() { |
| 12207 } |
| 12208 '''; |
| 12209 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12210 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12211 } |
| 12212 |
| 12213 void test_localVariableInference_transitive_field_lexical() { |
| 12214 String code = r''' |
| 12215 class A { |
| 12216 int x = 3; |
| 12217 f() { |
| 12218 var v = x; |
| 12219 return v; // marker |
| 12220 } |
| 12221 } |
| 12222 main() { |
| 12223 } |
| 12224 '''; |
| 12225 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12226 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12227 } |
| 12228 |
| 12229 void test_localVariableInference_transitive_field_reversed() { |
| 12230 String code = r''' |
| 12231 class A { |
| 12232 f() { |
| 12233 var v = x; |
| 12234 return v; // marker |
| 12235 } |
| 12236 int x = 3; |
| 12237 } |
| 12238 main() { |
| 12239 } |
| 12240 '''; |
| 12241 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12242 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12243 } |
| 12244 |
| 12245 void test_localVariableInference_transitive_list_local() { |
| 12246 String code = r''' |
| 12247 main() { |
| 12248 var x = <int>[3]; |
| 12249 var v = x[0]; |
| 12250 v; // marker |
| 12251 }'''; |
| 12252 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12253 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12254 } |
| 12255 |
| 12256 void test_localVariableInference_transitive_local() { |
| 12257 String code = r''' |
| 12258 main() { |
| 12259 var x = 3; |
| 12260 var v = x; |
| 12261 v; // marker |
| 12262 }'''; |
| 12263 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12264 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12265 } |
| 12266 |
| 12267 void test_localVariableInference_transitive_toplevel_inferred_lexical() { |
| 12268 if (!AnalysisEngine.instance.useTaskModel) { |
| 12269 return; |
| 12270 } |
| 12271 String code = r''' |
| 12272 final x = 3; |
| 12273 main() { |
| 12274 var v = x; |
| 12275 v; // marker |
| 12276 } |
| 12277 '''; |
| 12278 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12279 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12280 } |
| 12281 |
| 12282 void test_localVariableInference_transitive_toplevel_inferred_reversed() { |
| 12283 if (!AnalysisEngine.instance.useTaskModel) { |
| 12284 return; |
| 12285 } |
| 12286 String code = r''' |
| 12287 main() { |
| 12288 var v = x; |
| 12289 v; // marker |
| 12290 } |
| 12291 final x = 3; |
| 12292 '''; |
| 12293 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12294 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12295 } |
| 12296 |
| 12297 void test_localVariableInference_transitive_toplevel_lexical() { |
| 12298 String code = r''' |
| 12299 int x = 3; |
| 12300 main() { |
| 12301 var v = x; |
| 12302 v; // marker |
| 12303 } |
| 12304 '''; |
| 12305 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12306 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12307 } |
| 12308 |
| 12309 void test_localVariableInference_transitive_toplevel_reversed() { |
| 12310 String code = r''' |
| 12311 main() { |
| 12312 var v = x; |
| 12313 v; // marker |
| 12314 } |
| 12315 int x = 3; |
| 12316 '''; |
| 12317 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 12318 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 12319 } |
| 12320 } |
| 12321 |
| 12322 @reflectiveTest |
| 12323 class SubtypeManagerTest extends EngineTestCase { |
| 12324 /** |
| 12325 * The inheritance manager being tested. |
| 12326 */ |
| 12327 SubtypeManager _subtypeManager; |
| 12328 |
| 12329 /** |
| 12330 * The compilation unit element containing all of the types setup in each test
. |
| 12331 */ |
| 12332 CompilationUnitElementImpl _definingCompilationUnit; |
| 12333 |
| 12334 @override |
| 12335 void setUp() { |
| 12336 super.setUp(); |
| 12337 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 12338 FileBasedSource source = |
| 12339 new FileBasedSource(FileUtilities2.createFile("/test.dart")); |
| 12340 _definingCompilationUnit = new CompilationUnitElementImpl("test.dart"); |
| 12341 _definingCompilationUnit.librarySource = |
| 12342 _definingCompilationUnit.source = source; |
| 12343 LibraryElementImpl definingLibrary = |
| 12344 ElementFactory.library(context, "test"); |
| 12345 definingLibrary.definingCompilationUnit = _definingCompilationUnit; |
| 12346 _subtypeManager = new SubtypeManager(); |
| 12347 } |
| 12348 |
| 12349 void test_computeAllSubtypes_infiniteLoop() { |
| 12350 // |
| 12351 // class A extends B |
| 12352 // class B extends A |
| 12353 // |
| 12354 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 12355 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 12356 classA.supertype = classB.type; |
| 12357 _definingCompilationUnit.types = <ClassElement>[classA, classB]; |
| 12358 HashSet<ClassElement> subtypesOfA = |
| 12359 _subtypeManager.computeAllSubtypes(classA); |
| 12360 List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA); |
| 12361 expect(subtypesOfA, hasLength(2)); |
| 12362 expect(arraySubtypesOfA, unorderedEquals([classA, classB])); |
| 12363 } |
| 12364 |
| 12365 void test_computeAllSubtypes_manyRecursiveSubtypes() { |
| 12366 // |
| 12367 // class A |
| 12368 // class B extends A |
| 12369 // class C extends B |
| 12370 // class D extends B |
| 12371 // class E extends B |
| 12372 // |
| 12373 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 12374 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 12375 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); |
| 12376 ClassElementImpl classD = ElementFactory.classElement("D", classB.type); |
| 12377 ClassElementImpl classE = ElementFactory.classElement("E", classB.type); |
| 12378 _definingCompilationUnit.types = <ClassElement>[ |
| 12379 classA, |
| 12380 classB, |
| 12381 classC, |
| 12382 classD, |
| 12383 classE |
| 12384 ]; |
| 12385 HashSet<ClassElement> subtypesOfA = |
| 12386 _subtypeManager.computeAllSubtypes(classA); |
| 12387 List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA); |
| 12388 HashSet<ClassElement> subtypesOfB = |
| 12389 _subtypeManager.computeAllSubtypes(classB); |
| 12390 List<ClassElement> arraySubtypesOfB = new List.from(subtypesOfB); |
| 12391 expect(subtypesOfA, hasLength(4)); |
| 12392 expect(arraySubtypesOfA, unorderedEquals([classB, classC, classD, classE])); |
| 12393 expect(subtypesOfB, hasLength(3)); |
| 12394 expect(arraySubtypesOfB, unorderedEquals([classC, classD, classE])); |
| 12395 } |
| 12396 |
| 12397 void test_computeAllSubtypes_noSubtypes() { |
| 12398 // |
| 12399 // class A |
| 12400 // |
| 12401 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 12402 _definingCompilationUnit.types = <ClassElement>[classA]; |
| 12403 HashSet<ClassElement> subtypesOfA = |
| 12404 _subtypeManager.computeAllSubtypes(classA); |
| 12405 expect(subtypesOfA, hasLength(0)); |
| 12406 } |
| 12407 |
| 12408 void test_computeAllSubtypes_oneSubtype() { |
| 12409 // |
| 12410 // class A |
| 12411 // class B extends A |
| 12412 // |
| 12413 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 12414 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 12415 _definingCompilationUnit.types = <ClassElement>[classA, classB]; |
| 12416 HashSet<ClassElement> subtypesOfA = |
| 12417 _subtypeManager.computeAllSubtypes(classA); |
| 12418 List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA); |
| 12419 expect(subtypesOfA, hasLength(1)); |
| 12420 expect(arraySubtypesOfA, unorderedEquals([classB])); |
| 12421 } |
| 12422 } |
| 12423 |
| 12424 @reflectiveTest |
| 12425 class TypeOverrideManagerTest extends EngineTestCase { |
| 12426 void test_exitScope_noScopes() { |
| 12427 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12428 try { |
| 12429 manager.exitScope(); |
| 12430 fail("Expected IllegalStateException"); |
| 12431 } on IllegalStateException { |
| 12432 // Expected |
| 12433 } |
| 12434 } |
| 12435 |
| 12436 void test_exitScope_oneScope() { |
| 12437 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12438 manager.enterScope(); |
| 12439 manager.exitScope(); |
| 12440 try { |
| 12441 manager.exitScope(); |
| 12442 fail("Expected IllegalStateException"); |
| 12443 } on IllegalStateException { |
| 12444 // Expected |
| 12445 } |
| 12446 } |
| 12447 |
| 12448 void test_exitScope_twoScopes() { |
| 12449 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12450 manager.enterScope(); |
| 12451 manager.exitScope(); |
| 12452 manager.enterScope(); |
| 12453 manager.exitScope(); |
| 12454 try { |
| 12455 manager.exitScope(); |
| 12456 fail("Expected IllegalStateException"); |
| 12457 } on IllegalStateException { |
| 12458 // Expected |
| 12459 } |
| 12460 } |
| 12461 |
| 12462 void test_getType_enclosedOverride() { |
| 12463 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12464 LocalVariableElementImpl element = |
| 12465 ElementFactory.localVariableElement2("v"); |
| 12466 InterfaceType type = ElementFactory.classElement2("C").type; |
| 12467 manager.enterScope(); |
| 12468 manager.setType(element, type); |
| 12469 manager.enterScope(); |
| 12470 expect(manager.getType(element), same(type)); |
| 12471 } |
| 12472 |
| 12473 void test_getType_immediateOverride() { |
| 12474 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12475 LocalVariableElementImpl element = |
| 12476 ElementFactory.localVariableElement2("v"); |
| 12477 InterfaceType type = ElementFactory.classElement2("C").type; |
| 12478 manager.enterScope(); |
| 12479 manager.setType(element, type); |
| 12480 expect(manager.getType(element), same(type)); |
| 12481 } |
| 12482 |
| 12483 void test_getType_noOverride() { |
| 12484 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12485 manager.enterScope(); |
| 12486 expect(manager.getType(ElementFactory.localVariableElement2("v")), isNull); |
| 12487 } |
| 12488 |
| 12489 void test_getType_noScope() { |
| 12490 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12491 expect(manager.getType(ElementFactory.localVariableElement2("v")), isNull); |
| 12492 } |
| 12493 } |
| 12494 |
| 12495 @reflectiveTest |
| 12496 class TypePropagationTest extends ResolverTestCase { |
| 12497 void fail_finalPropertyInducingVariable_classMember_instance() { |
| 12498 addNamedSource( |
| 12499 "/lib.dart", |
| 12500 r''' |
| 12501 class A { |
| 12502 final v = 0; |
| 12503 }'''); |
| 12504 String code = r''' |
| 12505 import 'lib.dart'; |
| 12506 f(A a) { |
| 12507 return a.v; // marker |
| 12508 }'''; |
| 12509 _assertTypeOfMarkedExpression( |
| 12510 code, typeProvider.dynamicType, typeProvider.intType); |
| 12511 } |
| 12512 |
| 12513 void fail_finalPropertyInducingVariable_classMember_instance_inherited() { |
| 12514 addNamedSource( |
| 12515 "/lib.dart", |
| 12516 r''' |
| 12517 class A { |
| 12518 final v = 0; |
| 12519 }'''); |
| 12520 String code = r''' |
| 12521 import 'lib.dart'; |
| 12522 class B extends A { |
| 12523 m() { |
| 12524 return v; // marker |
| 12525 } |
| 12526 }'''; |
| 12527 _assertTypeOfMarkedExpression( |
| 12528 code, typeProvider.dynamicType, typeProvider.intType); |
| 12529 } |
| 12530 |
| 12531 void fail_finalPropertyInducingVariable_classMember_instance_propagatedTarget(
) { |
| 12532 addNamedSource( |
| 12533 "/lib.dart", |
| 12534 r''' |
| 12535 class A { |
| 12536 final v = 0; |
| 12537 }'''); |
| 12538 String code = r''' |
| 12539 import 'lib.dart'; |
| 12540 f(p) { |
| 12541 if (p is A) { |
| 12542 return p.v; // marker |
| 12543 } |
| 12544 }'''; |
| 12545 _assertTypeOfMarkedExpression( |
| 12546 code, typeProvider.dynamicType, typeProvider.intType); |
| 12547 } |
| 12548 |
| 12549 void fail_finalPropertyInducingVariable_classMember_instance_unprefixed() { |
| 12550 String code = r''' |
| 12551 class A { |
| 12552 final v = 0; |
| 12553 m() { |
| 12554 v; // marker |
| 12555 } |
| 12556 }'''; |
| 12557 _assertTypeOfMarkedExpression( |
| 12558 code, typeProvider.dynamicType, typeProvider.intType); |
| 12559 } |
| 12560 |
| 12561 void fail_finalPropertyInducingVariable_classMember_static() { |
| 12562 addNamedSource( |
| 12563 "/lib.dart", |
| 12564 r''' |
| 12565 class A { |
| 12566 static final V = 0; |
| 12567 }'''); |
| 12568 String code = r''' |
| 12569 import 'lib.dart'; |
| 12570 f() { |
| 12571 return A.V; // marker |
| 12572 }'''; |
| 12573 _assertTypeOfMarkedExpression( |
| 12574 code, typeProvider.dynamicType, typeProvider.intType); |
| 12575 } |
| 12576 |
| 12577 void fail_finalPropertyInducingVariable_topLevelVaraible_prefixed() { |
| 12578 addNamedSource("/lib.dart", "final V = 0;"); |
| 12579 String code = r''' |
| 12580 import 'lib.dart' as p; |
| 12581 f() { |
| 12582 var v2 = p.V; // marker prefixed |
| 12583 }'''; |
| 12584 _assertTypeOfMarkedExpression( |
| 12585 code, typeProvider.dynamicType, typeProvider.intType); |
| 12586 } |
| 12587 |
| 12588 void fail_finalPropertyInducingVariable_topLevelVaraible_simple() { |
| 12589 addNamedSource("/lib.dart", "final V = 0;"); |
| 12590 String code = r''' |
| 12591 import 'lib.dart'; |
| 12592 f() { |
| 12593 return V; // marker simple |
| 12594 }'''; |
| 12595 _assertTypeOfMarkedExpression( |
| 12596 code, typeProvider.dynamicType, typeProvider.intType); |
| 12597 } |
| 12598 |
| 12599 void fail_mergePropagatedTypesAtJoinPoint_1() { |
| 12600 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12601 _assertTypeOfMarkedExpression( |
| 12602 r''' |
| 12603 f1(x) { |
| 12604 var y = []; |
| 12605 if (x) { |
| 12606 y = 0; |
| 12607 } else { |
| 12608 y = ''; |
| 12609 } |
| 12610 // Propagated type is [List] here: incorrect. |
| 12611 // Best we can do is [Object]? |
| 12612 return y; // marker |
| 12613 }''', |
| 12614 null, |
| 12615 typeProvider.dynamicType); |
| 12616 } |
| 12617 |
| 12618 void fail_mergePropagatedTypesAtJoinPoint_2() { |
| 12619 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12620 _assertTypeOfMarkedExpression( |
| 12621 r''' |
| 12622 f2(x) { |
| 12623 var y = []; |
| 12624 if (x) { |
| 12625 y = 0; |
| 12626 } else { |
| 12627 } |
| 12628 // Propagated type is [List] here: incorrect. |
| 12629 // Best we can do is [Object]? |
| 12630 return y; // marker |
| 12631 }''', |
| 12632 null, |
| 12633 typeProvider.dynamicType); |
| 12634 } |
| 12635 |
| 12636 void fail_mergePropagatedTypesAtJoinPoint_3() { |
| 12637 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12638 _assertTypeOfMarkedExpression( |
| 12639 r''' |
| 12640 f4(x) { |
| 12641 var y = []; |
| 12642 if (x) { |
| 12643 y = 0; |
| 12644 } else { |
| 12645 y = 1.5; |
| 12646 } |
| 12647 // Propagated type is [List] here: incorrect. |
| 12648 // A correct answer is the least upper bound of [int] and [double], |
| 12649 // i.e. [num]. |
| 12650 return y; // marker |
| 12651 }''', |
| 12652 null, |
| 12653 typeProvider.numType); |
| 12654 } |
| 12655 |
| 12656 void fail_mergePropagatedTypesAtJoinPoint_5() { |
| 12657 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12658 _assertTypeOfMarkedExpression( |
| 12659 r''' |
| 12660 f6(x,y) { |
| 12661 var z = []; |
| 12662 if (x || (z = y) < 0) { |
| 12663 } else { |
| 12664 z = 0; |
| 12665 } |
| 12666 // Propagated type is [List] here: incorrect. |
| 12667 // Best we can do is [Object]? |
| 12668 return z; // marker |
| 12669 }''', |
| 12670 null, |
| 12671 typeProvider.dynamicType); |
| 12672 } |
| 12673 |
| 12674 void fail_mergePropagatedTypesAtJoinPoint_7() { |
| 12675 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12676 // |
| 12677 // In general [continue]s are unsafe for the purposes of |
| 12678 // [isAbruptTerminationStatement]. |
| 12679 // |
| 12680 // This is like example 6, but less tricky: the code in the branch that |
| 12681 // [continue]s is in effect after the [if]. |
| 12682 String code = r''' |
| 12683 f() { |
| 12684 var x = 0; |
| 12685 var c = false; |
| 12686 var d = true; |
| 12687 while (d) { |
| 12688 if (c) { |
| 12689 d = false; |
| 12690 } else { |
| 12691 x = ''; |
| 12692 c = true; |
| 12693 continue; |
| 12694 } |
| 12695 x; // marker |
| 12696 } |
| 12697 }'''; |
| 12698 DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType; |
| 12699 expect(typeProvider.intType.isSubtypeOf(t), isTrue); |
| 12700 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); |
| 12701 } |
| 12702 |
| 12703 void fail_mergePropagatedTypesAtJoinPoint_8() { |
| 12704 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12705 // |
| 12706 // In nested loops [breaks]s are unsafe for the purposes of |
| 12707 // [isAbruptTerminationStatement]. |
| 12708 // |
| 12709 // This is a combination of 6 and 7: we use an unlabeled [break] |
| 12710 // like a continue for the outer loop / like a labeled [break] to |
| 12711 // jump just above the [if]. |
| 12712 String code = r''' |
| 12713 f() { |
| 12714 var x = 0; |
| 12715 var c = false; |
| 12716 var d = true; |
| 12717 while (d) { |
| 12718 while (d) { |
| 12719 if (c) { |
| 12720 d = false; |
| 12721 } else { |
| 12722 x = ''; |
| 12723 c = true; |
| 12724 break; |
| 12725 } |
| 12726 x; // marker |
| 12727 } |
| 12728 } |
| 12729 }'''; |
| 12730 DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType; |
| 12731 expect(typeProvider.intType.isSubtypeOf(t), isTrue); |
| 12732 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); |
| 12733 } |
| 12734 |
| 12735 void fail_propagatedReturnType_functionExpression() { |
| 12736 // TODO(scheglov) disabled because we don't resolve function expression |
| 12737 String code = r''' |
| 12738 main() { |
| 12739 var v = (() {return 42;})(); |
| 12740 }'''; |
| 12741 _assertPropagatedAssignedType( |
| 12742 code, typeProvider.dynamicType, typeProvider.intType); |
| 12743 } |
| 12744 |
| 12745 void test_as() { |
| 12746 Source source = addSource(r''' |
| 12747 class A { |
| 12748 bool get g => true; |
| 12749 } |
| 12750 A f(var p) { |
| 12751 if ((p as A).g) { |
| 12752 return p; |
| 12753 } else { |
| 12754 return null; |
| 12755 } |
| 12756 }'''); |
| 12757 LibraryElement library = resolve2(source); |
| 12758 assertNoErrors(source); |
| 12759 verify([source]); |
| 12760 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12761 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12762 InterfaceType typeA = classA.element.type; |
| 12763 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12764 BlockFunctionBody body = |
| 12765 function.functionExpression.body as BlockFunctionBody; |
| 12766 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 12767 ReturnStatement statement = |
| 12768 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 12769 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12770 expect(variableName.propagatedType, same(typeA)); |
| 12771 } |
| 12772 |
| 12773 void test_assert() { |
| 12774 Source source = addSource(r''' |
| 12775 class A {} |
| 12776 A f(var p) { |
| 12777 assert (p is A); |
| 12778 return p; |
| 12779 }'''); |
| 12780 LibraryElement library = resolve2(source); |
| 12781 assertNoErrors(source); |
| 12782 verify([source]); |
| 12783 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12784 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12785 InterfaceType typeA = classA.element.type; |
| 12786 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12787 BlockFunctionBody body = |
| 12788 function.functionExpression.body as BlockFunctionBody; |
| 12789 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 12790 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12791 expect(variableName.propagatedType, same(typeA)); |
| 12792 } |
| 12793 |
| 12794 void test_assignment() { |
| 12795 Source source = addSource(r''' |
| 12796 f() { |
| 12797 var v; |
| 12798 v = 0; |
| 12799 return v; |
| 12800 }'''); |
| 12801 LibraryElement library = resolve2(source); |
| 12802 assertNoErrors(source); |
| 12803 verify([source]); |
| 12804 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12805 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 12806 BlockFunctionBody body = |
| 12807 function.functionExpression.body as BlockFunctionBody; |
| 12808 ReturnStatement statement = body.block.statements[2] as ReturnStatement; |
| 12809 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12810 expect(variableName.propagatedType, same(typeProvider.intType)); |
| 12811 } |
| 12812 |
| 12813 void test_assignment_afterInitializer() { |
| 12814 Source source = addSource(r''' |
| 12815 f() { |
| 12816 var v = 0; |
| 12817 v = 1.0; |
| 12818 return v; |
| 12819 }'''); |
| 12820 LibraryElement library = resolve2(source); |
| 12821 assertNoErrors(source); |
| 12822 verify([source]); |
| 12823 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12824 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 12825 BlockFunctionBody body = |
| 12826 function.functionExpression.body as BlockFunctionBody; |
| 12827 ReturnStatement statement = body.block.statements[2] as ReturnStatement; |
| 12828 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12829 expect(variableName.propagatedType, same(typeProvider.doubleType)); |
| 12830 } |
| 12831 |
| 12832 void test_assignment_null() { |
| 12833 String code = r''' |
| 12834 main() { |
| 12835 int v; // declare |
| 12836 v = null; |
| 12837 return v; // return |
| 12838 }'''; |
| 12839 CompilationUnit unit; |
| 12840 { |
| 12841 Source source = addSource(code); |
| 12842 LibraryElement library = resolve2(source); |
| 12843 assertNoErrors(source); |
| 12844 verify([source]); |
| 12845 unit = resolveCompilationUnit(source, library); |
| 12846 } |
| 12847 { |
| 12848 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12849 unit, code, "v; // declare", (node) => node is SimpleIdentifier); |
| 12850 expect(identifier.staticType, same(typeProvider.intType)); |
| 12851 expect(identifier.propagatedType, same(null)); |
| 12852 } |
| 12853 { |
| 12854 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12855 unit, code, "v = null;", (node) => node is SimpleIdentifier); |
| 12856 expect(identifier.staticType, same(typeProvider.intType)); |
| 12857 expect(identifier.propagatedType, same(null)); |
| 12858 } |
| 12859 { |
| 12860 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12861 unit, code, "v; // return", (node) => node is SimpleIdentifier); |
| 12862 expect(identifier.staticType, same(typeProvider.intType)); |
| 12863 expect(identifier.propagatedType, same(null)); |
| 12864 } |
| 12865 } |
| 12866 |
| 12867 void test_CanvasElement_getContext() { |
| 12868 String code = r''' |
| 12869 import 'dart:html'; |
| 12870 main(CanvasElement canvas) { |
| 12871 var context = canvas.getContext('2d'); |
| 12872 }'''; |
| 12873 Source source = addSource(code); |
| 12874 LibraryElement library = resolve2(source); |
| 12875 assertNoErrors(source); |
| 12876 verify([source]); |
| 12877 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12878 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12879 unit, code, "context", (node) => node is SimpleIdentifier); |
| 12880 expect(identifier.propagatedType.name, "CanvasRenderingContext2D"); |
| 12881 } |
| 12882 |
| 12883 void test_forEach() { |
| 12884 String code = r''' |
| 12885 main() { |
| 12886 var list = <String> []; |
| 12887 for (var e in list) { |
| 12888 e; |
| 12889 } |
| 12890 }'''; |
| 12891 Source source = addSource(code); |
| 12892 LibraryElement library = resolve2(source); |
| 12893 assertNoErrors(source); |
| 12894 verify([source]); |
| 12895 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12896 InterfaceType stringType = typeProvider.stringType; |
| 12897 // in the declaration |
| 12898 { |
| 12899 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12900 unit, code, "e in", (node) => node is SimpleIdentifier); |
| 12901 expect(identifier.propagatedType, same(stringType)); |
| 12902 } |
| 12903 // in the loop body |
| 12904 { |
| 12905 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12906 unit, code, "e;", (node) => node is SimpleIdentifier); |
| 12907 expect(identifier.propagatedType, same(stringType)); |
| 12908 } |
| 12909 } |
| 12910 |
| 12911 void test_forEach_async() { |
| 12912 String code = r''' |
| 12913 import 'dart:async'; |
| 12914 f(Stream<String> stream) async { |
| 12915 await for (var e in stream) { |
| 12916 e; |
| 12917 } |
| 12918 }'''; |
| 12919 Source source = addSource(code); |
| 12920 LibraryElement library = resolve2(source); |
| 12921 assertNoErrors(source); |
| 12922 verify([source]); |
| 12923 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12924 InterfaceType stringType = typeProvider.stringType; |
| 12925 // in the declaration |
| 12926 { |
| 12927 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12928 unit, code, "e in", (node) => node is SimpleIdentifier); |
| 12929 expect(identifier.propagatedType, same(stringType)); |
| 12930 } |
| 12931 // in the loop body |
| 12932 { |
| 12933 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12934 unit, code, "e;", (node) => node is SimpleIdentifier); |
| 12935 expect(identifier.propagatedType, same(stringType)); |
| 12936 } |
| 12937 } |
| 12938 |
| 12939 void test_functionExpression_asInvocationArgument() { |
| 12940 String code = r''' |
| 12941 class MyMap<K, V> { |
| 12942 forEach(f(K key, V value)) {} |
| 12943 } |
| 12944 f(MyMap<int, String> m) { |
| 12945 m.forEach((k, v) { |
| 12946 k; |
| 12947 v; |
| 12948 }); |
| 12949 }'''; |
| 12950 Source source = addSource(code); |
| 12951 LibraryElement library = resolve2(source); |
| 12952 assertNoErrors(source); |
| 12953 verify([source]); |
| 12954 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12955 // k |
| 12956 DartType intType = typeProvider.intType; |
| 12957 FormalParameter kParameter = EngineTestCase.findNode( |
| 12958 unit, code, "k, ", (node) => node is SimpleFormalParameter); |
| 12959 expect(kParameter.identifier.propagatedType, same(intType)); |
| 12960 SimpleIdentifier kIdentifier = EngineTestCase.findNode( |
| 12961 unit, code, "k;", (node) => node is SimpleIdentifier); |
| 12962 expect(kIdentifier.propagatedType, same(intType)); |
| 12963 expect(kIdentifier.staticType, same(typeProvider.dynamicType)); |
| 12964 // v |
| 12965 DartType stringType = typeProvider.stringType; |
| 12966 FormalParameter vParameter = EngineTestCase.findNode( |
| 12967 unit, code, "v)", (node) => node is SimpleFormalParameter); |
| 12968 expect(vParameter.identifier.propagatedType, same(stringType)); |
| 12969 SimpleIdentifier vIdentifier = EngineTestCase.findNode( |
| 12970 unit, code, "v;", (node) => node is SimpleIdentifier); |
| 12971 expect(vIdentifier.propagatedType, same(stringType)); |
| 12972 expect(vIdentifier.staticType, same(typeProvider.dynamicType)); |
| 12973 } |
| 12974 |
| 12975 void test_functionExpression_asInvocationArgument_fromInferredInvocation() { |
| 12976 String code = r''' |
| 12977 class MyMap<K, V> { |
| 12978 forEach(f(K key, V value)) {} |
| 12979 } |
| 12980 f(MyMap<int, String> m) { |
| 12981 var m2 = m; |
| 12982 m2.forEach((k, v) {}); |
| 12983 }'''; |
| 12984 Source source = addSource(code); |
| 12985 LibraryElement library = resolve2(source); |
| 12986 assertNoErrors(source); |
| 12987 verify([source]); |
| 12988 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12989 // k |
| 12990 DartType intType = typeProvider.intType; |
| 12991 FormalParameter kParameter = EngineTestCase.findNode( |
| 12992 unit, code, "k, ", (node) => node is SimpleFormalParameter); |
| 12993 expect(kParameter.identifier.propagatedType, same(intType)); |
| 12994 // v |
| 12995 DartType stringType = typeProvider.stringType; |
| 12996 FormalParameter vParameter = EngineTestCase.findNode( |
| 12997 unit, code, "v)", (node) => node is SimpleFormalParameter); |
| 12998 expect(vParameter.identifier.propagatedType, same(stringType)); |
| 12999 } |
| 13000 |
| 13001 void test_functionExpression_asInvocationArgument_functionExpressionInvocation
() { |
| 13002 String code = r''' |
| 13003 main() { |
| 13004 (f(String value)) {} ((v) { |
| 13005 v; |
| 13006 }); |
| 13007 }'''; |
| 13008 Source source = addSource(code); |
| 13009 LibraryElement library = resolve2(source); |
| 13010 assertNoErrors(source); |
| 13011 verify([source]); |
| 13012 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13013 // v |
| 13014 DartType dynamicType = typeProvider.dynamicType; |
| 13015 DartType stringType = typeProvider.stringType; |
| 13016 FormalParameter vParameter = EngineTestCase.findNode( |
| 13017 unit, code, "v)", (node) => node is FormalParameter); |
| 13018 expect(vParameter.identifier.propagatedType, same(stringType)); |
| 13019 expect(vParameter.identifier.staticType, same(dynamicType)); |
| 13020 SimpleIdentifier vIdentifier = EngineTestCase.findNode( |
| 13021 unit, code, "v;", (node) => node is SimpleIdentifier); |
| 13022 expect(vIdentifier.propagatedType, same(stringType)); |
| 13023 expect(vIdentifier.staticType, same(dynamicType)); |
| 13024 } |
| 13025 |
| 13026 void test_functionExpression_asInvocationArgument_keepIfLessSpecific() { |
| 13027 String code = r''' |
| 13028 class MyList { |
| 13029 forEach(f(Object value)) {} |
| 13030 } |
| 13031 f(MyList list) { |
| 13032 list.forEach((int v) { |
| 13033 v; |
| 13034 }); |
| 13035 }'''; |
| 13036 Source source = addSource(code); |
| 13037 LibraryElement library = resolve2(source); |
| 13038 assertNoErrors(source); |
| 13039 verify([source]); |
| 13040 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13041 // v |
| 13042 DartType intType = typeProvider.intType; |
| 13043 FormalParameter vParameter = EngineTestCase.findNode( |
| 13044 unit, code, "v)", (node) => node is SimpleFormalParameter); |
| 13045 expect(vParameter.identifier.propagatedType, same(null)); |
| 13046 expect(vParameter.identifier.staticType, same(intType)); |
| 13047 SimpleIdentifier vIdentifier = EngineTestCase.findNode( |
| 13048 unit, code, "v;", (node) => node is SimpleIdentifier); |
| 13049 expect(vIdentifier.staticType, same(intType)); |
| 13050 expect(vIdentifier.propagatedType, same(null)); |
| 13051 } |
| 13052 |
| 13053 void test_functionExpression_asInvocationArgument_notSubtypeOfStaticType() { |
| 13054 String code = r''' |
| 13055 class A { |
| 13056 m(void f(int i)) {} |
| 13057 } |
| 13058 x() { |
| 13059 A a = new A(); |
| 13060 a.m(() => 0); |
| 13061 }'''; |
| 13062 Source source = addSource(code); |
| 13063 LibraryElement library = resolve2(source); |
| 13064 assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); |
| 13065 verify([source]); |
| 13066 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13067 // () => 0 |
| 13068 FunctionExpression functionExpression = EngineTestCase.findNode( |
| 13069 unit, code, "() => 0)", (node) => node is FunctionExpression); |
| 13070 expect((functionExpression.staticType as FunctionType).parameters.length, |
| 13071 same(0)); |
| 13072 expect(functionExpression.propagatedType, same(null)); |
| 13073 } |
| 13074 |
| 13075 void test_functionExpression_asInvocationArgument_replaceIfMoreSpecific() { |
| 13076 String code = r''' |
| 13077 class MyList<E> { |
| 13078 forEach(f(E value)) {} |
| 13079 } |
| 13080 f(MyList<String> list) { |
| 13081 list.forEach((Object v) { |
| 13082 v; |
| 13083 }); |
| 13084 }'''; |
| 13085 Source source = addSource(code); |
| 13086 LibraryElement library = resolve2(source); |
| 13087 assertNoErrors(source); |
| 13088 verify([source]); |
| 13089 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13090 // v |
| 13091 DartType stringType = typeProvider.stringType; |
| 13092 FormalParameter vParameter = EngineTestCase.findNode( |
| 13093 unit, code, "v)", (node) => node is SimpleFormalParameter); |
| 13094 expect(vParameter.identifier.propagatedType, same(stringType)); |
| 13095 expect(vParameter.identifier.staticType, same(typeProvider.objectType)); |
| 13096 SimpleIdentifier vIdentifier = EngineTestCase.findNode( |
| 13097 unit, code, "v;", (node) => node is SimpleIdentifier); |
| 13098 expect(vIdentifier.propagatedType, same(stringType)); |
| 13099 } |
| 13100 |
| 13101 void test_Future_then() { |
| 13102 String code = r''' |
| 13103 import 'dart:async'; |
| 13104 main(Future<int> firstFuture) { |
| 13105 firstFuture.then((p1) { |
| 13106 return 1.0; |
| 13107 }).then((p2) { |
| 13108 return new Future<String>.value('str'); |
| 13109 }).then((p3) { |
| 13110 }); |
| 13111 }'''; |
| 13112 Source source = addSource(code); |
| 13113 LibraryElement library = resolve2(source); |
| 13114 assertNoErrors(source); |
| 13115 verify([source]); |
| 13116 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13117 // p1 |
| 13118 FormalParameter p1 = EngineTestCase.findNode( |
| 13119 unit, code, "p1) {", (node) => node is SimpleFormalParameter); |
| 13120 expect(p1.identifier.propagatedType, same(typeProvider.intType)); |
| 13121 // p2 |
| 13122 FormalParameter p2 = EngineTestCase.findNode( |
| 13123 unit, code, "p2) {", (node) => node is SimpleFormalParameter); |
| 13124 expect(p2.identifier.propagatedType, same(typeProvider.doubleType)); |
| 13125 // p3 |
| 13126 FormalParameter p3 = EngineTestCase.findNode( |
| 13127 unit, code, "p3) {", (node) => node is SimpleFormalParameter); |
| 13128 expect(p3.identifier.propagatedType, same(typeProvider.stringType)); |
| 13129 } |
| 13130 |
| 13131 void test_initializer() { |
| 13132 Source source = addSource(r''' |
| 13133 f() { |
| 13134 var v = 0; |
| 13135 return v; |
| 13136 }'''); |
| 13137 LibraryElement library = resolve2(source); |
| 13138 assertNoErrors(source); |
| 13139 verify([source]); |
| 13140 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13141 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13142 BlockFunctionBody body = |
| 13143 function.functionExpression.body as BlockFunctionBody; |
| 13144 NodeList<Statement> statements = body.block.statements; |
| 13145 // Type of 'v' in declaration. |
| 13146 { |
| 13147 VariableDeclarationStatement statement = |
| 13148 statements[0] as VariableDeclarationStatement; |
| 13149 SimpleIdentifier variableName = statement.variables.variables[0].name; |
| 13150 expect(variableName.staticType, same(typeProvider.dynamicType)); |
| 13151 expect(variableName.propagatedType, same(typeProvider.intType)); |
| 13152 } |
| 13153 // Type of 'v' in reference. |
| 13154 { |
| 13155 ReturnStatement statement = statements[1] as ReturnStatement; |
| 13156 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13157 expect(variableName.propagatedType, same(typeProvider.intType)); |
| 13158 } |
| 13159 } |
| 13160 |
| 13161 void test_initializer_dereference() { |
| 13162 Source source = addSource(r''' |
| 13163 f() { |
| 13164 var v = 'String'; |
| 13165 v. |
| 13166 }'''); |
| 13167 LibraryElement library = resolve2(source); |
| 13168 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13169 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13170 BlockFunctionBody body = |
| 13171 function.functionExpression.body as BlockFunctionBody; |
| 13172 ExpressionStatement statement = |
| 13173 body.block.statements[1] as ExpressionStatement; |
| 13174 PrefixedIdentifier invocation = statement.expression as PrefixedIdentifier; |
| 13175 SimpleIdentifier variableName = invocation.prefix; |
| 13176 expect(variableName.propagatedType, same(typeProvider.stringType)); |
| 13177 } |
| 13178 |
| 13179 void test_initializer_hasStaticType() { |
| 13180 Source source = addSource(r''' |
| 13181 f() { |
| 13182 int v = 0; |
| 13183 return v; |
| 13184 }'''); |
| 13185 LibraryElement library = resolve2(source); |
| 13186 assertNoErrors(source); |
| 13187 verify([source]); |
| 13188 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13189 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13190 BlockFunctionBody body = |
| 13191 function.functionExpression.body as BlockFunctionBody; |
| 13192 NodeList<Statement> statements = body.block.statements; |
| 13193 // Type of 'v' in declaration. |
| 13194 { |
| 13195 VariableDeclarationStatement statement = |
| 13196 statements[0] as VariableDeclarationStatement; |
| 13197 SimpleIdentifier variableName = statement.variables.variables[0].name; |
| 13198 expect(variableName.staticType, same(typeProvider.intType)); |
| 13199 expect(variableName.propagatedType, isNull); |
| 13200 } |
| 13201 // Type of 'v' in reference. |
| 13202 { |
| 13203 ReturnStatement statement = statements[1] as ReturnStatement; |
| 13204 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13205 expect(variableName.staticType, same(typeProvider.intType)); |
| 13206 expect(variableName.propagatedType, isNull); |
| 13207 } |
| 13208 } |
| 13209 |
| 13210 void test_initializer_hasStaticType_parameterized() { |
| 13211 Source source = addSource(r''' |
| 13212 f() { |
| 13213 List<int> v = <int>[]; |
| 13214 return v; |
| 13215 }'''); |
| 13216 LibraryElement library = resolve2(source); |
| 13217 assertNoErrors(source); |
| 13218 verify([source]); |
| 13219 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13220 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13221 BlockFunctionBody body = |
| 13222 function.functionExpression.body as BlockFunctionBody; |
| 13223 NodeList<Statement> statements = body.block.statements; |
| 13224 // Type of 'v' in declaration. |
| 13225 { |
| 13226 VariableDeclarationStatement statement = |
| 13227 statements[0] as VariableDeclarationStatement; |
| 13228 SimpleIdentifier variableName = statement.variables.variables[0].name; |
| 13229 expect(variableName.staticType, isNotNull); |
| 13230 expect(variableName.propagatedType, isNull); |
| 13231 } |
| 13232 // Type of 'v' in reference. |
| 13233 { |
| 13234 ReturnStatement statement = statements[1] as ReturnStatement; |
| 13235 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13236 expect(variableName.staticType, isNotNull); |
| 13237 expect(variableName.propagatedType, isNull); |
| 13238 } |
| 13239 } |
| 13240 |
| 13241 void test_initializer_null() { |
| 13242 String code = r''' |
| 13243 main() { |
| 13244 int v = null; |
| 13245 return v; // marker |
| 13246 }'''; |
| 13247 CompilationUnit unit; |
| 13248 { |
| 13249 Source source = addSource(code); |
| 13250 LibraryElement library = resolve2(source); |
| 13251 assertNoErrors(source); |
| 13252 verify([source]); |
| 13253 unit = resolveCompilationUnit(source, library); |
| 13254 } |
| 13255 { |
| 13256 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 13257 unit, code, "v = null;", (node) => node is SimpleIdentifier); |
| 13258 expect(identifier.staticType, same(typeProvider.intType)); |
| 13259 expect(identifier.propagatedType, same(null)); |
| 13260 } |
| 13261 { |
| 13262 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 13263 unit, code, "v; // marker", (node) => node is SimpleIdentifier); |
| 13264 expect(identifier.staticType, same(typeProvider.intType)); |
| 13265 expect(identifier.propagatedType, same(null)); |
| 13266 } |
| 13267 } |
| 13268 |
| 13269 void test_is_conditional() { |
| 13270 Source source = addSource(r''' |
| 13271 class A {} |
| 13272 A f(var p) { |
| 13273 return (p is A) ? p : null; |
| 13274 }'''); |
| 13275 LibraryElement library = resolve2(source); |
| 13276 assertNoErrors(source); |
| 13277 verify([source]); |
| 13278 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13279 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13280 InterfaceType typeA = classA.element.type; |
| 13281 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13282 BlockFunctionBody body = |
| 13283 function.functionExpression.body as BlockFunctionBody; |
| 13284 ReturnStatement statement = body.block.statements[0] as ReturnStatement; |
| 13285 ConditionalExpression conditional = |
| 13286 statement.expression as ConditionalExpression; |
| 13287 SimpleIdentifier variableName = |
| 13288 conditional.thenExpression as SimpleIdentifier; |
| 13289 expect(variableName.propagatedType, same(typeA)); |
| 13290 } |
| 13291 |
| 13292 void test_is_if() { |
| 13293 Source source = addSource(r''' |
| 13294 class A {} |
| 13295 A f(var p) { |
| 13296 if (p is A) { |
| 13297 return p; |
| 13298 } else { |
| 13299 return null; |
| 13300 } |
| 13301 }'''); |
| 13302 LibraryElement library = resolve2(source); |
| 13303 assertNoErrors(source); |
| 13304 verify([source]); |
| 13305 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13306 // prepare A |
| 13307 InterfaceType typeA; |
| 13308 { |
| 13309 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13310 typeA = classA.element.type; |
| 13311 } |
| 13312 // verify "f" |
| 13313 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13314 BlockFunctionBody body = |
| 13315 function.functionExpression.body as BlockFunctionBody; |
| 13316 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 13317 // "p is A" |
| 13318 { |
| 13319 IsExpression isExpression = ifStatement.condition; |
| 13320 SimpleIdentifier variableName = isExpression.expression; |
| 13321 expect(variableName.propagatedType, isNull); |
| 13322 } |
| 13323 // "return p;" |
| 13324 { |
| 13325 ReturnStatement statement = |
| 13326 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 13327 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13328 expect(variableName.propagatedType, same(typeA)); |
| 13329 } |
| 13330 } |
| 13331 |
| 13332 void test_is_if_lessSpecific() { |
| 13333 Source source = addSource(r''' |
| 13334 class A {} |
| 13335 A f(A p) { |
| 13336 if (p is String) { |
| 13337 return p; |
| 13338 } else { |
| 13339 return null; |
| 13340 } |
| 13341 }'''); |
| 13342 LibraryElement library = resolve2(source); |
| 13343 assertNoErrors(source); |
| 13344 verify([source]); |
| 13345 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13346 // ClassDeclaration classA = (ClassDeclaration) unit.getDeclarations().get(0)
; |
| 13347 // InterfaceType typeA = classA.getElement().getType(); |
| 13348 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13349 BlockFunctionBody body = |
| 13350 function.functionExpression.body as BlockFunctionBody; |
| 13351 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 13352 ReturnStatement statement = |
| 13353 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 13354 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13355 expect(variableName.propagatedType, same(null)); |
| 13356 } |
| 13357 |
| 13358 void test_is_if_logicalAnd() { |
| 13359 Source source = addSource(r''' |
| 13360 class A {} |
| 13361 A f(var p) { |
| 13362 if (p is A && p != null) { |
| 13363 return p; |
| 13364 } else { |
| 13365 return null; |
| 13366 } |
| 13367 }'''); |
| 13368 LibraryElement library = resolve2(source); |
| 13369 assertNoErrors(source); |
| 13370 verify([source]); |
| 13371 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13372 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13373 InterfaceType typeA = classA.element.type; |
| 13374 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13375 BlockFunctionBody body = |
| 13376 function.functionExpression.body as BlockFunctionBody; |
| 13377 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 13378 ReturnStatement statement = |
| 13379 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 13380 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13381 expect(variableName.propagatedType, same(typeA)); |
| 13382 } |
| 13383 |
| 13384 void test_is_postConditional() { |
| 13385 Source source = addSource(r''' |
| 13386 class A {} |
| 13387 A f(var p) { |
| 13388 A a = (p is A) ? p : throw null; |
| 13389 return p; |
| 13390 }'''); |
| 13391 LibraryElement library = resolve2(source); |
| 13392 assertNoErrors(source); |
| 13393 verify([source]); |
| 13394 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13395 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13396 InterfaceType typeA = classA.element.type; |
| 13397 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13398 BlockFunctionBody body = |
| 13399 function.functionExpression.body as BlockFunctionBody; |
| 13400 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13401 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13402 expect(variableName.propagatedType, same(typeA)); |
| 13403 } |
| 13404 |
| 13405 void test_is_postIf() { |
| 13406 Source source = addSource(r''' |
| 13407 class A {} |
| 13408 A f(var p) { |
| 13409 if (p is A) { |
| 13410 A a = p; |
| 13411 } else { |
| 13412 return null; |
| 13413 } |
| 13414 return p; |
| 13415 }'''); |
| 13416 LibraryElement library = resolve2(source); |
| 13417 assertNoErrors(source); |
| 13418 verify([source]); |
| 13419 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13420 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13421 InterfaceType typeA = classA.element.type; |
| 13422 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13423 BlockFunctionBody body = |
| 13424 function.functionExpression.body as BlockFunctionBody; |
| 13425 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13426 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13427 expect(variableName.propagatedType, same(typeA)); |
| 13428 } |
| 13429 |
| 13430 void test_is_subclass() { |
| 13431 Source source = addSource(r''' |
| 13432 class A {} |
| 13433 class B extends A { |
| 13434 B m() => this; |
| 13435 } |
| 13436 A f(A p) { |
| 13437 if (p is B) { |
| 13438 return p.m(); |
| 13439 } |
| 13440 return p; |
| 13441 }'''); |
| 13442 LibraryElement library = resolve2(source); |
| 13443 assertNoErrors(source); |
| 13444 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13445 FunctionDeclaration function = unit.declarations[2] as FunctionDeclaration; |
| 13446 BlockFunctionBody body = |
| 13447 function.functionExpression.body as BlockFunctionBody; |
| 13448 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 13449 ReturnStatement statement = |
| 13450 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 13451 MethodInvocation invocation = statement.expression as MethodInvocation; |
| 13452 expect(invocation.methodName.staticElement, isNotNull); |
| 13453 expect(invocation.methodName.propagatedElement, isNull); |
| 13454 } |
| 13455 |
| 13456 void test_is_while() { |
| 13457 Source source = addSource(r''' |
| 13458 class A {} |
| 13459 A f(var p) { |
| 13460 while (p is A) { |
| 13461 return p; |
| 13462 } |
| 13463 return p; |
| 13464 }'''); |
| 13465 LibraryElement library = resolve2(source); |
| 13466 assertNoErrors(source); |
| 13467 verify([source]); |
| 13468 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13469 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13470 InterfaceType typeA = classA.element.type; |
| 13471 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13472 BlockFunctionBody body = |
| 13473 function.functionExpression.body as BlockFunctionBody; |
| 13474 WhileStatement whileStatement = body.block.statements[0] as WhileStatement; |
| 13475 ReturnStatement statement = |
| 13476 (whileStatement.body as Block).statements[0] as ReturnStatement; |
| 13477 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13478 expect(variableName.propagatedType, same(typeA)); |
| 13479 } |
| 13480 |
| 13481 void test_isNot_conditional() { |
| 13482 Source source = addSource(r''' |
| 13483 class A {} |
| 13484 A f(var p) { |
| 13485 return (p is! A) ? null : p; |
| 13486 }'''); |
| 13487 LibraryElement library = resolve2(source); |
| 13488 assertNoErrors(source); |
| 13489 verify([source]); |
| 13490 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13491 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13492 InterfaceType typeA = classA.element.type; |
| 13493 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13494 BlockFunctionBody body = |
| 13495 function.functionExpression.body as BlockFunctionBody; |
| 13496 ReturnStatement statement = body.block.statements[0] as ReturnStatement; |
| 13497 ConditionalExpression conditional = |
| 13498 statement.expression as ConditionalExpression; |
| 13499 SimpleIdentifier variableName = |
| 13500 conditional.elseExpression as SimpleIdentifier; |
| 13501 expect(variableName.propagatedType, same(typeA)); |
| 13502 } |
| 13503 |
| 13504 void test_isNot_if() { |
| 13505 Source source = addSource(r''' |
| 13506 class A {} |
| 13507 A f(var p) { |
| 13508 if (p is! A) { |
| 13509 return null; |
| 13510 } else { |
| 13511 return p; |
| 13512 } |
| 13513 }'''); |
| 13514 LibraryElement library = resolve2(source); |
| 13515 assertNoErrors(source); |
| 13516 verify([source]); |
| 13517 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13518 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13519 InterfaceType typeA = classA.element.type; |
| 13520 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13521 BlockFunctionBody body = |
| 13522 function.functionExpression.body as BlockFunctionBody; |
| 13523 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 13524 ReturnStatement statement = |
| 13525 (ifStatement.elseStatement as Block).statements[0] as ReturnStatement; |
| 13526 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13527 expect(variableName.propagatedType, same(typeA)); |
| 13528 } |
| 13529 |
| 13530 void test_isNot_if_logicalOr() { |
| 13531 Source source = addSource(r''' |
| 13532 class A {} |
| 13533 A f(var p) { |
| 13534 if (p is! A || null == p) { |
| 13535 return null; |
| 13536 } else { |
| 13537 return p; |
| 13538 } |
| 13539 }'''); |
| 13540 LibraryElement library = resolve2(source); |
| 13541 assertNoErrors(source); |
| 13542 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13543 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13544 InterfaceType typeA = classA.element.type; |
| 13545 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13546 BlockFunctionBody body = |
| 13547 function.functionExpression.body as BlockFunctionBody; |
| 13548 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 13549 ReturnStatement statement = |
| 13550 (ifStatement.elseStatement as Block).statements[0] as ReturnStatement; |
| 13551 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13552 expect(variableName.propagatedType, same(typeA)); |
| 13553 } |
| 13554 |
| 13555 void test_isNot_postConditional() { |
| 13556 Source source = addSource(r''' |
| 13557 class A {} |
| 13558 A f(var p) { |
| 13559 A a = (p is! A) ? throw null : p; |
| 13560 return p; |
| 13561 }'''); |
| 13562 LibraryElement library = resolve2(source); |
| 13563 assertNoErrors(source); |
| 13564 verify([source]); |
| 13565 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13566 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13567 InterfaceType typeA = classA.element.type; |
| 13568 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13569 BlockFunctionBody body = |
| 13570 function.functionExpression.body as BlockFunctionBody; |
| 13571 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13572 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13573 expect(variableName.propagatedType, same(typeA)); |
| 13574 } |
| 13575 |
| 13576 void test_isNot_postIf() { |
| 13577 Source source = addSource(r''' |
| 13578 class A {} |
| 13579 A f(var p) { |
| 13580 if (p is! A) { |
| 13581 return null; |
| 13582 } |
| 13583 return p; |
| 13584 }'''); |
| 13585 LibraryElement library = resolve2(source); |
| 13586 assertNoErrors(source); |
| 13587 verify([source]); |
| 13588 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13589 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13590 InterfaceType typeA = classA.element.type; |
| 13591 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13592 BlockFunctionBody body = |
| 13593 function.functionExpression.body as BlockFunctionBody; |
| 13594 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13595 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13596 expect(variableName.propagatedType, same(typeA)); |
| 13597 } |
| 13598 |
| 13599 void test_issue20904BuggyTypePromotionAtIfJoin_5() { |
| 13600 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 13601 // |
| 13602 // This is not an example of the 20904 bug, but rather, |
| 13603 // an example of something that one obvious fix changes inadvertently: we |
| 13604 // want to avoid using type information from is-checks when it |
| 13605 // loses precision. I can't see how to get a bad hint this way, since |
| 13606 // it seems the propagated type is not used to generate hints when a |
| 13607 // more precise type would cause no hint. For example, for code like the |
| 13608 // following, when the propagated type of [x] is [A] -- as happens for the |
| 13609 // fix these tests aim to warn against -- there is no warning for |
| 13610 |
| 13611 // calling a method defined on [B] but not [A] (there aren't any, but |
| 13612 // pretend), but there is for calling a method not defined on either. |
| 13613 // By not overriding the propagated type via an is-check that loses |
| 13614 // precision, we get more precise completion under an is-check. However, |
| 13615 // I can only imagine strange code would make use of this feature. |
| 13616 // |
| 13617 // Here the is-check improves precision, so we use it. |
| 13618 String code = r''' |
| 13619 class A {} |
| 13620 class B extends A {} |
| 13621 f() { |
| 13622 var a = new A(); |
| 13623 var b = new B(); |
| 13624 b; // B |
| 13625 if (a is B) { |
| 13626 return a; // marker |
| 13627 } |
| 13628 }'''; |
| 13629 DartType tB = _findMarkedIdentifier(code, "; // B").propagatedType; |
| 13630 _assertTypeOfMarkedExpression(code, null, tB); |
| 13631 } |
| 13632 |
| 13633 void test_issue20904BuggyTypePromotionAtIfJoin_6() { |
| 13634 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 13635 // |
| 13636 // The other half of the *_5() test. |
| 13637 // |
| 13638 // Here the is-check loses precision, so we don't use it. |
| 13639 String code = r''' |
| 13640 class A {} |
| 13641 class B extends A {} |
| 13642 f() { |
| 13643 var b = new B(); |
| 13644 b; // B |
| 13645 if (b is A) { |
| 13646 return b; // marker |
| 13647 } |
| 13648 }'''; |
| 13649 DartType tB = _findMarkedIdentifier(code, "; // B").propagatedType; |
| 13650 _assertTypeOfMarkedExpression(code, null, tB); |
| 13651 } |
| 13652 |
| 13653 void test_listLiteral_different() { |
| 13654 Source source = addSource(r''' |
| 13655 f() { |
| 13656 var v = [0, '1', 2]; |
| 13657 return v[2]; |
| 13658 }'''); |
| 13659 LibraryElement library = resolve2(source); |
| 13660 assertNoErrors(source); |
| 13661 verify([source]); |
| 13662 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13663 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13664 BlockFunctionBody body = |
| 13665 function.functionExpression.body as BlockFunctionBody; |
| 13666 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13667 IndexExpression indexExpression = statement.expression as IndexExpression; |
| 13668 expect(indexExpression.propagatedType, isNull); |
| 13669 } |
| 13670 |
| 13671 void test_listLiteral_same() { |
| 13672 Source source = addSource(r''' |
| 13673 f() { |
| 13674 var v = [0, 1, 2]; |
| 13675 return v[2]; |
| 13676 }'''); |
| 13677 LibraryElement library = resolve2(source); |
| 13678 assertNoErrors(source); |
| 13679 verify([source]); |
| 13680 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13681 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13682 BlockFunctionBody body = |
| 13683 function.functionExpression.body as BlockFunctionBody; |
| 13684 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13685 IndexExpression indexExpression = statement.expression as IndexExpression; |
| 13686 expect(indexExpression.propagatedType, isNull); |
| 13687 Expression v = indexExpression.target; |
| 13688 InterfaceType propagatedType = v.propagatedType as InterfaceType; |
| 13689 expect(propagatedType.element, same(typeProvider.listType.element)); |
| 13690 List<DartType> typeArguments = propagatedType.typeArguments; |
| 13691 expect(typeArguments, hasLength(1)); |
| 13692 expect(typeArguments[0], same(typeProvider.dynamicType)); |
| 13693 } |
| 13694 |
| 13695 void test_mapLiteral_different() { |
| 13696 Source source = addSource(r''' |
| 13697 f() { |
| 13698 var v = {'0' : 0, 1 : '1', '2' : 2}; |
| 13699 return v; |
| 13700 }'''); |
| 13701 LibraryElement library = resolve2(source); |
| 13702 assertNoErrors(source); |
| 13703 verify([source]); |
| 13704 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13705 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13706 BlockFunctionBody body = |
| 13707 function.functionExpression.body as BlockFunctionBody; |
| 13708 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13709 SimpleIdentifier identifier = statement.expression as SimpleIdentifier; |
| 13710 InterfaceType propagatedType = identifier.propagatedType as InterfaceType; |
| 13711 expect(propagatedType.element, same(typeProvider.mapType.element)); |
| 13712 List<DartType> typeArguments = propagatedType.typeArguments; |
| 13713 expect(typeArguments, hasLength(2)); |
| 13714 expect(typeArguments[0], same(typeProvider.dynamicType)); |
| 13715 expect(typeArguments[1], same(typeProvider.dynamicType)); |
| 13716 } |
| 13717 |
| 13718 void test_mapLiteral_same() { |
| 13719 Source source = addSource(r''' |
| 13720 f() { |
| 13721 var v = {'a' : 0, 'b' : 1, 'c' : 2}; |
| 13722 return v; |
| 13723 }'''); |
| 13724 LibraryElement library = resolve2(source); |
| 13725 assertNoErrors(source); |
| 13726 verify([source]); |
| 13727 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13728 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13729 BlockFunctionBody body = |
| 13730 function.functionExpression.body as BlockFunctionBody; |
| 13731 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13732 SimpleIdentifier identifier = statement.expression as SimpleIdentifier; |
| 13733 InterfaceType propagatedType = identifier.propagatedType as InterfaceType; |
| 13734 expect(propagatedType.element, same(typeProvider.mapType.element)); |
| 13735 List<DartType> typeArguments = propagatedType.typeArguments; |
| 13736 expect(typeArguments, hasLength(2)); |
| 13737 expect(typeArguments[0], same(typeProvider.dynamicType)); |
| 13738 expect(typeArguments[1], same(typeProvider.dynamicType)); |
| 13739 } |
| 13740 |
| 13741 void test_mergePropagatedTypes_afterIfThen_different() { |
| 13742 String code = r''' |
| 13743 main() { |
| 13744 var v = 0; |
| 13745 if (v != null) { |
| 13746 v = ''; |
| 13747 } |
| 13748 return v; |
| 13749 }'''; |
| 13750 { |
| 13751 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v;"); |
| 13752 expect(identifier.propagatedType, null); |
| 13753 } |
| 13754 { |
| 13755 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = '';"); |
| 13756 expect(identifier.propagatedType, typeProvider.stringType); |
| 13757 } |
| 13758 } |
| 13759 |
| 13760 void test_mergePropagatedTypes_afterIfThen_same() { |
| 13761 _assertTypeOfMarkedExpression( |
| 13762 r''' |
| 13763 main() { |
| 13764 var v = 1; |
| 13765 if (v != null) { |
| 13766 v = 2; |
| 13767 } |
| 13768 return v; // marker |
| 13769 }''', |
| 13770 null, |
| 13771 typeProvider.intType); |
| 13772 } |
| 13773 |
| 13774 void test_mergePropagatedTypes_afterIfThenElse_different() { |
| 13775 _assertTypeOfMarkedExpression( |
| 13776 r''' |
| 13777 main() { |
| 13778 var v = 1; |
| 13779 if (v != null) { |
| 13780 v = 2; |
| 13781 } else { |
| 13782 v = '3'; |
| 13783 } |
| 13784 return v; // marker |
| 13785 }''', |
| 13786 null, |
| 13787 null); |
| 13788 } |
| 13789 |
| 13790 void test_mergePropagatedTypes_afterIfThenElse_same() { |
| 13791 _assertTypeOfMarkedExpression( |
| 13792 r''' |
| 13793 main() { |
| 13794 var v = 1; |
| 13795 if (v != null) { |
| 13796 v = 2; |
| 13797 } else { |
| 13798 v = 3; |
| 13799 } |
| 13800 return v; // marker |
| 13801 }''', |
| 13802 null, |
| 13803 typeProvider.intType); |
| 13804 } |
| 13805 |
| 13806 void test_mergePropagatedTypesAtJoinPoint_4() { |
| 13807 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 13808 _assertTypeOfMarkedExpression( |
| 13809 r''' |
| 13810 f5(x) { |
| 13811 var y = []; |
| 13812 if (x) { |
| 13813 y = 0; |
| 13814 } else { |
| 13815 return y; |
| 13816 } |
| 13817 // Propagated type is [int] here: correct. |
| 13818 return y; // marker |
| 13819 }''', |
| 13820 null, |
| 13821 typeProvider.intType); |
| 13822 } |
| 13823 |
| 13824 void test_mutatedOutsideScope() { |
| 13825 // https://code.google.com/p/dart/issues/detail?id=22732 |
| 13826 Source source = addSource(r''' |
| 13827 class Base { |
| 13828 } |
| 13829 |
| 13830 class Derived extends Base { |
| 13831 get y => null; |
| 13832 } |
| 13833 |
| 13834 class C { |
| 13835 void f() { |
| 13836 Base x = null; |
| 13837 if (x is Derived) { |
| 13838 print(x.y); // BAD |
| 13839 } |
| 13840 x = null; |
| 13841 } |
| 13842 } |
| 13843 |
| 13844 void g() { |
| 13845 Base x = null; |
| 13846 if (x is Derived) { |
| 13847 print(x.y); // GOOD |
| 13848 } |
| 13849 x = null; |
| 13850 }'''); |
| 13851 computeLibrarySourceErrors(source); |
| 13852 assertNoErrors(source); |
| 13853 } |
| 13854 |
| 13855 void test_objectAccessInference_disabled_for_library_prefix() { |
| 13856 String name = 'hashCode'; |
| 13857 addNamedSource( |
| 13858 '/helper.dart', |
| 13859 ''' |
| 13860 library helper; |
| 13861 dynamic get $name => 42; |
| 13862 '''); |
| 13863 String code = ''' |
| 13864 import 'helper.dart' as helper; |
| 13865 main() { |
| 13866 helper.$name; // marker |
| 13867 }'''; |
| 13868 |
| 13869 SimpleIdentifier id = _findMarkedIdentifier(code, "; // marker"); |
| 13870 PrefixedIdentifier prefixedId = id.parent; |
| 13871 expect(id.staticType, typeProvider.dynamicType); |
| 13872 expect(prefixedId.staticType, typeProvider.dynamicType); |
| 13873 } |
| 13874 |
| 13875 void test_objectAccessInference_disabled_for_local_getter() { |
| 13876 String name = 'hashCode'; |
| 13877 String code = ''' |
| 13878 dynamic get $name => null; |
| 13879 main() { |
| 13880 $name; // marker |
| 13881 }'''; |
| 13882 |
| 13883 SimpleIdentifier getter = _findMarkedIdentifier(code, "; // marker"); |
| 13884 expect(getter.staticType, typeProvider.dynamicType); |
| 13885 } |
| 13886 |
| 13887 void test_objectAccessInference_enabled_for_cascades() { |
| 13888 String name = 'hashCode'; |
| 13889 String code = ''' |
| 13890 main() { |
| 13891 dynamic obj; |
| 13892 obj..$name..$name; // marker |
| 13893 }'''; |
| 13894 PropertyAccess access = _findMarkedIdentifier(code, "; // marker").parent; |
| 13895 expect(access.staticType, typeProvider.dynamicType); |
| 13896 expect(access.realTarget.staticType, typeProvider.dynamicType); |
| 13897 } |
| 13898 |
| 13899 void test_objectMethodInference_disabled_for_library_prefix() { |
| 13900 String name = 'toString'; |
| 13901 addNamedSource( |
| 13902 '/helper.dart', |
| 13903 ''' |
| 13904 library helper; |
| 13905 dynamic $name = (int x) => x + 42'); |
| 13906 '''); |
| 13907 String code = ''' |
| 13908 import 'helper.dart' as helper; |
| 13909 main() { |
| 13910 helper.$name(); // marker |
| 13911 }'''; |
| 13912 SimpleIdentifier methodName = _findMarkedIdentifier(code, "(); // marker"); |
| 13913 MethodInvocation methodInvoke = methodName.parent; |
| 13914 expect(methodName.staticType, null, reason: 'library prefix has no type'); |
| 13915 expect(methodInvoke.staticType, typeProvider.dynamicType); |
| 13916 } |
| 13917 |
| 13918 void test_objectMethodInference_disabled_for_local_function() { |
| 13919 String name = 'toString'; |
| 13920 String code = ''' |
| 13921 main() { |
| 13922 dynamic $name = () => null; |
| 13923 $name(); // marker |
| 13924 }'''; |
| 13925 SimpleIdentifier identifier = _findMarkedIdentifier(code, "$name = "); |
| 13926 expect(identifier.staticType, typeProvider.dynamicType); |
| 13927 |
| 13928 SimpleIdentifier methodName = _findMarkedIdentifier(code, "(); // marker"); |
| 13929 MethodInvocation methodInvoke = methodName.parent; |
| 13930 expect(methodName.staticType, typeProvider.dynamicType); |
| 13931 expect(methodInvoke.staticType, typeProvider.dynamicType); |
| 13932 } |
| 13933 |
| 13934 void test_objectMethodInference_enabled_for_cascades() { |
| 13935 String name = 'toString'; |
| 13936 String code = ''' |
| 13937 main() { |
| 13938 dynamic obj; |
| 13939 obj..$name()..$name(); // marker |
| 13940 }'''; |
| 13941 SimpleIdentifier methodName = _findMarkedIdentifier(code, "(); // marker"); |
| 13942 MethodInvocation methodInvoke = methodName.parent; |
| 13943 |
| 13944 expect(methodInvoke.staticType, typeProvider.dynamicType); |
| 13945 expect(methodInvoke.realTarget.staticType, typeProvider.dynamicType); |
| 13946 } |
| 13947 |
| 13948 void test_objectMethodOnDynamicExpression_doubleEquals() { |
| 13949 // https://code.google.com/p/dart/issues/detail?id=20342 |
| 13950 // |
| 13951 // This was not actually part of Issue 20342, since the spec specifies a |
| 13952 // static type of [bool] for [==] comparison and the implementation |
| 13953 // was already consistent with the spec there. But, it's another |
| 13954 // [Object] method, so it's included here. |
| 13955 _assertTypeOfMarkedExpression( |
| 13956 r''' |
| 13957 f1(x) { |
| 13958 var v = (x == x); |
| 13959 return v; // marker |
| 13960 }''', |
| 13961 null, |
| 13962 typeProvider.boolType); |
| 13963 } |
| 13964 |
| 13965 void test_objectMethodOnDynamicExpression_hashCode() { |
| 13966 // https://code.google.com/p/dart/issues/detail?id=20342 |
| 13967 _assertTypeOfMarkedExpression( |
| 13968 r''' |
| 13969 f1(x) { |
| 13970 var v = x.hashCode; |
| 13971 return v; // marker |
| 13972 }''', |
| 13973 null, |
| 13974 typeProvider.intType); |
| 13975 } |
| 13976 |
| 13977 void test_objectMethodOnDynamicExpression_runtimeType() { |
| 13978 // https://code.google.com/p/dart/issues/detail?id=20342 |
| 13979 _assertTypeOfMarkedExpression( |
| 13980 r''' |
| 13981 f1(x) { |
| 13982 var v = x.runtimeType; |
| 13983 return v; // marker |
| 13984 }''', |
| 13985 null, |
| 13986 typeProvider.typeType); |
| 13987 } |
| 13988 |
| 13989 void test_objectMethodOnDynamicExpression_toString() { |
| 13990 // https://code.google.com/p/dart/issues/detail?id=20342 |
| 13991 _assertTypeOfMarkedExpression( |
| 13992 r''' |
| 13993 f1(x) { |
| 13994 var v = x.toString(); |
| 13995 return v; // marker |
| 13996 }''', |
| 13997 null, |
| 13998 typeProvider.stringType); |
| 13999 } |
| 14000 |
| 14001 void test_propagatedReturnType_localFunction() { |
| 14002 String code = r''' |
| 14003 main() { |
| 14004 f() => 42; |
| 14005 var v = f(); |
| 14006 }'''; |
| 14007 _assertPropagatedAssignedType( |
| 14008 code, typeProvider.dynamicType, typeProvider.intType); |
| 14009 } |
| 14010 |
| 14011 void test_query() { |
| 14012 Source source = addSource(r''' |
| 14013 import 'dart:html'; |
| 14014 |
| 14015 main() { |
| 14016 var v1 = query('a'); |
| 14017 var v2 = query('A'); |
| 14018 var v3 = query('body:active'); |
| 14019 var v4 = query('button[foo="bar"]'); |
| 14020 var v5 = query('div.class'); |
| 14021 var v6 = query('input#id'); |
| 14022 var v7 = query('select#id'); |
| 14023 // invocation of method |
| 14024 var m1 = document.query('div'); |
| 14025 // unsupported currently |
| 14026 var b1 = query('noSuchTag'); |
| 14027 var b2 = query('DART_EDITOR_NO_SUCH_TYPE'); |
| 14028 var b3 = query('body div'); |
| 14029 return [v1, v2, v3, v4, v5, v6, v7, m1, b1, b2, b3]; |
| 14030 }'''); |
| 14031 LibraryElement library = resolve2(source); |
| 14032 assertNoErrors(source); |
| 14033 verify([source]); |
| 14034 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 14035 FunctionDeclaration main = unit.declarations[0] as FunctionDeclaration; |
| 14036 BlockFunctionBody body = main.functionExpression.body as BlockFunctionBody; |
| 14037 ReturnStatement statement = body.block.statements[11] as ReturnStatement; |
| 14038 NodeList<Expression> elements = |
| 14039 (statement.expression as ListLiteral).elements; |
| 14040 expect(elements[0].propagatedType.name, "AnchorElement"); |
| 14041 expect(elements[1].propagatedType.name, "AnchorElement"); |
| 14042 expect(elements[2].propagatedType.name, "BodyElement"); |
| 14043 expect(elements[3].propagatedType.name, "ButtonElement"); |
| 14044 expect(elements[4].propagatedType.name, "DivElement"); |
| 14045 expect(elements[5].propagatedType.name, "InputElement"); |
| 14046 expect(elements[6].propagatedType.name, "SelectElement"); |
| 14047 expect(elements[7].propagatedType.name, "DivElement"); |
| 14048 expect(elements[8].propagatedType.name, "Element"); |
| 14049 expect(elements[9].propagatedType.name, "Element"); |
| 14050 expect(elements[10].propagatedType.name, "Element"); |
| 14051 } |
| 14052 } |
| 14053 |
| 14054 @reflectiveTest |
| 14055 class TypeProviderImplTest extends EngineTestCase { |
| 14056 void test_creation() { |
| 14057 // |
| 14058 // Create a mock library element with the types expected to be in dart:core. |
| 14059 // We cannot use either ElementFactory or TestTypeProvider (which uses |
| 14060 // ElementFactory) because we side-effect the elements in ways that would |
| 14061 // break other tests. |
| 14062 // |
| 14063 InterfaceType objectType = _classElement("Object", null).type; |
| 14064 InterfaceType boolType = _classElement("bool", objectType).type; |
| 14065 InterfaceType numType = _classElement("num", objectType).type; |
| 14066 InterfaceType doubleType = _classElement("double", numType).type; |
| 14067 InterfaceType functionType = _classElement("Function", objectType).type; |
| 14068 InterfaceType futureType = _classElement("Future", objectType, ["T"]).type; |
| 14069 InterfaceType intType = _classElement("int", numType).type; |
| 14070 InterfaceType iterableType = |
| 14071 _classElement("Iterable", objectType, ["T"]).type; |
| 14072 InterfaceType listType = _classElement("List", objectType, ["E"]).type; |
| 14073 InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type; |
| 14074 InterfaceType stackTraceType = _classElement("StackTrace", objectType).type; |
| 14075 InterfaceType streamType = _classElement("Stream", objectType, ["T"]).type; |
| 14076 InterfaceType stringType = _classElement("String", objectType).type; |
| 14077 InterfaceType symbolType = _classElement("Symbol", objectType).type; |
| 14078 InterfaceType typeType = _classElement("Type", objectType).type; |
| 14079 CompilationUnitElementImpl coreUnit = |
| 14080 new CompilationUnitElementImpl("core.dart"); |
| 14081 coreUnit.types = <ClassElement>[ |
| 14082 boolType.element, |
| 14083 doubleType.element, |
| 14084 functionType.element, |
| 14085 intType.element, |
| 14086 iterableType.element, |
| 14087 listType.element, |
| 14088 mapType.element, |
| 14089 objectType.element, |
| 14090 stackTraceType.element, |
| 14091 stringType.element, |
| 14092 symbolType.element, |
| 14093 typeType.element |
| 14094 ]; |
| 14095 CompilationUnitElementImpl asyncUnit = |
| 14096 new CompilationUnitElementImpl("async.dart"); |
| 14097 asyncUnit.types = <ClassElement>[futureType.element, streamType.element]; |
| 14098 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); |
| 14099 LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode( |
| 14100 context, AstFactory.libraryIdentifier2(["dart.core"])); |
| 14101 coreLibrary.definingCompilationUnit = coreUnit; |
| 14102 LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode( |
| 14103 context, AstFactory.libraryIdentifier2(["dart.async"])); |
| 14104 asyncLibrary.definingCompilationUnit = asyncUnit; |
| 14105 // |
| 14106 // Create a type provider and ensure that it can return the expected types. |
| 14107 // |
| 14108 TypeProviderImpl provider = new TypeProviderImpl(coreLibrary, asyncLibrary); |
| 14109 expect(provider.boolType, same(boolType)); |
| 14110 expect(provider.bottomType, isNotNull); |
| 14111 expect(provider.doubleType, same(doubleType)); |
| 14112 expect(provider.dynamicType, isNotNull); |
| 14113 expect(provider.functionType, same(functionType)); |
| 14114 expect(provider.futureType, same(futureType)); |
| 14115 expect(provider.intType, same(intType)); |
| 14116 expect(provider.listType, same(listType)); |
| 14117 expect(provider.mapType, same(mapType)); |
| 14118 expect(provider.objectType, same(objectType)); |
| 14119 expect(provider.stackTraceType, same(stackTraceType)); |
| 14120 expect(provider.stringType, same(stringType)); |
| 14121 expect(provider.symbolType, same(symbolType)); |
| 14122 expect(provider.typeType, same(typeType)); |
| 14123 } |
| 14124 |
| 14125 ClassElement _classElement(String typeName, InterfaceType superclassType, |
| 14126 [List<String> parameterNames]) { |
| 14127 ClassElementImpl element = |
| 14128 new ClassElementImpl.forNode(AstFactory.identifier3(typeName)); |
| 14129 element.supertype = superclassType; |
| 14130 InterfaceTypeImpl type = new InterfaceTypeImpl(element); |
| 14131 element.type = type; |
| 14132 if (parameterNames != null) { |
| 14133 int count = parameterNames.length; |
| 14134 if (count > 0) { |
| 14135 List<TypeParameterElementImpl> typeParameters = |
| 14136 new List<TypeParameterElementImpl>(count); |
| 14137 List<TypeParameterTypeImpl> typeArguments = |
| 14138 new List<TypeParameterTypeImpl>(count); |
| 14139 for (int i = 0; i < count; i++) { |
| 14140 TypeParameterElementImpl typeParameter = |
| 14141 new TypeParameterElementImpl.forNode( |
| 14142 AstFactory.identifier3(parameterNames[i])); |
| 14143 typeParameters[i] = typeParameter; |
| 14144 typeArguments[i] = new TypeParameterTypeImpl(typeParameter); |
| 14145 typeParameter.type = typeArguments[i]; |
| 14146 } |
| 14147 element.typeParameters = typeParameters; |
| 14148 type.typeArguments = typeArguments; |
| 14149 } |
| 14150 } |
| 14151 return element; |
| 14152 } |
| 14153 } |
| 14154 |
| 14155 @reflectiveTest |
| 14156 class TypeResolverVisitorTest extends EngineTestCase { |
| 14157 /** |
| 14158 * The error listener to which errors will be reported. |
| 14159 */ |
| 14160 GatheringErrorListener _listener; |
| 14161 |
| 14162 /** |
| 14163 * The object representing the information about the library in which the type
s are being |
| 14164 * resolved. |
| 14165 */ |
| 14166 Library _library; |
| 14167 |
| 14168 /** |
| 14169 * The type provider used to access the types. |
| 14170 */ |
| 14171 TestTypeProvider _typeProvider; |
| 14172 |
| 14173 /** |
| 14174 * The visitor used to resolve types needed to form the type hierarchy. |
| 14175 */ |
| 14176 TypeResolverVisitor _visitor; |
| 14177 |
| 14178 void fail_visitConstructorDeclaration() { |
| 14179 fail("Not yet tested"); |
| 14180 _listener.assertNoErrors(); |
| 14181 } |
| 14182 |
| 14183 void fail_visitFunctionTypeAlias() { |
| 14184 fail("Not yet tested"); |
| 14185 _listener.assertNoErrors(); |
| 14186 } |
| 14187 |
| 14188 void fail_visitVariableDeclaration() { |
| 14189 fail("Not yet tested"); |
| 14190 ClassElement type = ElementFactory.classElement2("A"); |
| 14191 VariableDeclaration node = AstFactory.variableDeclaration("a"); |
| 14192 AstFactory.variableDeclarationList(null, AstFactory.typeName(type), [node]); |
| 14193 //resolve(node); |
| 14194 expect(node.name.staticType, same(type.type)); |
| 14195 _listener.assertNoErrors(); |
| 14196 } |
| 14197 |
| 14198 @override |
| 14199 void setUp() { |
| 14200 _listener = new GatheringErrorListener(); |
| 14201 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 14202 Source librarySource = |
| 14203 new FileBasedSource(FileUtilities2.createFile("/lib.dart")); |
| 14204 _library = new Library(context, _listener, librarySource); |
| 14205 LibraryElementImpl element = new LibraryElementImpl.forNode( |
| 14206 context, AstFactory.libraryIdentifier2(["lib"])); |
| 14207 element.definingCompilationUnit = |
| 14208 new CompilationUnitElementImpl("lib.dart"); |
| 14209 _library.libraryElement = element; |
| 14210 _typeProvider = new TestTypeProvider(); |
| 14211 _visitor = new TypeResolverVisitor(_library.libraryElement, librarySource, |
| 14212 _typeProvider, _library.errorListener, |
| 14213 nameScope: _library.libraryScope); |
| 14214 } |
| 14215 |
| 14216 void test_visitCatchClause_exception() { |
| 14217 // catch (e) |
| 14218 CatchClause clause = AstFactory.catchClause("e"); |
| 14219 SimpleIdentifier exceptionParameter = clause.exceptionParameter; |
| 14220 exceptionParameter.staticElement = |
| 14221 new LocalVariableElementImpl.forNode(exceptionParameter); |
| 14222 _resolveCatchClause(clause, _typeProvider.dynamicType, null); |
| 14223 _listener.assertNoErrors(); |
| 14224 } |
| 14225 |
| 14226 void test_visitCatchClause_exception_stackTrace() { |
| 14227 // catch (e, s) |
| 14228 CatchClause clause = AstFactory.catchClause2("e", "s"); |
| 14229 SimpleIdentifier exceptionParameter = clause.exceptionParameter; |
| 14230 exceptionParameter.staticElement = |
| 14231 new LocalVariableElementImpl.forNode(exceptionParameter); |
| 14232 SimpleIdentifier stackTraceParameter = clause.stackTraceParameter; |
| 14233 stackTraceParameter.staticElement = |
| 14234 new LocalVariableElementImpl.forNode(stackTraceParameter); |
| 14235 _resolveCatchClause( |
| 14236 clause, _typeProvider.dynamicType, _typeProvider.stackTraceType); |
| 14237 _listener.assertNoErrors(); |
| 14238 } |
| 14239 |
| 14240 void test_visitCatchClause_on_exception() { |
| 14241 // on E catch (e) |
| 14242 ClassElement exceptionElement = ElementFactory.classElement2("E"); |
| 14243 TypeName exceptionType = AstFactory.typeName(exceptionElement); |
| 14244 CatchClause clause = AstFactory.catchClause4(exceptionType, "e"); |
| 14245 SimpleIdentifier exceptionParameter = clause.exceptionParameter; |
| 14246 exceptionParameter.staticElement = |
| 14247 new LocalVariableElementImpl.forNode(exceptionParameter); |
| 14248 _resolveCatchClause( |
| 14249 clause, exceptionElement.type, null, [exceptionElement]); |
| 14250 _listener.assertNoErrors(); |
| 14251 } |
| 14252 |
| 14253 void test_visitCatchClause_on_exception_stackTrace() { |
| 14254 // on E catch (e, s) |
| 14255 ClassElement exceptionElement = ElementFactory.classElement2("E"); |
| 14256 TypeName exceptionType = AstFactory.typeName(exceptionElement); |
| 14257 (exceptionType.name as SimpleIdentifier).staticElement = exceptionElement; |
| 14258 CatchClause clause = AstFactory.catchClause5(exceptionType, "e", "s"); |
| 14259 SimpleIdentifier exceptionParameter = clause.exceptionParameter; |
| 14260 exceptionParameter.staticElement = |
| 14261 new LocalVariableElementImpl.forNode(exceptionParameter); |
| 14262 SimpleIdentifier stackTraceParameter = clause.stackTraceParameter; |
| 14263 stackTraceParameter.staticElement = |
| 14264 new LocalVariableElementImpl.forNode(stackTraceParameter); |
| 14265 _resolveCatchClause(clause, exceptionElement.type, |
| 14266 _typeProvider.stackTraceType, [exceptionElement]); |
| 14267 _listener.assertNoErrors(); |
| 14268 } |
| 14269 |
| 14270 void test_visitClassDeclaration() { |
| 14271 // class A extends B with C implements D {} |
| 14272 // class B {} |
| 14273 // class C {} |
| 14274 // class D {} |
| 14275 ClassElement elementA = ElementFactory.classElement2("A"); |
| 14276 ClassElement elementB = ElementFactory.classElement2("B"); |
| 14277 ClassElement elementC = ElementFactory.classElement2("C"); |
| 14278 ClassElement elementD = ElementFactory.classElement2("D"); |
| 14279 ExtendsClause extendsClause = |
| 14280 AstFactory.extendsClause(AstFactory.typeName(elementB)); |
| 14281 WithClause withClause = |
| 14282 AstFactory.withClause([AstFactory.typeName(elementC)]); |
| 14283 ImplementsClause implementsClause = |
| 14284 AstFactory.implementsClause([AstFactory.typeName(elementD)]); |
| 14285 ClassDeclaration declaration = AstFactory.classDeclaration( |
| 14286 null, "A", null, extendsClause, withClause, implementsClause); |
| 14287 declaration.name.staticElement = elementA; |
| 14288 _resolveNode(declaration, [elementA, elementB, elementC, elementD]); |
| 14289 expect(elementA.supertype, same(elementB.type)); |
| 14290 List<InterfaceType> mixins = elementA.mixins; |
| 14291 expect(mixins, hasLength(1)); |
| 14292 expect(mixins[0], same(elementC.type)); |
| 14293 List<InterfaceType> interfaces = elementA.interfaces; |
| 14294 expect(interfaces, hasLength(1)); |
| 14295 expect(interfaces[0], same(elementD.type)); |
| 14296 _listener.assertNoErrors(); |
| 14297 } |
| 14298 |
| 14299 void test_visitClassDeclaration_instanceMemberCollidesWithClass() { |
| 14300 // class A {} |
| 14301 // class B extends A { |
| 14302 // void A() {} |
| 14303 // } |
| 14304 ClassElementImpl elementA = ElementFactory.classElement2("A"); |
| 14305 ClassElementImpl elementB = ElementFactory.classElement2("B"); |
| 14306 elementB.methods = <MethodElement>[ |
| 14307 ElementFactory.methodElement("A", VoidTypeImpl.instance) |
| 14308 ]; |
| 14309 ExtendsClause extendsClause = |
| 14310 AstFactory.extendsClause(AstFactory.typeName(elementA)); |
| 14311 ClassDeclaration declaration = |
| 14312 AstFactory.classDeclaration(null, "B", null, extendsClause, null, null); |
| 14313 declaration.name.staticElement = elementB; |
| 14314 _resolveNode(declaration, [elementA, elementB]); |
| 14315 expect(elementB.supertype, same(elementA.type)); |
| 14316 _listener.assertNoErrors(); |
| 14317 } |
| 14318 |
| 14319 void test_visitClassTypeAlias() { |
| 14320 // class A = B with C implements D; |
| 14321 ClassElement elementA = ElementFactory.classElement2("A"); |
| 14322 ClassElement elementB = ElementFactory.classElement2("B"); |
| 14323 ClassElement elementC = ElementFactory.classElement2("C"); |
| 14324 ClassElement elementD = ElementFactory.classElement2("D"); |
| 14325 WithClause withClause = |
| 14326 AstFactory.withClause([AstFactory.typeName(elementC)]); |
| 14327 ImplementsClause implementsClause = |
| 14328 AstFactory.implementsClause([AstFactory.typeName(elementD)]); |
| 14329 ClassTypeAlias alias = AstFactory.classTypeAlias("A", null, null, |
| 14330 AstFactory.typeName(elementB), withClause, implementsClause); |
| 14331 alias.name.staticElement = elementA; |
| 14332 _resolveNode(alias, [elementA, elementB, elementC, elementD]); |
| 14333 expect(elementA.supertype, same(elementB.type)); |
| 14334 List<InterfaceType> mixins = elementA.mixins; |
| 14335 expect(mixins, hasLength(1)); |
| 14336 expect(mixins[0], same(elementC.type)); |
| 14337 List<InterfaceType> interfaces = elementA.interfaces; |
| 14338 expect(interfaces, hasLength(1)); |
| 14339 expect(interfaces[0], same(elementD.type)); |
| 14340 _listener.assertNoErrors(); |
| 14341 } |
| 14342 |
| 14343 void test_visitClassTypeAlias_constructorWithOptionalParams_ignored() { |
| 14344 // class T {} |
| 14345 // class B { |
| 14346 // B.c1(); |
| 14347 // B.c2([T a0]); |
| 14348 // B.c3({T a0}); |
| 14349 // } |
| 14350 // class M {} |
| 14351 // class C = B with M |
| 14352 ClassElement classT = ElementFactory.classElement2('T', []); |
| 14353 ClassElementImpl classB = ElementFactory.classElement2('B', []); |
| 14354 ConstructorElementImpl constructorBc1 = |
| 14355 ElementFactory.constructorElement2(classB, 'c1', []); |
| 14356 ConstructorElementImpl constructorBc2 = |
| 14357 ElementFactory.constructorElement2(classB, 'c2', [classT.type]); |
| 14358 (constructorBc2.parameters[0] as ParameterElementImpl).parameterKind = |
| 14359 ParameterKind.POSITIONAL; |
| 14360 ConstructorElementImpl constructorBc3 = |
| 14361 ElementFactory.constructorElement2(classB, 'c3', [classT.type]); |
| 14362 (constructorBc3.parameters[0] as ParameterElementImpl).parameterKind = |
| 14363 ParameterKind.NAMED; |
| 14364 classB.constructors = [constructorBc1, constructorBc2, constructorBc3]; |
| 14365 ClassElement classM = ElementFactory.classElement2('M', []); |
| 14366 WithClause withClause = |
| 14367 AstFactory.withClause([AstFactory.typeName(classM, [])]); |
| 14368 ClassElement classC = ElementFactory.classTypeAlias2('C', []); |
| 14369 ClassTypeAlias alias = AstFactory.classTypeAlias( |
| 14370 'C', null, null, AstFactory.typeName(classB, []), withClause, null); |
| 14371 alias.name.staticElement = classC; |
| 14372 _resolveNode(alias, [classT, classB, classM, classC]); |
| 14373 expect(classC.constructors, hasLength(1)); |
| 14374 ConstructorElement constructor = classC.constructors[0]; |
| 14375 expect(constructor.isFactory, isFalse); |
| 14376 expect(constructor.isSynthetic, isTrue); |
| 14377 expect(constructor.name, 'c1'); |
| 14378 expect(constructor.functions, hasLength(0)); |
| 14379 expect(constructor.labels, hasLength(0)); |
| 14380 expect(constructor.localVariables, hasLength(0)); |
| 14381 expect(constructor.parameters, isEmpty); |
| 14382 } |
| 14383 |
| 14384 void test_visitClassTypeAlias_constructorWithParams() { |
| 14385 // class T {} |
| 14386 // class B { |
| 14387 // B(T a0); |
| 14388 // } |
| 14389 // class M {} |
| 14390 // class C = B with M |
| 14391 ClassElement classT = ElementFactory.classElement2('T', []); |
| 14392 ClassElementImpl classB = ElementFactory.classElement2('B', []); |
| 14393 ConstructorElementImpl constructorB = |
| 14394 ElementFactory.constructorElement2(classB, '', [classT.type]); |
| 14395 classB.constructors = [constructorB]; |
| 14396 ClassElement classM = ElementFactory.classElement2('M', []); |
| 14397 WithClause withClause = |
| 14398 AstFactory.withClause([AstFactory.typeName(classM, [])]); |
| 14399 ClassElement classC = ElementFactory.classTypeAlias2('C', []); |
| 14400 ClassTypeAlias alias = AstFactory.classTypeAlias( |
| 14401 'C', null, null, AstFactory.typeName(classB, []), withClause, null); |
| 14402 alias.name.staticElement = classC; |
| 14403 _resolveNode(alias, [classT, classB, classM, classC]); |
| 14404 expect(classC.constructors, hasLength(1)); |
| 14405 ConstructorElement constructor = classC.constructors[0]; |
| 14406 expect(constructor.isFactory, isFalse); |
| 14407 expect(constructor.isSynthetic, isTrue); |
| 14408 expect(constructor.name, ''); |
| 14409 expect(constructor.functions, hasLength(0)); |
| 14410 expect(constructor.labels, hasLength(0)); |
| 14411 expect(constructor.localVariables, hasLength(0)); |
| 14412 expect(constructor.parameters, hasLength(1)); |
| 14413 expect(constructor.parameters[0].type, equals(classT.type)); |
| 14414 expect(constructor.parameters[0].name, |
| 14415 equals(constructorB.parameters[0].name)); |
| 14416 } |
| 14417 |
| 14418 void test_visitClassTypeAlias_defaultConstructor() { |
| 14419 // class B {} |
| 14420 // class M {} |
| 14421 // class C = B with M |
| 14422 ClassElementImpl classB = ElementFactory.classElement2('B', []); |
| 14423 ConstructorElementImpl constructorB = |
| 14424 ElementFactory.constructorElement2(classB, '', []); |
| 14425 constructorB.setModifier(Modifier.SYNTHETIC, true); |
| 14426 classB.constructors = [constructorB]; |
| 14427 ClassElement classM = ElementFactory.classElement2('M', []); |
| 14428 WithClause withClause = |
| 14429 AstFactory.withClause([AstFactory.typeName(classM, [])]); |
| 14430 ClassElement classC = ElementFactory.classTypeAlias2('C', []); |
| 14431 ClassTypeAlias alias = AstFactory.classTypeAlias( |
| 14432 'C', null, null, AstFactory.typeName(classB, []), withClause, null); |
| 14433 alias.name.staticElement = classC; |
| 14434 _resolveNode(alias, [classB, classM, classC]); |
| 14435 expect(classC.constructors, hasLength(1)); |
| 14436 ConstructorElement constructor = classC.constructors[0]; |
| 14437 expect(constructor.isFactory, isFalse); |
| 14438 expect(constructor.isSynthetic, isTrue); |
| 14439 expect(constructor.name, ''); |
| 14440 expect(constructor.functions, hasLength(0)); |
| 14441 expect(constructor.labels, hasLength(0)); |
| 14442 expect(constructor.localVariables, hasLength(0)); |
| 14443 expect(constructor.parameters, isEmpty); |
| 14444 } |
| 14445 |
| 14446 void test_visitFieldFormalParameter_functionType() { |
| 14447 InterfaceType intType = _typeProvider.intType; |
| 14448 TypeName intTypeName = AstFactory.typeName4("int"); |
| 14449 String innerParameterName = "a"; |
| 14450 SimpleFormalParameter parameter = |
| 14451 AstFactory.simpleFormalParameter3(innerParameterName); |
| 14452 parameter.identifier.staticElement = |
| 14453 ElementFactory.requiredParameter(innerParameterName); |
| 14454 String outerParameterName = "p"; |
| 14455 FormalParameter node = AstFactory.fieldFormalParameter(null, intTypeName, |
| 14456 outerParameterName, AstFactory.formalParameterList([parameter])); |
| 14457 node.identifier.staticElement = |
| 14458 ElementFactory.requiredParameter(outerParameterName); |
| 14459 DartType parameterType = _resolveFormalParameter(node, [intType.element]); |
| 14460 EngineTestCase.assertInstanceOf( |
| 14461 (obj) => obj is FunctionType, FunctionType, parameterType); |
| 14462 FunctionType functionType = parameterType as FunctionType; |
| 14463 expect(functionType.returnType, same(intType)); |
| 14464 expect(functionType.parameters, hasLength(1)); |
| 14465 _listener.assertNoErrors(); |
| 14466 } |
| 14467 |
| 14468 void test_visitFieldFormalParameter_noType() { |
| 14469 String parameterName = "p"; |
| 14470 FormalParameter node = |
| 14471 AstFactory.fieldFormalParameter(Keyword.VAR, null, parameterName); |
| 14472 node.identifier.staticElement = |
| 14473 ElementFactory.requiredParameter(parameterName); |
| 14474 expect(_resolveFormalParameter(node), same(_typeProvider.dynamicType)); |
| 14475 _listener.assertNoErrors(); |
| 14476 } |
| 14477 |
| 14478 void test_visitFieldFormalParameter_type() { |
| 14479 InterfaceType intType = _typeProvider.intType; |
| 14480 TypeName intTypeName = AstFactory.typeName4("int"); |
| 14481 String parameterName = "p"; |
| 14482 FormalParameter node = |
| 14483 AstFactory.fieldFormalParameter(null, intTypeName, parameterName); |
| 14484 node.identifier.staticElement = |
| 14485 ElementFactory.requiredParameter(parameterName); |
| 14486 expect(_resolveFormalParameter(node, [intType.element]), same(intType)); |
| 14487 _listener.assertNoErrors(); |
| 14488 } |
| 14489 |
| 14490 void test_visitFunctionDeclaration() { |
| 14491 // R f(P p) {} |
| 14492 // class R {} |
| 14493 // class P {} |
| 14494 ClassElement elementR = ElementFactory.classElement2('R'); |
| 14495 ClassElement elementP = ElementFactory.classElement2('P'); |
| 14496 FunctionElement elementF = ElementFactory.functionElement('f'); |
| 14497 FunctionDeclaration declaration = AstFactory.functionDeclaration( |
| 14498 AstFactory.typeName4('R'), |
| 14499 null, |
| 14500 'f', |
| 14501 AstFactory.functionExpression2( |
| 14502 AstFactory.formalParameterList([ |
| 14503 AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p') |
| 14504 ]), |
| 14505 null)); |
| 14506 declaration.name.staticElement = elementF; |
| 14507 _resolveNode(declaration, [elementR, elementP]); |
| 14508 expect(declaration.returnType.type, elementR.type); |
| 14509 SimpleFormalParameter parameter = |
| 14510 declaration.functionExpression.parameters.parameters[0]; |
| 14511 expect(parameter.type.type, elementP.type); |
| 14512 _listener.assertNoErrors(); |
| 14513 } |
| 14514 |
| 14515 void test_visitFunctionDeclaration_typeParameter() { |
| 14516 // E f<E>(E e) {} |
| 14517 TypeParameterElement elementE = ElementFactory.typeParameterElement('E'); |
| 14518 FunctionElementImpl elementF = ElementFactory.functionElement('f'); |
| 14519 elementF.typeParameters = <TypeParameterElement>[elementE]; |
| 14520 FunctionDeclaration declaration = AstFactory.functionDeclaration( |
| 14521 AstFactory.typeName4('E'), |
| 14522 null, |
| 14523 'f', |
| 14524 AstFactory.functionExpression2( |
| 14525 AstFactory.formalParameterList([ |
| 14526 AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e') |
| 14527 ]), |
| 14528 null)); |
| 14529 declaration.name.staticElement = elementF; |
| 14530 _resolveNode(declaration, []); |
| 14531 expect(declaration.returnType.type, elementE.type); |
| 14532 SimpleFormalParameter parameter = |
| 14533 declaration.functionExpression.parameters.parameters[0]; |
| 14534 expect(parameter.type.type, elementE.type); |
| 14535 _listener.assertNoErrors(); |
| 14536 } |
| 14537 |
| 14538 void test_visitFunctionTypedFormalParameter() { |
| 14539 // R f(R g(P p)) {} |
| 14540 // class R {} |
| 14541 // class P {} |
| 14542 ClassElement elementR = ElementFactory.classElement2('R'); |
| 14543 ClassElement elementP = ElementFactory.classElement2('P'); |
| 14544 FunctionElement elementF = ElementFactory.functionElement('f'); |
| 14545 ParameterElementImpl requiredParameter = |
| 14546 ElementFactory.requiredParameter('p'); |
| 14547 FunctionTypedFormalParameter parameterDeclaration = AstFactory |
| 14548 .functionTypedFormalParameter(AstFactory.typeName4('R'), 'g', [ |
| 14549 AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p') |
| 14550 ]); |
| 14551 parameterDeclaration.identifier.staticElement = requiredParameter; |
| 14552 FunctionDeclaration declaration = AstFactory.functionDeclaration( |
| 14553 AstFactory.typeName4('R'), |
| 14554 null, |
| 14555 'f', |
| 14556 AstFactory.functionExpression2( |
| 14557 AstFactory.formalParameterList([parameterDeclaration]), null)); |
| 14558 declaration.name.staticElement = elementF; |
| 14559 _resolveNode(declaration, [elementR, elementP]); |
| 14560 expect(declaration.returnType.type, elementR.type); |
| 14561 FunctionTypedFormalParameter parameter = |
| 14562 declaration.functionExpression.parameters.parameters[0]; |
| 14563 expect(parameter.returnType.type, elementR.type); |
| 14564 SimpleFormalParameter innerParameter = parameter.parameters.parameters[0]; |
| 14565 expect(innerParameter.type.type, elementP.type); |
| 14566 _listener.assertNoErrors(); |
| 14567 } |
| 14568 |
| 14569 void test_visitFunctionTypedFormalParameter_typeParameter() { |
| 14570 // R f(R g<E>(E e)) {} |
| 14571 // class R {} |
| 14572 ClassElement elementR = ElementFactory.classElement2('R'); |
| 14573 TypeParameterElement elementE = ElementFactory.typeParameterElement('E'); |
| 14574 FunctionElement elementF = ElementFactory.functionElement('f'); |
| 14575 ParameterElementImpl requiredParameter = |
| 14576 ElementFactory.requiredParameter('g'); |
| 14577 requiredParameter.typeParameters = <TypeParameterElement>[elementE]; |
| 14578 FunctionTypedFormalParameter parameterDeclaration = AstFactory |
| 14579 .functionTypedFormalParameter(AstFactory.typeName4('R'), 'g', [ |
| 14580 AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e') |
| 14581 ]); |
| 14582 parameterDeclaration.identifier.staticElement = requiredParameter; |
| 14583 FunctionDeclaration declaration = AstFactory.functionDeclaration( |
| 14584 AstFactory.typeName4('R'), |
| 14585 null, |
| 14586 'f', |
| 14587 AstFactory.functionExpression2( |
| 14588 AstFactory.formalParameterList([parameterDeclaration]), null)); |
| 14589 declaration.name.staticElement = elementF; |
| 14590 _resolveNode(declaration, [elementR]); |
| 14591 expect(declaration.returnType.type, elementR.type); |
| 14592 FunctionTypedFormalParameter parameter = |
| 14593 declaration.functionExpression.parameters.parameters[0]; |
| 14594 expect(parameter.returnType.type, elementR.type); |
| 14595 SimpleFormalParameter innerParameter = parameter.parameters.parameters[0]; |
| 14596 expect(innerParameter.type.type, elementE.type); |
| 14597 _listener.assertNoErrors(); |
| 14598 } |
| 14599 |
| 14600 void test_visitMethodDeclaration() { |
| 14601 // class A { |
| 14602 // R m(P p) {} |
| 14603 // } |
| 14604 // class R {} |
| 14605 // class P {} |
| 14606 ClassElementImpl elementA = ElementFactory.classElement2('A'); |
| 14607 ClassElement elementR = ElementFactory.classElement2('R'); |
| 14608 ClassElement elementP = ElementFactory.classElement2('P'); |
| 14609 MethodElement elementM = ElementFactory.methodElement('m', null); |
| 14610 elementA.methods = <MethodElement>[elementM]; |
| 14611 MethodDeclaration declaration = AstFactory.methodDeclaration( |
| 14612 null, |
| 14613 AstFactory.typeName4('R'), |
| 14614 null, |
| 14615 null, |
| 14616 AstFactory.identifier3('m'), |
| 14617 AstFactory.formalParameterList([ |
| 14618 AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p') |
| 14619 ])); |
| 14620 declaration.name.staticElement = elementM; |
| 14621 _resolveNode(declaration, [elementA, elementR, elementP]); |
| 14622 expect(declaration.returnType.type, elementR.type); |
| 14623 SimpleFormalParameter parameter = declaration.parameters.parameters[0]; |
| 14624 expect(parameter.type.type, elementP.type); |
| 14625 _listener.assertNoErrors(); |
| 14626 } |
| 14627 |
| 14628 void test_visitMethodDeclaration_typeParameter() { |
| 14629 // class A { |
| 14630 // E m<E>(E e) {} |
| 14631 // } |
| 14632 ClassElementImpl elementA = ElementFactory.classElement2('A'); |
| 14633 TypeParameterElement elementE = ElementFactory.typeParameterElement('E'); |
| 14634 MethodElementImpl elementM = ElementFactory.methodElement('m', null); |
| 14635 elementM.typeParameters = <TypeParameterElement>[elementE]; |
| 14636 elementA.methods = <MethodElement>[elementM]; |
| 14637 MethodDeclaration declaration = AstFactory.methodDeclaration( |
| 14638 null, |
| 14639 AstFactory.typeName4('E'), |
| 14640 null, |
| 14641 null, |
| 14642 AstFactory.identifier3('m'), |
| 14643 AstFactory.formalParameterList([ |
| 14644 AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e') |
| 14645 ])); |
| 14646 declaration.name.staticElement = elementM; |
| 14647 _resolveNode(declaration, [elementA]); |
| 14648 expect(declaration.returnType.type, elementE.type); |
| 14649 SimpleFormalParameter parameter = declaration.parameters.parameters[0]; |
| 14650 expect(parameter.type.type, elementE.type); |
| 14651 _listener.assertNoErrors(); |
| 14652 } |
| 14653 |
| 14654 void test_visitSimpleFormalParameter_noType() { |
| 14655 // p |
| 14656 FormalParameter node = AstFactory.simpleFormalParameter3("p"); |
| 14657 node.identifier.staticElement = |
| 14658 new ParameterElementImpl.forNode(AstFactory.identifier3("p")); |
| 14659 expect(_resolveFormalParameter(node), same(_typeProvider.dynamicType)); |
| 14660 _listener.assertNoErrors(); |
| 14661 } |
| 14662 |
| 14663 void test_visitSimpleFormalParameter_type() { |
| 14664 // int p |
| 14665 InterfaceType intType = _typeProvider.intType; |
| 14666 ClassElement intElement = intType.element; |
| 14667 FormalParameter node = |
| 14668 AstFactory.simpleFormalParameter4(AstFactory.typeName(intElement), "p"); |
| 14669 SimpleIdentifier identifier = node.identifier; |
| 14670 ParameterElementImpl element = new ParameterElementImpl.forNode(identifier); |
| 14671 identifier.staticElement = element; |
| 14672 expect(_resolveFormalParameter(node, [intElement]), same(intType)); |
| 14673 _listener.assertNoErrors(); |
| 14674 } |
| 14675 |
| 14676 void test_visitTypeName_noParameters_noArguments() { |
| 14677 ClassElement classA = ElementFactory.classElement2("A"); |
| 14678 TypeName typeName = AstFactory.typeName(classA); |
| 14679 typeName.type = null; |
| 14680 _resolveNode(typeName, [classA]); |
| 14681 expect(typeName.type, same(classA.type)); |
| 14682 _listener.assertNoErrors(); |
| 14683 } |
| 14684 |
| 14685 void test_visitTypeName_parameters_arguments() { |
| 14686 ClassElement classA = ElementFactory.classElement2("A", ["E"]); |
| 14687 ClassElement classB = ElementFactory.classElement2("B"); |
| 14688 TypeName typeName = |
| 14689 AstFactory.typeName(classA, [AstFactory.typeName(classB)]); |
| 14690 typeName.type = null; |
| 14691 _resolveNode(typeName, [classA, classB]); |
| 14692 InterfaceType resultType = typeName.type as InterfaceType; |
| 14693 expect(resultType.element, same(classA)); |
| 14694 List<DartType> resultArguments = resultType.typeArguments; |
| 14695 expect(resultArguments, hasLength(1)); |
| 14696 expect(resultArguments[0], same(classB.type)); |
| 14697 _listener.assertNoErrors(); |
| 14698 } |
| 14699 |
| 14700 void test_visitTypeName_parameters_noArguments() { |
| 14701 ClassElement classA = ElementFactory.classElement2("A", ["E"]); |
| 14702 TypeName typeName = AstFactory.typeName(classA); |
| 14703 typeName.type = null; |
| 14704 _resolveNode(typeName, [classA]); |
| 14705 InterfaceType resultType = typeName.type as InterfaceType; |
| 14706 expect(resultType.element, same(classA)); |
| 14707 List<DartType> resultArguments = resultType.typeArguments; |
| 14708 expect(resultArguments, hasLength(1)); |
| 14709 expect(resultArguments[0], same(DynamicTypeImpl.instance)); |
| 14710 _listener.assertNoErrors(); |
| 14711 } |
| 14712 |
| 14713 void test_visitTypeName_void() { |
| 14714 ClassElement classA = ElementFactory.classElement2("A"); |
| 14715 TypeName typeName = AstFactory.typeName4("void"); |
| 14716 _resolveNode(typeName, [classA]); |
| 14717 expect(typeName.type, same(VoidTypeImpl.instance)); |
| 14718 _listener.assertNoErrors(); |
| 14719 } |
| 14720 |
| 14721 /** |
| 14722 * Analyze the given catch clause and assert that the types of the parameters
have been set to the |
| 14723 * given types. The types can be null if the catch clause does not have the co
rresponding |
| 14724 * parameter. |
| 14725 * |
| 14726 * @param node the catch clause to be analyzed |
| 14727 * @param exceptionType the expected type of the exception parameter |
| 14728 * @param stackTraceType the expected type of the stack trace parameter |
| 14729 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 14730 * being resolved |
| 14731 */ |
| 14732 void _resolveCatchClause( |
| 14733 CatchClause node, DartType exceptionType, InterfaceType stackTraceType, |
| 14734 [List<Element> definedElements]) { |
| 14735 _resolveNode(node, definedElements); |
| 14736 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| 14737 if (exceptionParameter != null) { |
| 14738 expect(exceptionParameter.staticType, same(exceptionType)); |
| 14739 } |
| 14740 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; |
| 14741 if (stackTraceParameter != null) { |
| 14742 expect(stackTraceParameter.staticType, same(stackTraceType)); |
| 14743 } |
| 14744 } |
| 14745 |
| 14746 /** |
| 14747 * Return the type associated with the given parameter after the static type a
nalyzer has computed |
| 14748 * a type for it. |
| 14749 * |
| 14750 * @param node the parameter with which the type is associated |
| 14751 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 14752 * being resolved |
| 14753 * @return the type associated with the parameter |
| 14754 */ |
| 14755 DartType _resolveFormalParameter(FormalParameter node, |
| 14756 [List<Element> definedElements]) { |
| 14757 _resolveNode(node, definedElements); |
| 14758 return (node.identifier.staticElement as ParameterElement).type; |
| 14759 } |
| 14760 |
| 14761 /** |
| 14762 * Return the element associated with the given identifier after the resolver
has resolved the |
| 14763 * identifier. |
| 14764 * |
| 14765 * @param node the expression to be resolved |
| 14766 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 14767 * being resolved |
| 14768 * @return the element to which the expression was resolved |
| 14769 */ |
| 14770 void _resolveNode(AstNode node, [List<Element> definedElements]) { |
| 14771 if (definedElements != null) { |
| 14772 for (Element element in definedElements) { |
| 14773 _library.libraryScope.define(element); |
| 14774 } |
| 14775 } |
| 14776 node.accept(_visitor); |
| 14777 } |
| 14778 } |
| 14779 |
| 14780 class _AnalysisContextFactory_initContextWithCore |
| 14781 extends DirectoryBasedDartSdk { |
| 14782 _AnalysisContextFactory_initContextWithCore(JavaFile arg0) : super(arg0); |
| 14783 |
| 14784 @override |
| 14785 LibraryMap initialLibraryMap(bool useDart2jsPaths) { |
| 14786 LibraryMap map = new LibraryMap(); |
| 14787 _addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart"); |
| 14788 _addLibrary(map, DartSdk.DART_CORE, false, "core.dart"); |
| 14789 _addLibrary(map, DartSdk.DART_HTML, false, "html_dartium.dart"); |
| 14790 _addLibrary(map, AnalysisContextFactory._DART_MATH, false, "math.dart"); |
| 14791 _addLibrary(map, AnalysisContextFactory._DART_INTERCEPTORS, true, |
| 14792 "_interceptors.dart"); |
| 14793 _addLibrary( |
| 14794 map, AnalysisContextFactory._DART_JS_HELPER, true, "_js_helper.dart"); |
| 14795 return map; |
| 14796 } |
| 14797 |
| 14798 void _addLibrary(LibraryMap map, String uri, bool isInternal, String path) { |
| 14799 SdkLibraryImpl library = new SdkLibraryImpl(uri); |
| 14800 if (isInternal) { |
| 14801 library.category = "Internal"; |
| 14802 } |
| 14803 library.path = path; |
| 14804 map.setLibrary(uri, library); |
| 14805 } |
| 14806 } |
| 14807 |
| 14808 class _SimpleResolverTest_localVariable_types_invoked |
| 14809 extends RecursiveAstVisitor<Object> { |
| 14810 final SimpleResolverTest test; |
| 14811 |
| 14812 List<bool> found; |
| 14813 |
| 14814 List<CaughtException> thrownException; |
| 14815 |
| 14816 _SimpleResolverTest_localVariable_types_invoked( |
| 14817 this.test, this.found, this.thrownException) |
| 14818 : super(); |
| 14819 |
| 14820 @override |
| 14821 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 14822 if (node.name == "myVar" && node.parent is MethodInvocation) { |
| 14823 try { |
| 14824 found[0] = true; |
| 14825 // check static type |
| 14826 DartType staticType = node.staticType; |
| 14827 expect(staticType, same(test.typeProvider.dynamicType)); |
| 14828 // check propagated type |
| 14829 FunctionType propagatedType = node.propagatedType as FunctionType; |
| 14830 expect(propagatedType.returnType, test.typeProvider.stringType); |
| 14831 } on AnalysisException catch (e, stackTrace) { |
| 14832 thrownException[0] = new CaughtException(e, stackTrace); |
| 14833 } |
| 14834 } |
| 14835 return null; |
| 14836 } |
| 14837 } |
| 14838 |
| 14839 /** |
| 14840 * Shared infrastructure for [StaticTypeAnalyzer2Test] and |
| 14841 * [StrongModeStaticTypeAnalyzer2Test]. |
| 14842 */ |
| 14843 class _StaticTypeAnalyzer2TestShared extends ResolverTestCase { |
| 14844 String testCode; |
| 14845 Source testSource; |
| 14846 CompilationUnit testUnit; |
| 14847 |
| 14848 SimpleIdentifier _findIdentifier(String search) { |
| 14849 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 14850 testUnit, testCode, search, (node) => node is SimpleIdentifier); |
| 14851 return identifier; |
| 14852 } |
| 14853 |
| 14854 void _resolveTestUnit(String code) { |
| 14855 testCode = code; |
| 14856 testSource = addSource(testCode); |
| 14857 LibraryElement library = resolve2(testSource); |
| 14858 assertNoErrors(testSource); |
| 14859 verify([testSource]); |
| 14860 testUnit = resolveCompilationUnit(testSource, library); |
| 14861 } |
| 14862 } |
OLD | NEW |