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(StrongModeTypePropagationTest); |
| 72 } |
| 73 |
| 74 /** |
| 75 * The class `AnalysisContextFactory` defines utility methods used to create ana
lysis contexts |
| 76 * for testing purposes. |
| 77 */ |
| 78 class AnalysisContextFactory { |
| 79 static String _DART_MATH = "dart:math"; |
| 80 |
| 81 static String _DART_INTERCEPTORS = "dart:_interceptors"; |
| 82 |
| 83 static String _DART_JS_HELPER = "dart:_js_helper"; |
| 84 |
| 85 /** |
| 86 * Create an analysis context that has a fake core library already resolved. |
| 87 * Return the context that was created. |
| 88 */ |
| 89 static InternalAnalysisContext contextWithCore() { |
| 90 if (AnalysisEngine.instance.useTaskModel) { |
| 91 NewAnalysisContextForTests context = new NewAnalysisContextForTests(); |
| 92 return initContextWithCore(context); |
| 93 } |
| 94 AnalysisContextForTests context = new AnalysisContextForTests(); |
| 95 return initContextWithCore(context); |
| 96 } |
| 97 |
| 98 /** |
| 99 * Create an analysis context that uses the given [options] and has a fake |
| 100 * core library already resolved. Return the context that was created. |
| 101 */ |
| 102 static InternalAnalysisContext contextWithCoreAndOptions( |
| 103 AnalysisOptions options) { |
| 104 if (AnalysisEngine.instance.useTaskModel) { |
| 105 NewAnalysisContextForTests context = new NewAnalysisContextForTests(); |
| 106 context._internalSetAnalysisOptions(options); |
| 107 return initContextWithCore(context); |
| 108 } |
| 109 AnalysisContextForTests context = new AnalysisContextForTests(); |
| 110 context._internalSetAnalysisOptions(options); |
| 111 return initContextWithCore(context); |
| 112 } |
| 113 |
| 114 /** |
| 115 * Initialize the given analysis context with a fake core library already reso
lved. |
| 116 * |
| 117 * @param context the context to be initialized (not `null`) |
| 118 * @return the analysis context that was created |
| 119 */ |
| 120 static InternalAnalysisContext initContextWithCore( |
| 121 InternalAnalysisContext context) { |
| 122 DirectoryBasedDartSdk sdk = new _AnalysisContextFactory_initContextWithCore( |
| 123 new JavaFile("/fake/sdk")); |
| 124 SourceFactory sourceFactory = |
| 125 new SourceFactory([new DartUriResolver(sdk), new FileUriResolver()]); |
| 126 context.sourceFactory = sourceFactory; |
| 127 AnalysisContext coreContext = sdk.context; |
| 128 // |
| 129 // dart:core |
| 130 // |
| 131 TestTypeProvider provider = new TestTypeProvider(); |
| 132 CompilationUnitElementImpl coreUnit = |
| 133 new CompilationUnitElementImpl("core.dart"); |
| 134 Source coreSource = sourceFactory.forUri(DartSdk.DART_CORE); |
| 135 coreContext.setContents(coreSource, ""); |
| 136 coreUnit.librarySource = coreUnit.source = coreSource; |
| 137 ClassElementImpl proxyClassElement = ElementFactory.classElement2("_Proxy"); |
| 138 ClassElement objectClassElement = provider.objectType.element; |
| 139 coreUnit.types = <ClassElement>[ |
| 140 provider.boolType.element, |
| 141 provider.deprecatedType.element, |
| 142 provider.doubleType.element, |
| 143 provider.functionType.element, |
| 144 provider.intType.element, |
| 145 provider.iterableType.element, |
| 146 provider.iteratorType.element, |
| 147 provider.listType.element, |
| 148 provider.mapType.element, |
| 149 provider.nullType.element, |
| 150 provider.numType.element, |
| 151 objectClassElement, |
| 152 proxyClassElement, |
| 153 provider.stackTraceType.element, |
| 154 provider.stringType.element, |
| 155 provider.symbolType.element, |
| 156 provider.typeType.element |
| 157 ]; |
| 158 coreUnit.functions = <FunctionElement>[ |
| 159 ElementFactory.functionElement3("identical", provider.boolType.element, |
| 160 <ClassElement>[objectClassElement, objectClassElement], null), |
| 161 ElementFactory.functionElement3("print", VoidTypeImpl.instance.element, |
| 162 <ClassElement>[objectClassElement], null) |
| 163 ]; |
| 164 TopLevelVariableElement proxyTopLevelVariableElt = ElementFactory |
| 165 .topLevelVariableElement3("proxy", true, false, proxyClassElement.type); |
| 166 ConstTopLevelVariableElementImpl deprecatedTopLevelVariableElt = |
| 167 ElementFactory.topLevelVariableElement3( |
| 168 "deprecated", true, false, provider.deprecatedType); |
| 169 deprecatedTopLevelVariableElt.constantInitializer = AstFactory |
| 170 .instanceCreationExpression2( |
| 171 Keyword.CONST, |
| 172 AstFactory.typeName(provider.deprecatedType.element), |
| 173 [AstFactory.string2('next release')]); |
| 174 coreUnit.accessors = <PropertyAccessorElement>[ |
| 175 proxyTopLevelVariableElt.getter, |
| 176 deprecatedTopLevelVariableElt.getter |
| 177 ]; |
| 178 coreUnit.topLevelVariables = <TopLevelVariableElement>[ |
| 179 proxyTopLevelVariableElt, |
| 180 deprecatedTopLevelVariableElt |
| 181 ]; |
| 182 LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode( |
| 183 coreContext, AstFactory.libraryIdentifier2(["dart", "core"])); |
| 184 coreLibrary.definingCompilationUnit = coreUnit; |
| 185 // |
| 186 // dart:async |
| 187 // |
| 188 CompilationUnitElementImpl asyncUnit = |
| 189 new CompilationUnitElementImpl("async.dart"); |
| 190 Source asyncSource = sourceFactory.forUri(DartSdk.DART_ASYNC); |
| 191 coreContext.setContents(asyncSource, ""); |
| 192 asyncUnit.librarySource = asyncUnit.source = asyncSource; |
| 193 // Future |
| 194 ClassElementImpl futureElement = |
| 195 ElementFactory.classElement2("Future", ["T"]); |
| 196 InterfaceType futureType = futureElement.type; |
| 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 MethodElement thenMethod = ElementFactory.methodElementWithParameters( |
| 222 "then", futureElement.type.typeArguments, futureType, [ |
| 223 ElementFactory.requiredParameter2("onValue", aliasType), |
| 224 ElementFactory.namedParameter2("onError", provider.functionType) |
| 225 ]); |
| 226 futureElement.methods = <MethodElement>[thenMethod]; |
| 227 // Completer |
| 228 ClassElementImpl completerElement = |
| 229 ElementFactory.classElement2("Completer", ["T"]); |
| 230 ConstructorElementImpl completerConstructor = |
| 231 ElementFactory.constructorElement2(completerElement, null); |
| 232 (completerConstructor.type as FunctionTypeImpl).typeArguments = |
| 233 completerElement.type.typeArguments; |
| 234 completerElement.constructors = <ConstructorElement>[completerConstructor]; |
| 235 // StreamSubscription |
| 236 ClassElementImpl streamSubscriptionElement = |
| 237 ElementFactory.classElement2("StreamSubscription", ["T"]); |
| 238 // Stream |
| 239 ClassElementImpl streamElement = |
| 240 ElementFactory.classElement2("Stream", ["T"]); |
| 241 streamElement.constructors = <ConstructorElement>[ |
| 242 ElementFactory.constructorElement2(streamElement, null) |
| 243 ]; |
| 244 DartType returnType = streamSubscriptionElement.type |
| 245 .substitute4(streamElement.type.typeArguments); |
| 246 List<DartType> parameterTypes = <DartType>[ |
| 247 ElementFactory |
| 248 .functionElement3('onData', VoidTypeImpl.instance.element, |
| 249 <TypeDefiningElement>[streamElement.typeParameters[0]], null) |
| 250 .type, |
| 251 ]; |
| 252 // TODO(brianwilkerson) This is missing the optional parameters. |
| 253 MethodElementImpl listenMethod = |
| 254 ElementFactory.methodElement('listen', returnType, parameterTypes); |
| 255 streamElement.methods = <MethodElement>[listenMethod]; |
| 256 |
| 257 asyncUnit.types = <ClassElement>[ |
| 258 completerElement, |
| 259 futureElement, |
| 260 streamElement |
| 261 ]; |
| 262 LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode( |
| 263 coreContext, AstFactory.libraryIdentifier2(["dart", "async"])); |
| 264 asyncLibrary.definingCompilationUnit = asyncUnit; |
| 265 // |
| 266 // dart:html |
| 267 // |
| 268 CompilationUnitElementImpl htmlUnit = |
| 269 new CompilationUnitElementImpl("html_dartium.dart"); |
| 270 Source htmlSource = sourceFactory.forUri(DartSdk.DART_HTML); |
| 271 coreContext.setContents(htmlSource, ""); |
| 272 htmlUnit.librarySource = htmlUnit.source = htmlSource; |
| 273 ClassElementImpl elementElement = ElementFactory.classElement2("Element"); |
| 274 InterfaceType elementType = elementElement.type; |
| 275 ClassElementImpl canvasElement = |
| 276 ElementFactory.classElement("CanvasElement", elementType); |
| 277 ClassElementImpl contextElement = |
| 278 ElementFactory.classElement2("CanvasRenderingContext"); |
| 279 InterfaceType contextElementType = contextElement.type; |
| 280 ClassElementImpl context2dElement = ElementFactory.classElement( |
| 281 "CanvasRenderingContext2D", contextElementType); |
| 282 canvasElement.methods = <MethodElement>[ |
| 283 ElementFactory.methodElement( |
| 284 "getContext", contextElementType, [provider.stringType]) |
| 285 ]; |
| 286 canvasElement.accessors = <PropertyAccessorElement>[ |
| 287 ElementFactory.getterElement("context2D", false, context2dElement.type) |
| 288 ]; |
| 289 canvasElement.fields = canvasElement.accessors |
| 290 .map((PropertyAccessorElement accessor) => accessor.variable) |
| 291 .toList(); |
| 292 ClassElementImpl documentElement = |
| 293 ElementFactory.classElement("Document", elementType); |
| 294 ClassElementImpl htmlDocumentElement = |
| 295 ElementFactory.classElement("HtmlDocument", documentElement.type); |
| 296 htmlDocumentElement.methods = <MethodElement>[ |
| 297 ElementFactory.methodElement( |
| 298 "query", elementType, <DartType>[provider.stringType]) |
| 299 ]; |
| 300 htmlUnit.types = <ClassElement>[ |
| 301 ElementFactory.classElement("AnchorElement", elementType), |
| 302 ElementFactory.classElement("BodyElement", elementType), |
| 303 ElementFactory.classElement("ButtonElement", elementType), |
| 304 canvasElement, |
| 305 contextElement, |
| 306 context2dElement, |
| 307 ElementFactory.classElement("DivElement", elementType), |
| 308 documentElement, |
| 309 elementElement, |
| 310 htmlDocumentElement, |
| 311 ElementFactory.classElement("InputElement", elementType), |
| 312 ElementFactory.classElement("SelectElement", elementType) |
| 313 ]; |
| 314 htmlUnit.functions = <FunctionElement>[ |
| 315 ElementFactory.functionElement3("query", elementElement, |
| 316 <ClassElement>[provider.stringType.element], ClassElement.EMPTY_LIST) |
| 317 ]; |
| 318 TopLevelVariableElementImpl document = ElementFactory |
| 319 .topLevelVariableElement3( |
| 320 "document", false, true, htmlDocumentElement.type); |
| 321 htmlUnit.topLevelVariables = <TopLevelVariableElement>[document]; |
| 322 htmlUnit.accessors = <PropertyAccessorElement>[document.getter]; |
| 323 LibraryElementImpl htmlLibrary = new LibraryElementImpl.forNode( |
| 324 coreContext, AstFactory.libraryIdentifier2(["dart", "dom", "html"])); |
| 325 htmlLibrary.definingCompilationUnit = htmlUnit; |
| 326 // |
| 327 // dart:math |
| 328 // |
| 329 CompilationUnitElementImpl mathUnit = |
| 330 new CompilationUnitElementImpl("math.dart"); |
| 331 Source mathSource = sourceFactory.forUri(_DART_MATH); |
| 332 coreContext.setContents(mathSource, ""); |
| 333 mathUnit.librarySource = mathUnit.source = mathSource; |
| 334 FunctionElement cosElement = ElementFactory.functionElement3( |
| 335 "cos", |
| 336 provider.doubleType.element, |
| 337 <ClassElement>[provider.numType.element], |
| 338 ClassElement.EMPTY_LIST); |
| 339 TopLevelVariableElement ln10Element = ElementFactory |
| 340 .topLevelVariableElement3("LN10", true, false, provider.doubleType); |
| 341 TopLevelVariableElement piElement = ElementFactory.topLevelVariableElement3( |
| 342 "PI", true, false, provider.doubleType); |
| 343 ClassElementImpl randomElement = ElementFactory.classElement2("Random"); |
| 344 randomElement.abstract = true; |
| 345 ConstructorElementImpl randomConstructor = |
| 346 ElementFactory.constructorElement2(randomElement, null); |
| 347 randomConstructor.factory = true; |
| 348 ParameterElementImpl seedParam = new ParameterElementImpl("seed", 0); |
| 349 seedParam.parameterKind = ParameterKind.POSITIONAL; |
| 350 seedParam.type = provider.intType; |
| 351 randomConstructor.parameters = <ParameterElement>[seedParam]; |
| 352 randomElement.constructors = <ConstructorElement>[randomConstructor]; |
| 353 FunctionElement sinElement = ElementFactory.functionElement3( |
| 354 "sin", |
| 355 provider.doubleType.element, |
| 356 <ClassElement>[provider.numType.element], |
| 357 ClassElement.EMPTY_LIST); |
| 358 FunctionElement sqrtElement = ElementFactory.functionElement3( |
| 359 "sqrt", |
| 360 provider.doubleType.element, |
| 361 <ClassElement>[provider.numType.element], |
| 362 ClassElement.EMPTY_LIST); |
| 363 mathUnit.accessors = <PropertyAccessorElement>[ |
| 364 ln10Element.getter, |
| 365 piElement.getter |
| 366 ]; |
| 367 mathUnit.functions = <FunctionElement>[cosElement, sinElement, sqrtElement]; |
| 368 mathUnit.topLevelVariables = <TopLevelVariableElement>[ |
| 369 ln10Element, |
| 370 piElement |
| 371 ]; |
| 372 mathUnit.types = <ClassElement>[randomElement]; |
| 373 LibraryElementImpl mathLibrary = new LibraryElementImpl.forNode( |
| 374 coreContext, AstFactory.libraryIdentifier2(["dart", "math"])); |
| 375 mathLibrary.definingCompilationUnit = mathUnit; |
| 376 // |
| 377 // Set empty sources for the rest of the libraries. |
| 378 // |
| 379 Source source = sourceFactory.forUri(_DART_INTERCEPTORS); |
| 380 coreContext.setContents(source, ""); |
| 381 source = sourceFactory.forUri(_DART_JS_HELPER); |
| 382 coreContext.setContents(source, ""); |
| 383 // |
| 384 // Record the elements. |
| 385 // |
| 386 HashMap<Source, LibraryElement> elementMap = |
| 387 new HashMap<Source, LibraryElement>(); |
| 388 elementMap[coreSource] = coreLibrary; |
| 389 elementMap[asyncSource] = asyncLibrary; |
| 390 elementMap[htmlSource] = htmlLibrary; |
| 391 elementMap[mathSource] = mathLibrary; |
| 392 context.recordLibraryElements(elementMap); |
| 393 return context; |
| 394 } |
| 395 |
| 396 /** |
| 397 * Create an analysis context that has a fake core library already resolved. |
| 398 * Return the context that was created. |
| 399 */ |
| 400 static AnalysisContextImpl oldContextWithCore() { |
| 401 AnalysisContextForTests context = new AnalysisContextForTests(); |
| 402 return initContextWithCore(context); |
| 403 } |
| 404 |
| 405 /** |
| 406 * Create an analysis context that uses the given [options] and has a fake |
| 407 * core library already resolved. Return the context that was created. |
| 408 */ |
| 409 static AnalysisContextImpl oldContextWithCoreAndOptions( |
| 410 AnalysisOptions options) { |
| 411 AnalysisContextForTests context = new AnalysisContextForTests(); |
| 412 context._internalSetAnalysisOptions(options); |
| 413 return initContextWithCore(context); |
| 414 } |
| 415 } |
| 416 |
| 417 /** |
| 418 * Instances of the class `AnalysisContextForTests` implement an analysis contex
t that has a |
| 419 * fake SDK that is much smaller and faster for testing purposes. |
| 420 */ |
| 421 class AnalysisContextForTests extends AnalysisContextImpl { |
| 422 @override |
| 423 void set analysisOptions(AnalysisOptions options) { |
| 424 AnalysisOptions currentOptions = analysisOptions; |
| 425 bool needsRecompute = currentOptions.analyzeFunctionBodiesPredicate != |
| 426 options.analyzeFunctionBodiesPredicate || |
| 427 currentOptions.generateImplicitErrors != |
| 428 options.generateImplicitErrors || |
| 429 currentOptions.generateSdkErrors != options.generateSdkErrors || |
| 430 currentOptions.dart2jsHint != options.dart2jsHint || |
| 431 (currentOptions.hint && !options.hint) || |
| 432 currentOptions.preserveComments != options.preserveComments || |
| 433 currentOptions.enableStrictCallChecks != options.enableStrictCallChecks; |
| 434 if (needsRecompute) { |
| 435 fail( |
| 436 "Cannot set options that cause the sources to be reanalyzed in a test
context"); |
| 437 } |
| 438 super.analysisOptions = options; |
| 439 } |
| 440 |
| 441 @override |
| 442 bool exists(Source source) => |
| 443 super.exists(source) || sourceFactory.dartSdk.context.exists(source); |
| 444 |
| 445 @override |
| 446 TimestampedData<String> getContents(Source source) { |
| 447 if (source.isInSystemLibrary) { |
| 448 return sourceFactory.dartSdk.context.getContents(source); |
| 449 } |
| 450 return super.getContents(source); |
| 451 } |
| 452 |
| 453 @override |
| 454 int getModificationStamp(Source source) { |
| 455 if (source.isInSystemLibrary) { |
| 456 return sourceFactory.dartSdk.context.getModificationStamp(source); |
| 457 } |
| 458 return super.getModificationStamp(source); |
| 459 } |
| 460 |
| 461 /** |
| 462 * Set the analysis options, even if they would force re-analysis. This method
should only be |
| 463 * invoked before the fake SDK is initialized. |
| 464 * |
| 465 * @param options the analysis options to be set |
| 466 */ |
| 467 void _internalSetAnalysisOptions(AnalysisOptions options) { |
| 468 super.analysisOptions = options; |
| 469 } |
| 470 } |
| 471 |
| 472 /** |
| 473 * Helper for creating and managing single [AnalysisContext]. |
| 474 */ |
| 475 class AnalysisContextHelper { |
| 476 AnalysisContext context; |
| 477 |
| 478 /** |
| 479 * Creates new [AnalysisContext] using [AnalysisContextFactory]. |
| 480 */ |
| 481 AnalysisContextHelper([AnalysisOptionsImpl options]) { |
| 482 if (options == null) { |
| 483 options = new AnalysisOptionsImpl(); |
| 484 } |
| 485 options.cacheSize = 256; |
| 486 context = AnalysisContextFactory.contextWithCoreAndOptions(options); |
| 487 } |
| 488 |
| 489 Source addSource(String path, String code) { |
| 490 Source source = new FileBasedSource(FileUtilities2.createFile(path)); |
| 491 if (path.endsWith(".dart") || path.endsWith(".html")) { |
| 492 ChangeSet changeSet = new ChangeSet(); |
| 493 changeSet.addedSource(source); |
| 494 context.applyChanges(changeSet); |
| 495 } |
| 496 context.setContents(source, code); |
| 497 return source; |
| 498 } |
| 499 |
| 500 CompilationUnitElement getDefiningUnitElement(Source source) => |
| 501 context.getCompilationUnitElement(source, source); |
| 502 |
| 503 CompilationUnit resolveDefiningUnit(Source source) { |
| 504 LibraryElement libraryElement = context.computeLibraryElement(source); |
| 505 return context.resolveCompilationUnit(source, libraryElement); |
| 506 } |
| 507 |
| 508 void runTasks() { |
| 509 AnalysisResult result = context.performAnalysisTask(); |
| 510 while (result.changeNotices != null) { |
| 511 result = context.performAnalysisTask(); |
| 512 } |
| 513 } |
| 514 } |
| 515 |
| 516 @reflectiveTest |
| 517 class AnalysisDeltaTest extends EngineTestCase { |
| 518 TestSource source1 = new TestSource('/1.dart'); |
| 519 TestSource source2 = new TestSource('/2.dart'); |
| 520 TestSource source3 = new TestSource('/3.dart'); |
| 521 |
| 522 void test_getAddedSources() { |
| 523 AnalysisDelta delta = new AnalysisDelta(); |
| 524 delta.setAnalysisLevel(source1, AnalysisLevel.ALL); |
| 525 delta.setAnalysisLevel(source2, AnalysisLevel.ERRORS); |
| 526 delta.setAnalysisLevel(source3, AnalysisLevel.NONE); |
| 527 List<Source> addedSources = delta.addedSources; |
| 528 expect(addedSources, hasLength(2)); |
| 529 expect(addedSources, unorderedEquals([source1, source2])); |
| 530 } |
| 531 |
| 532 void test_getAnalysisLevels() { |
| 533 AnalysisDelta delta = new AnalysisDelta(); |
| 534 expect(delta.analysisLevels.length, 0); |
| 535 } |
| 536 |
| 537 void test_setAnalysisLevel() { |
| 538 AnalysisDelta delta = new AnalysisDelta(); |
| 539 delta.setAnalysisLevel(source1, AnalysisLevel.ALL); |
| 540 delta.setAnalysisLevel(source2, AnalysisLevel.ERRORS); |
| 541 Map<Source, AnalysisLevel> levels = delta.analysisLevels; |
| 542 expect(levels.length, 2); |
| 543 expect(levels[source1], AnalysisLevel.ALL); |
| 544 expect(levels[source2], AnalysisLevel.ERRORS); |
| 545 } |
| 546 |
| 547 void test_toString() { |
| 548 AnalysisDelta delta = new AnalysisDelta(); |
| 549 delta.setAnalysisLevel(new TestSource(), AnalysisLevel.ALL); |
| 550 String result = delta.toString(); |
| 551 expect(result, isNotNull); |
| 552 expect(result.length > 0, isTrue); |
| 553 } |
| 554 } |
| 555 |
| 556 @reflectiveTest |
| 557 class ChangeSetTest extends EngineTestCase { |
| 558 void test_changedContent() { |
| 559 TestSource source = new TestSource(); |
| 560 String content = ""; |
| 561 ChangeSet changeSet = new ChangeSet(); |
| 562 changeSet.changedContent(source, content); |
| 563 expect(changeSet.addedSources, hasLength(0)); |
| 564 expect(changeSet.changedSources, hasLength(0)); |
| 565 Map<Source, String> map = changeSet.changedContents; |
| 566 expect(map, hasLength(1)); |
| 567 expect(map[source], same(content)); |
| 568 expect(changeSet.changedRanges, hasLength(0)); |
| 569 expect(changeSet.deletedSources, hasLength(0)); |
| 570 expect(changeSet.removedSources, hasLength(0)); |
| 571 expect(changeSet.removedContainers, hasLength(0)); |
| 572 } |
| 573 |
| 574 void test_changedRange() { |
| 575 TestSource source = new TestSource(); |
| 576 String content = ""; |
| 577 ChangeSet changeSet = new ChangeSet(); |
| 578 changeSet.changedRange(source, content, 1, 2, 3); |
| 579 expect(changeSet.addedSources, hasLength(0)); |
| 580 expect(changeSet.changedSources, hasLength(0)); |
| 581 expect(changeSet.changedContents, hasLength(0)); |
| 582 Map<Source, ChangeSet_ContentChange> map = changeSet.changedRanges; |
| 583 expect(map, hasLength(1)); |
| 584 ChangeSet_ContentChange change = map[source]; |
| 585 expect(change, isNotNull); |
| 586 expect(change.contents, content); |
| 587 expect(change.offset, 1); |
| 588 expect(change.oldLength, 2); |
| 589 expect(change.newLength, 3); |
| 590 expect(changeSet.deletedSources, hasLength(0)); |
| 591 expect(changeSet.removedSources, hasLength(0)); |
| 592 expect(changeSet.removedContainers, hasLength(0)); |
| 593 } |
| 594 |
| 595 void test_toString() { |
| 596 ChangeSet changeSet = new ChangeSet(); |
| 597 changeSet.addedSource(new TestSource()); |
| 598 changeSet.changedSource(new TestSource()); |
| 599 changeSet.changedContent(new TestSource(), ""); |
| 600 changeSet.changedRange(new TestSource(), "", 0, 0, 0); |
| 601 changeSet.deletedSource(new TestSource()); |
| 602 changeSet.removedSource(new TestSource()); |
| 603 changeSet |
| 604 .removedContainer(new SourceContainer_ChangeSetTest_test_toString()); |
| 605 expect(changeSet.toString(), isNotNull); |
| 606 } |
| 607 } |
| 608 |
| 609 @reflectiveTest |
| 610 class CheckedModeCompileTimeErrorCodeTest extends ResolverTestCase { |
| 611 void test_fieldFormalParameterAssignableToField_extends() { |
| 612 // According to checked-mode type checking rules, a value of type B is |
| 613 // assignable to a field of type A, because B extends A (and hence is a |
| 614 // subtype of A). |
| 615 Source source = addSource(r''' |
| 616 class A { |
| 617 const A(); |
| 618 } |
| 619 class B extends A { |
| 620 const B(); |
| 621 } |
| 622 class C { |
| 623 final A a; |
| 624 const C(this.a); |
| 625 } |
| 626 var v = const C(const B());'''); |
| 627 computeLibrarySourceErrors(source); |
| 628 assertNoErrors(source); |
| 629 verify([source]); |
| 630 } |
| 631 |
| 632 void test_fieldFormalParameterAssignableToField_fieldType_unresolved_null() { |
| 633 // Null always passes runtime type checks, even when the type is |
| 634 // unresolved. |
| 635 Source source = addSource(r''' |
| 636 class A { |
| 637 final Unresolved x; |
| 638 const A(String this.x); |
| 639 } |
| 640 var v = const A(null);'''); |
| 641 computeLibrarySourceErrors(source); |
| 642 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); |
| 643 verify([source]); |
| 644 } |
| 645 |
| 646 void test_fieldFormalParameterAssignableToField_implements() { |
| 647 // According to checked-mode type checking rules, a value of type B is |
| 648 // assignable to a field of type A, because B implements A (and hence is a |
| 649 // subtype of A). |
| 650 Source source = addSource(r''' |
| 651 class A {} |
| 652 class B implements A { |
| 653 const B(); |
| 654 } |
| 655 class C { |
| 656 final A a; |
| 657 const C(this.a); |
| 658 } |
| 659 var v = const C(const B());'''); |
| 660 computeLibrarySourceErrors(source); |
| 661 assertNoErrors(source); |
| 662 verify([source]); |
| 663 } |
| 664 |
| 665 void test_fieldFormalParameterAssignableToField_list_dynamic() { |
| 666 // [1, 2, 3] has type List<dynamic>, which is a subtype of List<int>. |
| 667 Source source = addSource(r''' |
| 668 class A { |
| 669 const A(List<int> x); |
| 670 } |
| 671 var x = const A(const [1, 2, 3]);'''); |
| 672 computeLibrarySourceErrors(source); |
| 673 assertNoErrors(source); |
| 674 verify([source]); |
| 675 } |
| 676 |
| 677 void test_fieldFormalParameterAssignableToField_list_nonDynamic() { |
| 678 // <int>[1, 2, 3] has type List<int>, which is a subtype of List<num>. |
| 679 Source source = addSource(r''' |
| 680 class A { |
| 681 const A(List<num> x); |
| 682 } |
| 683 var x = const A(const <int>[1, 2, 3]);'''); |
| 684 computeLibrarySourceErrors(source); |
| 685 assertNoErrors(source); |
| 686 verify([source]); |
| 687 } |
| 688 |
| 689 void test_fieldFormalParameterAssignableToField_map_dynamic() { |
| 690 // {1: 2} has type Map<dynamic, dynamic>, which is a subtype of |
| 691 // Map<int, int>. |
| 692 Source source = addSource(r''' |
| 693 class A { |
| 694 const A(Map<int, int> x); |
| 695 } |
| 696 var x = const A(const {1: 2});'''); |
| 697 computeLibrarySourceErrors(source); |
| 698 assertNoErrors(source); |
| 699 verify([source]); |
| 700 } |
| 701 |
| 702 void test_fieldFormalParameterAssignableToField_map_keyDifferent() { |
| 703 // <int, int>{1: 2} has type Map<int, int>, which is a subtype of |
| 704 // Map<num, int>. |
| 705 Source source = addSource(r''' |
| 706 class A { |
| 707 const A(Map<num, int> x); |
| 708 } |
| 709 var x = const A(const <int, int>{1: 2});'''); |
| 710 computeLibrarySourceErrors(source); |
| 711 assertNoErrors(source); |
| 712 verify([source]); |
| 713 } |
| 714 |
| 715 void test_fieldFormalParameterAssignableToField_map_valueDifferent() { |
| 716 // <int, int>{1: 2} has type Map<int, int>, which is a subtype of |
| 717 // Map<int, num>. |
| 718 Source source = addSource(r''' |
| 719 class A { |
| 720 const A(Map<int, num> x); |
| 721 } |
| 722 var x = const A(const <int, int>{1: 2});'''); |
| 723 computeLibrarySourceErrors(source); |
| 724 assertNoErrors(source); |
| 725 verify([source]); |
| 726 } |
| 727 |
| 728 void test_fieldFormalParameterAssignableToField_notype() { |
| 729 // If a field is declared without a type, then any value may be assigned to |
| 730 // it. |
| 731 Source source = addSource(r''' |
| 732 class A { |
| 733 final x; |
| 734 const A(this.x); |
| 735 } |
| 736 var v = const A(5);'''); |
| 737 computeLibrarySourceErrors(source); |
| 738 assertNoErrors(source); |
| 739 verify([source]); |
| 740 } |
| 741 |
| 742 void test_fieldFormalParameterAssignableToField_null() { |
| 743 // Null is assignable to anything. |
| 744 Source source = addSource(r''' |
| 745 class A { |
| 746 final int x; |
| 747 const A(this.x); |
| 748 } |
| 749 var v = const A(null);'''); |
| 750 computeLibrarySourceErrors(source); |
| 751 assertNoErrors(source); |
| 752 verify([source]); |
| 753 } |
| 754 |
| 755 void test_fieldFormalParameterAssignableToField_typedef() { |
| 756 // foo has the runtime type dynamic -> dynamic, so it should be assignable |
| 757 // to A.f. |
| 758 Source source = addSource(r''' |
| 759 typedef String Int2String(int x); |
| 760 class A { |
| 761 final Int2String f; |
| 762 const A(this.f); |
| 763 } |
| 764 foo(x) => 1; |
| 765 var v = const A(foo);'''); |
| 766 computeLibrarySourceErrors(source); |
| 767 assertNoErrors(source); |
| 768 verify([source]); |
| 769 } |
| 770 |
| 771 void test_fieldFormalParameterAssignableToField_typeSubstitution() { |
| 772 // foo has the runtime type dynamic -> dynamic, so it should be assignable |
| 773 // to A.f. |
| 774 Source source = addSource(r''' |
| 775 class A<T> { |
| 776 final T x; |
| 777 const A(this.x); |
| 778 } |
| 779 var v = const A<int>(3);'''); |
| 780 computeLibrarySourceErrors(source); |
| 781 assertNoErrors(source); |
| 782 verify([source]); |
| 783 } |
| 784 |
| 785 void test_fieldFormalParameterNotAssignableToField() { |
| 786 Source source = addSource(r''' |
| 787 class A { |
| 788 final int x; |
| 789 const A(this.x); |
| 790 } |
| 791 var v = const A('foo');'''); |
| 792 computeLibrarySourceErrors(source); |
| 793 assertErrors(source, [ |
| 794 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 795 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE |
| 796 ]); |
| 797 verify([source]); |
| 798 } |
| 799 |
| 800 void test_fieldFormalParameterNotAssignableToField_extends() { |
| 801 // According to checked-mode type checking rules, a value of type A is not |
| 802 // assignable to a field of type B, because B extends A (the subtyping |
| 803 // relationship is in the wrong direction). |
| 804 Source source = addSource(r''' |
| 805 class A { |
| 806 const A(); |
| 807 } |
| 808 class B extends A { |
| 809 const B(); |
| 810 } |
| 811 class C { |
| 812 final B b; |
| 813 const C(this.b); |
| 814 } |
| 815 var v = const C(const A());'''); |
| 816 computeLibrarySourceErrors(source); |
| 817 assertErrors(source, [ |
| 818 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 819 ]); |
| 820 verify([source]); |
| 821 } |
| 822 |
| 823 void test_fieldFormalParameterNotAssignableToField_fieldType() { |
| 824 Source source = addSource(r''' |
| 825 class A { |
| 826 final int x; |
| 827 const A(String this.x); |
| 828 } |
| 829 var v = const A('foo');'''); |
| 830 computeLibrarySourceErrors(source); |
| 831 assertErrors(source, [ |
| 832 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 833 StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE |
| 834 ]); |
| 835 verify([source]); |
| 836 } |
| 837 |
| 838 void test_fieldFormalParameterNotAssignableToField_fieldType_unresolved() { |
| 839 Source source = addSource(r''' |
| 840 class A { |
| 841 final Unresolved x; |
| 842 const A(String this.x); |
| 843 } |
| 844 var v = const A('foo');'''); |
| 845 computeLibrarySourceErrors(source); |
| 846 assertErrors(source, [ |
| 847 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 848 StaticWarningCode.UNDEFINED_CLASS |
| 849 ]); |
| 850 verify([source]); |
| 851 } |
| 852 |
| 853 void test_fieldFormalParameterNotAssignableToField_implements() { |
| 854 // According to checked-mode type checking rules, a value of type A is not |
| 855 // assignable to a field of type B, because B implements A (the subtyping |
| 856 // relationship is in the wrong direction). |
| 857 Source source = addSource(r''' |
| 858 class A { |
| 859 const A(); |
| 860 } |
| 861 class B implements A {} |
| 862 class C { |
| 863 final B b; |
| 864 const C(this.b); |
| 865 } |
| 866 var v = const C(const A());'''); |
| 867 computeLibrarySourceErrors(source); |
| 868 assertErrors(source, [ |
| 869 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 870 ]); |
| 871 verify([source]); |
| 872 } |
| 873 |
| 874 void test_fieldFormalParameterNotAssignableToField_list() { |
| 875 // <num>[1, 2, 3] has type List<num>, which is not a subtype of List<int>. |
| 876 Source source = addSource(r''' |
| 877 class A { |
| 878 const A(List<int> x); |
| 879 } |
| 880 var x = const A(const <num>[1, 2, 3]);'''); |
| 881 computeLibrarySourceErrors(source); |
| 882 assertErrors(source, [ |
| 883 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 884 ]); |
| 885 verify([source]); |
| 886 } |
| 887 |
| 888 void test_fieldFormalParameterNotAssignableToField_map_keyMismatch() { |
| 889 // <num, int>{1: 2} has type Map<num, int>, which is not a subtype of |
| 890 // Map<int, int>. |
| 891 Source source = addSource(r''' |
| 892 class A { |
| 893 const A(Map<int, int> x); |
| 894 } |
| 895 var x = const A(const <num, int>{1: 2});'''); |
| 896 computeLibrarySourceErrors(source); |
| 897 assertErrors(source, [ |
| 898 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 899 ]); |
| 900 verify([source]); |
| 901 } |
| 902 |
| 903 void test_fieldFormalParameterNotAssignableToField_map_valueMismatch() { |
| 904 // <int, num>{1: 2} has type Map<int, num>, which is not a subtype of |
| 905 // Map<int, int>. |
| 906 Source source = addSource(r''' |
| 907 class A { |
| 908 const A(Map<int, int> x); |
| 909 } |
| 910 var x = const A(const <int, num>{1: 2});'''); |
| 911 computeLibrarySourceErrors(source); |
| 912 assertErrors(source, [ |
| 913 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 914 ]); |
| 915 verify([source]); |
| 916 } |
| 917 |
| 918 void test_fieldFormalParameterNotAssignableToField_optional() { |
| 919 Source source = addSource(r''' |
| 920 class A { |
| 921 final int x; |
| 922 const A([this.x = 'foo']); |
| 923 } |
| 924 var v = const A();'''); |
| 925 computeLibrarySourceErrors(source); |
| 926 assertErrors(source, [ |
| 927 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 928 StaticTypeWarningCode.INVALID_ASSIGNMENT |
| 929 ]); |
| 930 verify([source]); |
| 931 } |
| 932 |
| 933 void test_fieldFormalParameterNotAssignableToField_typedef() { |
| 934 // foo has the runtime type String -> int, so it should not be assignable |
| 935 // to A.f (A.f requires it to be int -> String). |
| 936 Source source = addSource(r''' |
| 937 typedef String Int2String(int x); |
| 938 class A { |
| 939 final Int2String f; |
| 940 const A(this.f); |
| 941 } |
| 942 int foo(String x) => 1; |
| 943 var v = const A(foo);'''); |
| 944 computeLibrarySourceErrors(source); |
| 945 assertErrors(source, [ |
| 946 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 947 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE |
| 948 ]); |
| 949 verify([source]); |
| 950 } |
| 951 |
| 952 void test_fieldInitializerNotAssignable() { |
| 953 Source source = addSource(r''' |
| 954 class A { |
| 955 final int x; |
| 956 const A() : x = ''; |
| 957 }'''); |
| 958 computeLibrarySourceErrors(source); |
| 959 assertErrors(source, [ |
| 960 CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE, |
| 961 StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE |
| 962 ]); |
| 963 verify([source]); |
| 964 } |
| 965 |
| 966 void test_fieldTypeMismatch() { |
| 967 Source source = addSource(r''' |
| 968 class A { |
| 969 const A(x) : y = x; |
| 970 final int y; |
| 971 } |
| 972 var v = const A('foo');'''); |
| 973 computeLibrarySourceErrors(source); |
| 974 assertErrors(source, [ |
| 975 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH |
| 976 ]); |
| 977 verify([source]); |
| 978 } |
| 979 |
| 980 void test_fieldTypeMismatch_generic() { |
| 981 Source source = addSource(r''' |
| 982 class C<T> { |
| 983 final T x = y; |
| 984 const C(); |
| 985 } |
| 986 const y = 1; |
| 987 var v = const C<String>(); |
| 988 '''); |
| 989 computeLibrarySourceErrors(source); |
| 990 assertErrors(source, [ |
| 991 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, |
| 992 HintCode.INVALID_ASSIGNMENT |
| 993 ]); |
| 994 verify([source]); |
| 995 } |
| 996 |
| 997 void test_fieldTypeMismatch_unresolved() { |
| 998 Source source = addSource(r''' |
| 999 class A { |
| 1000 const A(x) : y = x; |
| 1001 final Unresolved y; |
| 1002 } |
| 1003 var v = const A('foo');'''); |
| 1004 computeLibrarySourceErrors(source); |
| 1005 assertErrors(source, [ |
| 1006 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, |
| 1007 StaticWarningCode.UNDEFINED_CLASS |
| 1008 ]); |
| 1009 verify([source]); |
| 1010 } |
| 1011 |
| 1012 void test_fieldTypeOk_generic() { |
| 1013 Source source = addSource(r''' |
| 1014 class C<T> { |
| 1015 final T x = y; |
| 1016 const C(); |
| 1017 } |
| 1018 const y = 1; |
| 1019 var v = const C<int>(); |
| 1020 '''); |
| 1021 computeLibrarySourceErrors(source); |
| 1022 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 1023 verify([source]); |
| 1024 } |
| 1025 |
| 1026 void test_fieldTypeOk_null() { |
| 1027 Source source = addSource(r''' |
| 1028 class A { |
| 1029 const A(x) : y = x; |
| 1030 final int y; |
| 1031 } |
| 1032 var v = const A(null);'''); |
| 1033 computeLibrarySourceErrors(source); |
| 1034 assertNoErrors(source); |
| 1035 verify([source]); |
| 1036 } |
| 1037 |
| 1038 void test_fieldTypeOk_unresolved_null() { |
| 1039 // Null always passes runtime type checks, even when the type is |
| 1040 // unresolved. |
| 1041 Source source = addSource(r''' |
| 1042 class A { |
| 1043 const A(x) : y = x; |
| 1044 final Unresolved y; |
| 1045 } |
| 1046 var v = const A(null);'''); |
| 1047 computeLibrarySourceErrors(source); |
| 1048 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); |
| 1049 verify([source]); |
| 1050 } |
| 1051 |
| 1052 void test_listElementTypeNotAssignable() { |
| 1053 Source source = addSource("var v = const <String> [42];"); |
| 1054 computeLibrarySourceErrors(source); |
| 1055 assertErrors(source, [ |
| 1056 CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, |
| 1057 StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE |
| 1058 ]); |
| 1059 verify([source]); |
| 1060 } |
| 1061 |
| 1062 void test_mapKeyTypeNotAssignable() { |
| 1063 Source source = addSource("var v = const <String, int > {1 : 2};"); |
| 1064 computeLibrarySourceErrors(source); |
| 1065 assertErrors(source, [ |
| 1066 CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, |
| 1067 StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE |
| 1068 ]); |
| 1069 verify([source]); |
| 1070 } |
| 1071 |
| 1072 void test_mapValueTypeNotAssignable() { |
| 1073 Source source = addSource("var v = const <String, String> {'a' : 2};"); |
| 1074 computeLibrarySourceErrors(source); |
| 1075 assertErrors(source, [ |
| 1076 CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, |
| 1077 StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE |
| 1078 ]); |
| 1079 verify([source]); |
| 1080 } |
| 1081 |
| 1082 void test_parameterAssignable_null() { |
| 1083 // Null is assignable to anything. |
| 1084 Source source = addSource(r''' |
| 1085 class A { |
| 1086 const A(int x); |
| 1087 } |
| 1088 var v = const A(null);'''); |
| 1089 computeLibrarySourceErrors(source); |
| 1090 assertNoErrors(source); |
| 1091 verify([source]); |
| 1092 } |
| 1093 |
| 1094 void test_parameterAssignable_typeSubstitution() { |
| 1095 Source source = addSource(r''' |
| 1096 class A<T> { |
| 1097 const A(T x); |
| 1098 } |
| 1099 var v = const A<int>(3);'''); |
| 1100 computeLibrarySourceErrors(source); |
| 1101 assertNoErrors(source); |
| 1102 verify([source]); |
| 1103 } |
| 1104 |
| 1105 void test_parameterAssignable_undefined_null() { |
| 1106 // Null always passes runtime type checks, even when the type is |
| 1107 // unresolved. |
| 1108 Source source = addSource(r''' |
| 1109 class A { |
| 1110 const A(Unresolved x); |
| 1111 } |
| 1112 var v = const A(null);'''); |
| 1113 computeLibrarySourceErrors(source); |
| 1114 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); |
| 1115 verify([source]); |
| 1116 } |
| 1117 |
| 1118 void test_parameterNotAssignable() { |
| 1119 Source source = addSource(r''' |
| 1120 class A { |
| 1121 const A(int x); |
| 1122 } |
| 1123 var v = const A('foo');'''); |
| 1124 computeLibrarySourceErrors(source); |
| 1125 assertErrors(source, [ |
| 1126 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 1127 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE |
| 1128 ]); |
| 1129 verify([source]); |
| 1130 } |
| 1131 |
| 1132 void test_parameterNotAssignable_typeSubstitution() { |
| 1133 Source source = addSource(r''' |
| 1134 class A<T> { |
| 1135 const A(T x); |
| 1136 } |
| 1137 var v = const A<int>('foo');'''); |
| 1138 computeLibrarySourceErrors(source); |
| 1139 assertErrors(source, [ |
| 1140 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 1141 StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE |
| 1142 ]); |
| 1143 verify([source]); |
| 1144 } |
| 1145 |
| 1146 void test_parameterNotAssignable_undefined() { |
| 1147 Source source = addSource(r''' |
| 1148 class A { |
| 1149 const A(Unresolved x); |
| 1150 } |
| 1151 var v = const A('foo');'''); |
| 1152 computeLibrarySourceErrors(source); |
| 1153 assertErrors(source, [ |
| 1154 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, |
| 1155 StaticWarningCode.UNDEFINED_CLASS |
| 1156 ]); |
| 1157 verify([source]); |
| 1158 } |
| 1159 |
| 1160 void test_redirectingConstructor_paramTypeMismatch() { |
| 1161 Source source = addSource(r''' |
| 1162 class A { |
| 1163 const A.a1(x) : this.a2(x); |
| 1164 const A.a2(String x); |
| 1165 } |
| 1166 var v = const A.a1(0);'''); |
| 1167 computeLibrarySourceErrors(source); |
| 1168 assertErrors(source, [ |
| 1169 CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH |
| 1170 ]); |
| 1171 verify([source]); |
| 1172 } |
| 1173 |
| 1174 void test_topLevelVarAssignable_null() { |
| 1175 Source source = addSource("const int x = null;"); |
| 1176 computeLibrarySourceErrors(source); |
| 1177 assertNoErrors(source); |
| 1178 verify([source]); |
| 1179 } |
| 1180 |
| 1181 void test_topLevelVarAssignable_undefined_null() { |
| 1182 // Null always passes runtime type checks, even when the type is |
| 1183 // unresolved. |
| 1184 Source source = addSource("const Unresolved x = null;"); |
| 1185 computeLibrarySourceErrors(source); |
| 1186 assertErrors(source, [StaticWarningCode.UNDEFINED_CLASS]); |
| 1187 verify([source]); |
| 1188 } |
| 1189 |
| 1190 void test_topLevelVarNotAssignable() { |
| 1191 Source source = addSource("const int x = 'foo';"); |
| 1192 computeLibrarySourceErrors(source); |
| 1193 assertErrors(source, [ |
| 1194 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, |
| 1195 StaticTypeWarningCode.INVALID_ASSIGNMENT |
| 1196 ]); |
| 1197 verify([source]); |
| 1198 } |
| 1199 |
| 1200 void test_topLevelVarNotAssignable_undefined() { |
| 1201 Source source = addSource("const Unresolved x = 'foo';"); |
| 1202 computeLibrarySourceErrors(source); |
| 1203 assertErrors(source, [ |
| 1204 CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, |
| 1205 StaticWarningCode.UNDEFINED_CLASS |
| 1206 ]); |
| 1207 verify([source]); |
| 1208 } |
| 1209 } |
| 1210 |
| 1211 @reflectiveTest |
| 1212 class ElementResolverTest extends EngineTestCase { |
| 1213 /** |
| 1214 * The error listener to which errors will be reported. |
| 1215 */ |
| 1216 GatheringErrorListener _listener; |
| 1217 |
| 1218 /** |
| 1219 * The type provider used to access the types. |
| 1220 */ |
| 1221 TestTypeProvider _typeProvider; |
| 1222 |
| 1223 /** |
| 1224 * The library containing the code being resolved. |
| 1225 */ |
| 1226 LibraryElementImpl _definingLibrary; |
| 1227 |
| 1228 /** |
| 1229 * The resolver visitor that maintains the state for the resolver. |
| 1230 */ |
| 1231 ResolverVisitor _visitor; |
| 1232 |
| 1233 /** |
| 1234 * The resolver being used to resolve the test cases. |
| 1235 */ |
| 1236 ElementResolver _resolver; |
| 1237 |
| 1238 void fail_visitExportDirective_combinators() { |
| 1239 fail("Not yet tested"); |
| 1240 // Need to set up the exported library so that the identifier can be |
| 1241 // resolved. |
| 1242 ExportDirective directive = AstFactory.exportDirective2(null, [ |
| 1243 AstFactory.hideCombinator2(["A"]) |
| 1244 ]); |
| 1245 _resolveNode(directive); |
| 1246 _listener.assertNoErrors(); |
| 1247 } |
| 1248 |
| 1249 void fail_visitFunctionExpressionInvocation() { |
| 1250 fail("Not yet tested"); |
| 1251 _listener.assertNoErrors(); |
| 1252 } |
| 1253 |
| 1254 void fail_visitImportDirective_combinators_noPrefix() { |
| 1255 fail("Not yet tested"); |
| 1256 // Need to set up the imported library so that the identifier can be |
| 1257 // resolved. |
| 1258 ImportDirective directive = AstFactory.importDirective3(null, null, [ |
| 1259 AstFactory.showCombinator2(["A"]) |
| 1260 ]); |
| 1261 _resolveNode(directive); |
| 1262 _listener.assertNoErrors(); |
| 1263 } |
| 1264 |
| 1265 void fail_visitImportDirective_combinators_prefix() { |
| 1266 fail("Not yet tested"); |
| 1267 // Need to set up the imported library so that the identifiers can be |
| 1268 // resolved. |
| 1269 String prefixName = "p"; |
| 1270 _definingLibrary.imports = <ImportElement>[ |
| 1271 ElementFactory.importFor(null, ElementFactory.prefix(prefixName)) |
| 1272 ]; |
| 1273 ImportDirective directive = AstFactory.importDirective3(null, prefixName, [ |
| 1274 AstFactory.showCombinator2(["A"]), |
| 1275 AstFactory.hideCombinator2(["B"]) |
| 1276 ]); |
| 1277 _resolveNode(directive); |
| 1278 _listener.assertNoErrors(); |
| 1279 } |
| 1280 |
| 1281 void fail_visitRedirectingConstructorInvocation() { |
| 1282 fail("Not yet tested"); |
| 1283 _listener.assertNoErrors(); |
| 1284 } |
| 1285 |
| 1286 @override |
| 1287 void setUp() { |
| 1288 _listener = new GatheringErrorListener(); |
| 1289 _typeProvider = new TestTypeProvider(); |
| 1290 _resolver = _createResolver(); |
| 1291 } |
| 1292 |
| 1293 void test_lookUpMethodInInterfaces() { |
| 1294 InterfaceType intType = _typeProvider.intType; |
| 1295 // |
| 1296 // abstract class A { int operator[](int index); } |
| 1297 // |
| 1298 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1299 MethodElement operator = |
| 1300 ElementFactory.methodElement("[]", intType, [intType]); |
| 1301 classA.methods = <MethodElement>[operator]; |
| 1302 // |
| 1303 // class B implements A {} |
| 1304 // |
| 1305 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 1306 classB.interfaces = <InterfaceType>[classA.type]; |
| 1307 // |
| 1308 // class C extends Object with B {} |
| 1309 // |
| 1310 ClassElementImpl classC = ElementFactory.classElement2("C"); |
| 1311 classC.mixins = <InterfaceType>[classB.type]; |
| 1312 // |
| 1313 // class D extends C {} |
| 1314 // |
| 1315 ClassElementImpl classD = ElementFactory.classElement("D", classC.type); |
| 1316 // |
| 1317 // D a; |
| 1318 // a[i]; |
| 1319 // |
| 1320 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 1321 array.staticType = classD.type; |
| 1322 IndexExpression expression = |
| 1323 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 1324 expect(_resolveIndexExpression(expression), same(operator)); |
| 1325 _listener.assertNoErrors(); |
| 1326 } |
| 1327 |
| 1328 void test_visitAssignmentExpression_compound() { |
| 1329 InterfaceType intType = _typeProvider.intType; |
| 1330 SimpleIdentifier leftHandSide = AstFactory.identifier3("a"); |
| 1331 leftHandSide.staticType = intType; |
| 1332 AssignmentExpression assignment = AstFactory.assignmentExpression( |
| 1333 leftHandSide, TokenType.PLUS_EQ, AstFactory.integer(1)); |
| 1334 _resolveNode(assignment); |
| 1335 expect( |
| 1336 assignment.staticElement, same(getMethod(_typeProvider.numType, "+"))); |
| 1337 _listener.assertNoErrors(); |
| 1338 } |
| 1339 |
| 1340 void test_visitAssignmentExpression_simple() { |
| 1341 AssignmentExpression expression = AstFactory.assignmentExpression( |
| 1342 AstFactory.identifier3("x"), TokenType.EQ, AstFactory.integer(0)); |
| 1343 _resolveNode(expression); |
| 1344 expect(expression.staticElement, isNull); |
| 1345 _listener.assertNoErrors(); |
| 1346 } |
| 1347 |
| 1348 void test_visitBinaryExpression_bangEq() { |
| 1349 // String i; |
| 1350 // var j; |
| 1351 // i == j |
| 1352 InterfaceType stringType = _typeProvider.stringType; |
| 1353 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1354 left.staticType = stringType; |
| 1355 BinaryExpression expression = AstFactory.binaryExpression( |
| 1356 left, TokenType.BANG_EQ, AstFactory.identifier3("j")); |
| 1357 _resolveNode(expression); |
| 1358 var stringElement = stringType.element; |
| 1359 expect(expression.staticElement, isNotNull); |
| 1360 expect( |
| 1361 expression.staticElement, |
| 1362 stringElement.lookUpMethod( |
| 1363 TokenType.EQ_EQ.lexeme, stringElement.library)); |
| 1364 expect(expression.propagatedElement, isNull); |
| 1365 _listener.assertNoErrors(); |
| 1366 } |
| 1367 |
| 1368 void test_visitBinaryExpression_eq() { |
| 1369 // String i; |
| 1370 // var j; |
| 1371 // i == j |
| 1372 InterfaceType stringType = _typeProvider.stringType; |
| 1373 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1374 left.staticType = stringType; |
| 1375 BinaryExpression expression = AstFactory.binaryExpression( |
| 1376 left, TokenType.EQ_EQ, AstFactory.identifier3("j")); |
| 1377 _resolveNode(expression); |
| 1378 var stringElement = stringType.element; |
| 1379 expect( |
| 1380 expression.staticElement, |
| 1381 stringElement.lookUpMethod( |
| 1382 TokenType.EQ_EQ.lexeme, stringElement.library)); |
| 1383 expect(expression.propagatedElement, isNull); |
| 1384 _listener.assertNoErrors(); |
| 1385 } |
| 1386 |
| 1387 void test_visitBinaryExpression_plus() { |
| 1388 // num i; |
| 1389 // var j; |
| 1390 // i + j |
| 1391 InterfaceType numType = _typeProvider.numType; |
| 1392 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1393 left.staticType = numType; |
| 1394 BinaryExpression expression = AstFactory.binaryExpression( |
| 1395 left, TokenType.PLUS, AstFactory.identifier3("j")); |
| 1396 _resolveNode(expression); |
| 1397 expect(expression.staticElement, getMethod(numType, "+")); |
| 1398 expect(expression.propagatedElement, isNull); |
| 1399 _listener.assertNoErrors(); |
| 1400 } |
| 1401 |
| 1402 void test_visitBinaryExpression_plus_propagatedElement() { |
| 1403 // var i = 1; |
| 1404 // var j; |
| 1405 // i + j |
| 1406 InterfaceType numType = _typeProvider.numType; |
| 1407 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1408 left.propagatedType = numType; |
| 1409 BinaryExpression expression = AstFactory.binaryExpression( |
| 1410 left, TokenType.PLUS, AstFactory.identifier3("j")); |
| 1411 _resolveNode(expression); |
| 1412 expect(expression.staticElement, isNull); |
| 1413 expect(expression.propagatedElement, getMethod(numType, "+")); |
| 1414 _listener.assertNoErrors(); |
| 1415 } |
| 1416 |
| 1417 void test_visitBreakStatement_withLabel() { |
| 1418 // loop: while (true) { |
| 1419 // break loop; |
| 1420 // } |
| 1421 String label = "loop"; |
| 1422 LabelElementImpl labelElement = |
| 1423 new LabelElementImpl(AstFactory.identifier3(label), false, false); |
| 1424 BreakStatement breakStatement = AstFactory.breakStatement2(label); |
| 1425 Expression condition = AstFactory.booleanLiteral(true); |
| 1426 WhileStatement whileStatement = |
| 1427 AstFactory.whileStatement(condition, breakStatement); |
| 1428 expect(_resolveBreak(breakStatement, labelElement, whileStatement), |
| 1429 same(labelElement)); |
| 1430 expect(breakStatement.target, same(whileStatement)); |
| 1431 _listener.assertNoErrors(); |
| 1432 } |
| 1433 |
| 1434 void test_visitBreakStatement_withoutLabel() { |
| 1435 BreakStatement statement = AstFactory.breakStatement(); |
| 1436 _resolveStatement(statement, null, null); |
| 1437 _listener.assertNoErrors(); |
| 1438 } |
| 1439 |
| 1440 void test_visitConstructorName_named() { |
| 1441 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1442 String constructorName = "a"; |
| 1443 ConstructorElement constructor = |
| 1444 ElementFactory.constructorElement2(classA, constructorName); |
| 1445 classA.constructors = <ConstructorElement>[constructor]; |
| 1446 ConstructorName name = AstFactory.constructorName( |
| 1447 AstFactory.typeName(classA), constructorName); |
| 1448 _resolveNode(name); |
| 1449 expect(name.staticElement, same(constructor)); |
| 1450 _listener.assertNoErrors(); |
| 1451 } |
| 1452 |
| 1453 void test_visitConstructorName_unnamed() { |
| 1454 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1455 String constructorName = null; |
| 1456 ConstructorElement constructor = |
| 1457 ElementFactory.constructorElement2(classA, constructorName); |
| 1458 classA.constructors = <ConstructorElement>[constructor]; |
| 1459 ConstructorName name = AstFactory.constructorName( |
| 1460 AstFactory.typeName(classA), constructorName); |
| 1461 _resolveNode(name); |
| 1462 expect(name.staticElement, same(constructor)); |
| 1463 _listener.assertNoErrors(); |
| 1464 } |
| 1465 |
| 1466 void test_visitContinueStatement_withLabel() { |
| 1467 // loop: while (true) { |
| 1468 // continue loop; |
| 1469 // } |
| 1470 String label = "loop"; |
| 1471 LabelElementImpl labelElement = |
| 1472 new LabelElementImpl(AstFactory.identifier3(label), false, false); |
| 1473 ContinueStatement continueStatement = AstFactory.continueStatement(label); |
| 1474 Expression condition = AstFactory.booleanLiteral(true); |
| 1475 WhileStatement whileStatement = |
| 1476 AstFactory.whileStatement(condition, continueStatement); |
| 1477 expect(_resolveContinue(continueStatement, labelElement, whileStatement), |
| 1478 same(labelElement)); |
| 1479 expect(continueStatement.target, same(whileStatement)); |
| 1480 _listener.assertNoErrors(); |
| 1481 } |
| 1482 |
| 1483 void test_visitContinueStatement_withoutLabel() { |
| 1484 ContinueStatement statement = AstFactory.continueStatement(); |
| 1485 _resolveStatement(statement, null, null); |
| 1486 _listener.assertNoErrors(); |
| 1487 } |
| 1488 |
| 1489 void test_visitEnumDeclaration() { |
| 1490 ClassElementImpl enumElement = |
| 1491 ElementFactory.enumElement(_typeProvider, ('E')); |
| 1492 EnumDeclaration enumNode = AstFactory.enumDeclaration2('E', []); |
| 1493 Annotation annotationNode = |
| 1494 AstFactory.annotation(AstFactory.identifier3('a')); |
| 1495 annotationNode.element = ElementFactory.classElement2('A'); |
| 1496 enumNode.metadata.add(annotationNode); |
| 1497 enumNode.name.staticElement = enumElement; |
| 1498 _resolveNode(enumNode); |
| 1499 List<ElementAnnotation> metadata = enumElement.metadata; |
| 1500 expect(metadata, hasLength(1)); |
| 1501 } |
| 1502 |
| 1503 void test_visitExportDirective_noCombinators() { |
| 1504 ExportDirective directive = AstFactory.exportDirective2(null); |
| 1505 directive.element = ElementFactory |
| 1506 .exportFor(ElementFactory.library(_definingLibrary.context, "lib")); |
| 1507 _resolveNode(directive); |
| 1508 _listener.assertNoErrors(); |
| 1509 } |
| 1510 |
| 1511 void test_visitFieldFormalParameter() { |
| 1512 String fieldName = "f"; |
| 1513 InterfaceType intType = _typeProvider.intType; |
| 1514 FieldElementImpl fieldElement = |
| 1515 ElementFactory.fieldElement(fieldName, false, false, false, intType); |
| 1516 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1517 classA.fields = <FieldElement>[fieldElement]; |
| 1518 FieldFormalParameter parameter = |
| 1519 AstFactory.fieldFormalParameter2(fieldName); |
| 1520 FieldFormalParameterElementImpl parameterElement = |
| 1521 ElementFactory.fieldFormalParameter(parameter.identifier); |
| 1522 parameterElement.field = fieldElement; |
| 1523 parameterElement.type = intType; |
| 1524 parameter.identifier.staticElement = parameterElement; |
| 1525 _resolveInClass(parameter, classA); |
| 1526 expect(parameter.element.type, same(intType)); |
| 1527 } |
| 1528 |
| 1529 void test_visitImportDirective_noCombinators_noPrefix() { |
| 1530 ImportDirective directive = AstFactory.importDirective3(null, null); |
| 1531 directive.element = ElementFactory.importFor( |
| 1532 ElementFactory.library(_definingLibrary.context, "lib"), null); |
| 1533 _resolveNode(directive); |
| 1534 _listener.assertNoErrors(); |
| 1535 } |
| 1536 |
| 1537 void test_visitImportDirective_noCombinators_prefix() { |
| 1538 String prefixName = "p"; |
| 1539 ImportElement importElement = ElementFactory.importFor( |
| 1540 ElementFactory.library(_definingLibrary.context, "lib"), |
| 1541 ElementFactory.prefix(prefixName)); |
| 1542 _definingLibrary.imports = <ImportElement>[importElement]; |
| 1543 ImportDirective directive = AstFactory.importDirective3(null, prefixName); |
| 1544 directive.element = importElement; |
| 1545 _resolveNode(directive); |
| 1546 _listener.assertNoErrors(); |
| 1547 } |
| 1548 |
| 1549 void test_visitImportDirective_withCombinators() { |
| 1550 ShowCombinator combinator = AstFactory.showCombinator2(["A", "B", "C"]); |
| 1551 ImportDirective directive = |
| 1552 AstFactory.importDirective3(null, null, [combinator]); |
| 1553 LibraryElementImpl library = |
| 1554 ElementFactory.library(_definingLibrary.context, "lib"); |
| 1555 TopLevelVariableElementImpl varA = |
| 1556 ElementFactory.topLevelVariableElement2("A"); |
| 1557 TopLevelVariableElementImpl varB = |
| 1558 ElementFactory.topLevelVariableElement2("B"); |
| 1559 TopLevelVariableElementImpl varC = |
| 1560 ElementFactory.topLevelVariableElement2("C"); |
| 1561 CompilationUnitElementImpl unit = |
| 1562 library.definingCompilationUnit as CompilationUnitElementImpl; |
| 1563 unit.accessors = <PropertyAccessorElement>[ |
| 1564 varA.getter, |
| 1565 varA.setter, |
| 1566 varB.getter, |
| 1567 varC.setter |
| 1568 ]; |
| 1569 unit.topLevelVariables = <TopLevelVariableElement>[varA, varB, varC]; |
| 1570 directive.element = ElementFactory.importFor(library, null); |
| 1571 _resolveNode(directive); |
| 1572 expect(combinator.shownNames[0].staticElement, same(varA)); |
| 1573 expect(combinator.shownNames[1].staticElement, same(varB)); |
| 1574 expect(combinator.shownNames[2].staticElement, same(varC)); |
| 1575 _listener.assertNoErrors(); |
| 1576 } |
| 1577 |
| 1578 void test_visitIndexExpression_get() { |
| 1579 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1580 InterfaceType intType = _typeProvider.intType; |
| 1581 MethodElement getter = |
| 1582 ElementFactory.methodElement("[]", intType, [intType]); |
| 1583 classA.methods = <MethodElement>[getter]; |
| 1584 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 1585 array.staticType = classA.type; |
| 1586 IndexExpression expression = |
| 1587 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 1588 expect(_resolveIndexExpression(expression), same(getter)); |
| 1589 _listener.assertNoErrors(); |
| 1590 } |
| 1591 |
| 1592 void test_visitIndexExpression_set() { |
| 1593 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1594 InterfaceType intType = _typeProvider.intType; |
| 1595 MethodElement setter = |
| 1596 ElementFactory.methodElement("[]=", intType, [intType]); |
| 1597 classA.methods = <MethodElement>[setter]; |
| 1598 SimpleIdentifier array = AstFactory.identifier3("a"); |
| 1599 array.staticType = classA.type; |
| 1600 IndexExpression expression = |
| 1601 AstFactory.indexExpression(array, AstFactory.identifier3("i")); |
| 1602 AstFactory.assignmentExpression( |
| 1603 expression, TokenType.EQ, AstFactory.integer(0)); |
| 1604 expect(_resolveIndexExpression(expression), same(setter)); |
| 1605 _listener.assertNoErrors(); |
| 1606 } |
| 1607 |
| 1608 void test_visitInstanceCreationExpression_named() { |
| 1609 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1610 String constructorName = "a"; |
| 1611 ConstructorElement constructor = |
| 1612 ElementFactory.constructorElement2(classA, constructorName); |
| 1613 classA.constructors = <ConstructorElement>[constructor]; |
| 1614 ConstructorName name = AstFactory.constructorName( |
| 1615 AstFactory.typeName(classA), constructorName); |
| 1616 name.staticElement = constructor; |
| 1617 InstanceCreationExpression creation = |
| 1618 AstFactory.instanceCreationExpression(Keyword.NEW, name); |
| 1619 _resolveNode(creation); |
| 1620 expect(creation.staticElement, same(constructor)); |
| 1621 _listener.assertNoErrors(); |
| 1622 } |
| 1623 |
| 1624 void test_visitInstanceCreationExpression_unnamed() { |
| 1625 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1626 String constructorName = null; |
| 1627 ConstructorElement constructor = |
| 1628 ElementFactory.constructorElement2(classA, constructorName); |
| 1629 classA.constructors = <ConstructorElement>[constructor]; |
| 1630 ConstructorName name = AstFactory.constructorName( |
| 1631 AstFactory.typeName(classA), constructorName); |
| 1632 name.staticElement = constructor; |
| 1633 InstanceCreationExpression creation = |
| 1634 AstFactory.instanceCreationExpression(Keyword.NEW, name); |
| 1635 _resolveNode(creation); |
| 1636 expect(creation.staticElement, same(constructor)); |
| 1637 _listener.assertNoErrors(); |
| 1638 } |
| 1639 |
| 1640 void test_visitInstanceCreationExpression_unnamed_namedParameter() { |
| 1641 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1642 String constructorName = null; |
| 1643 ConstructorElementImpl constructor = |
| 1644 ElementFactory.constructorElement2(classA, constructorName); |
| 1645 String parameterName = "a"; |
| 1646 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 1647 constructor.parameters = <ParameterElement>[parameter]; |
| 1648 classA.constructors = <ConstructorElement>[constructor]; |
| 1649 ConstructorName name = AstFactory.constructorName( |
| 1650 AstFactory.typeName(classA), constructorName); |
| 1651 name.staticElement = constructor; |
| 1652 InstanceCreationExpression creation = AstFactory.instanceCreationExpression( |
| 1653 Keyword.NEW, |
| 1654 name, |
| 1655 [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]); |
| 1656 _resolveNode(creation); |
| 1657 expect(creation.staticElement, same(constructor)); |
| 1658 expect( |
| 1659 (creation.argumentList.arguments[0] as NamedExpression) |
| 1660 .name |
| 1661 .label |
| 1662 .staticElement, |
| 1663 same(parameter)); |
| 1664 _listener.assertNoErrors(); |
| 1665 } |
| 1666 |
| 1667 void test_visitMethodInvocation() { |
| 1668 InterfaceType numType = _typeProvider.numType; |
| 1669 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1670 left.staticType = numType; |
| 1671 String methodName = "abs"; |
| 1672 MethodInvocation invocation = AstFactory.methodInvocation(left, methodName); |
| 1673 _resolveNode(invocation); |
| 1674 expect(invocation.methodName.staticElement, |
| 1675 same(getMethod(numType, methodName))); |
| 1676 _listener.assertNoErrors(); |
| 1677 } |
| 1678 |
| 1679 void test_visitMethodInvocation_namedParameter() { |
| 1680 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1681 String methodName = "m"; |
| 1682 String parameterName = "p"; |
| 1683 MethodElementImpl method = ElementFactory.methodElement(methodName, null); |
| 1684 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 1685 method.parameters = <ParameterElement>[parameter]; |
| 1686 classA.methods = <MethodElement>[method]; |
| 1687 SimpleIdentifier left = AstFactory.identifier3("i"); |
| 1688 left.staticType = classA.type; |
| 1689 MethodInvocation invocation = AstFactory.methodInvocation(left, methodName, |
| 1690 [AstFactory.namedExpression2(parameterName, AstFactory.integer(0))]); |
| 1691 _resolveNode(invocation); |
| 1692 expect(invocation.methodName.staticElement, same(method)); |
| 1693 expect( |
| 1694 (invocation.argumentList.arguments[0] as NamedExpression) |
| 1695 .name |
| 1696 .label |
| 1697 .staticElement, |
| 1698 same(parameter)); |
| 1699 _listener.assertNoErrors(); |
| 1700 } |
| 1701 |
| 1702 void test_visitPostfixExpression() { |
| 1703 InterfaceType numType = _typeProvider.numType; |
| 1704 SimpleIdentifier operand = AstFactory.identifier3("i"); |
| 1705 operand.staticType = numType; |
| 1706 PostfixExpression expression = |
| 1707 AstFactory.postfixExpression(operand, TokenType.PLUS_PLUS); |
| 1708 _resolveNode(expression); |
| 1709 expect(expression.staticElement, getMethod(numType, "+")); |
| 1710 _listener.assertNoErrors(); |
| 1711 } |
| 1712 |
| 1713 void test_visitPrefixedIdentifier_dynamic() { |
| 1714 DartType dynamicType = _typeProvider.dynamicType; |
| 1715 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 1716 VariableElementImpl variable = ElementFactory.localVariableElement(target); |
| 1717 variable.type = dynamicType; |
| 1718 target.staticElement = variable; |
| 1719 target.staticType = dynamicType; |
| 1720 PrefixedIdentifier identifier = |
| 1721 AstFactory.identifier(target, AstFactory.identifier3("b")); |
| 1722 _resolveNode(identifier); |
| 1723 expect(identifier.staticElement, isNull); |
| 1724 expect(identifier.identifier.staticElement, isNull); |
| 1725 _listener.assertNoErrors(); |
| 1726 } |
| 1727 |
| 1728 void test_visitPrefixedIdentifier_nonDynamic() { |
| 1729 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1730 String getterName = "b"; |
| 1731 PropertyAccessorElement getter = |
| 1732 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 1733 classA.accessors = <PropertyAccessorElement>[getter]; |
| 1734 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 1735 VariableElementImpl variable = ElementFactory.localVariableElement(target); |
| 1736 variable.type = classA.type; |
| 1737 target.staticElement = variable; |
| 1738 target.staticType = classA.type; |
| 1739 PrefixedIdentifier identifier = |
| 1740 AstFactory.identifier(target, AstFactory.identifier3(getterName)); |
| 1741 _resolveNode(identifier); |
| 1742 expect(identifier.staticElement, same(getter)); |
| 1743 expect(identifier.identifier.staticElement, same(getter)); |
| 1744 _listener.assertNoErrors(); |
| 1745 } |
| 1746 |
| 1747 void test_visitPrefixedIdentifier_staticClassMember_getter() { |
| 1748 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1749 // set accessors |
| 1750 String propName = "b"; |
| 1751 PropertyAccessorElement getter = |
| 1752 ElementFactory.getterElement(propName, false, _typeProvider.intType); |
| 1753 PropertyAccessorElement setter = |
| 1754 ElementFactory.setterElement(propName, false, _typeProvider.intType); |
| 1755 classA.accessors = <PropertyAccessorElement>[getter, setter]; |
| 1756 // prepare "A.m" |
| 1757 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 1758 target.staticElement = classA; |
| 1759 target.staticType = classA.type; |
| 1760 PrefixedIdentifier identifier = |
| 1761 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 1762 // resolve |
| 1763 _resolveNode(identifier); |
| 1764 expect(identifier.staticElement, same(getter)); |
| 1765 expect(identifier.identifier.staticElement, same(getter)); |
| 1766 _listener.assertNoErrors(); |
| 1767 } |
| 1768 |
| 1769 void test_visitPrefixedIdentifier_staticClassMember_method() { |
| 1770 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1771 // set methods |
| 1772 String propName = "m"; |
| 1773 MethodElement method = |
| 1774 ElementFactory.methodElement("m", _typeProvider.intType); |
| 1775 classA.methods = <MethodElement>[method]; |
| 1776 // prepare "A.m" |
| 1777 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 1778 target.staticElement = classA; |
| 1779 target.staticType = classA.type; |
| 1780 PrefixedIdentifier identifier = |
| 1781 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 1782 AstFactory.assignmentExpression( |
| 1783 identifier, TokenType.EQ, AstFactory.nullLiteral()); |
| 1784 // resolve |
| 1785 _resolveNode(identifier); |
| 1786 expect(identifier.staticElement, same(method)); |
| 1787 expect(identifier.identifier.staticElement, same(method)); |
| 1788 _listener.assertNoErrors(); |
| 1789 } |
| 1790 |
| 1791 void test_visitPrefixedIdentifier_staticClassMember_setter() { |
| 1792 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1793 // set accessors |
| 1794 String propName = "b"; |
| 1795 PropertyAccessorElement getter = |
| 1796 ElementFactory.getterElement(propName, false, _typeProvider.intType); |
| 1797 PropertyAccessorElement setter = |
| 1798 ElementFactory.setterElement(propName, false, _typeProvider.intType); |
| 1799 classA.accessors = <PropertyAccessorElement>[getter, setter]; |
| 1800 // prepare "A.b = null" |
| 1801 SimpleIdentifier target = AstFactory.identifier3("A"); |
| 1802 target.staticElement = classA; |
| 1803 target.staticType = classA.type; |
| 1804 PrefixedIdentifier identifier = |
| 1805 AstFactory.identifier(target, AstFactory.identifier3(propName)); |
| 1806 AstFactory.assignmentExpression( |
| 1807 identifier, TokenType.EQ, AstFactory.nullLiteral()); |
| 1808 // resolve |
| 1809 _resolveNode(identifier); |
| 1810 expect(identifier.staticElement, same(setter)); |
| 1811 expect(identifier.identifier.staticElement, same(setter)); |
| 1812 _listener.assertNoErrors(); |
| 1813 } |
| 1814 |
| 1815 void test_visitPrefixExpression() { |
| 1816 InterfaceType numType = _typeProvider.numType; |
| 1817 SimpleIdentifier operand = AstFactory.identifier3("i"); |
| 1818 operand.staticType = numType; |
| 1819 PrefixExpression expression = |
| 1820 AstFactory.prefixExpression(TokenType.PLUS_PLUS, operand); |
| 1821 _resolveNode(expression); |
| 1822 expect(expression.staticElement, getMethod(numType, "+")); |
| 1823 _listener.assertNoErrors(); |
| 1824 } |
| 1825 |
| 1826 void test_visitPropertyAccess_getter_identifier() { |
| 1827 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1828 String getterName = "b"; |
| 1829 PropertyAccessorElement getter = |
| 1830 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 1831 classA.accessors = <PropertyAccessorElement>[getter]; |
| 1832 SimpleIdentifier target = AstFactory.identifier3("a"); |
| 1833 target.staticType = classA.type; |
| 1834 PropertyAccess access = AstFactory.propertyAccess2(target, getterName); |
| 1835 _resolveNode(access); |
| 1836 expect(access.propertyName.staticElement, same(getter)); |
| 1837 _listener.assertNoErrors(); |
| 1838 } |
| 1839 |
| 1840 void test_visitPropertyAccess_getter_super() { |
| 1841 // |
| 1842 // class A { |
| 1843 // int get b; |
| 1844 // } |
| 1845 // class B { |
| 1846 // ... super.m ... |
| 1847 // } |
| 1848 // |
| 1849 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1850 String getterName = "b"; |
| 1851 PropertyAccessorElement getter = |
| 1852 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 1853 classA.accessors = <PropertyAccessorElement>[getter]; |
| 1854 SuperExpression target = AstFactory.superExpression(); |
| 1855 target.staticType = ElementFactory.classElement("B", classA.type).type; |
| 1856 PropertyAccess access = AstFactory.propertyAccess2(target, getterName); |
| 1857 AstFactory.methodDeclaration2( |
| 1858 null, |
| 1859 null, |
| 1860 null, |
| 1861 null, |
| 1862 AstFactory.identifier3("m"), |
| 1863 AstFactory.formalParameterList(), |
| 1864 AstFactory.expressionFunctionBody(access)); |
| 1865 _resolveNode(access); |
| 1866 expect(access.propertyName.staticElement, same(getter)); |
| 1867 _listener.assertNoErrors(); |
| 1868 } |
| 1869 |
| 1870 void test_visitPropertyAccess_setter_this() { |
| 1871 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1872 String setterName = "b"; |
| 1873 PropertyAccessorElement setter = |
| 1874 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 1875 classA.accessors = <PropertyAccessorElement>[setter]; |
| 1876 ThisExpression target = AstFactory.thisExpression(); |
| 1877 target.staticType = classA.type; |
| 1878 PropertyAccess access = AstFactory.propertyAccess2(target, setterName); |
| 1879 AstFactory.assignmentExpression( |
| 1880 access, TokenType.EQ, AstFactory.integer(0)); |
| 1881 _resolveNode(access); |
| 1882 expect(access.propertyName.staticElement, same(setter)); |
| 1883 _listener.assertNoErrors(); |
| 1884 } |
| 1885 |
| 1886 void test_visitSimpleIdentifier_classScope() { |
| 1887 InterfaceType doubleType = _typeProvider.doubleType; |
| 1888 String fieldName = "NAN"; |
| 1889 SimpleIdentifier node = AstFactory.identifier3(fieldName); |
| 1890 _resolveInClass(node, doubleType.element); |
| 1891 expect(node.staticElement, getGetter(doubleType, fieldName)); |
| 1892 _listener.assertNoErrors(); |
| 1893 } |
| 1894 |
| 1895 void test_visitSimpleIdentifier_dynamic() { |
| 1896 SimpleIdentifier node = AstFactory.identifier3("dynamic"); |
| 1897 _resolveIdentifier(node); |
| 1898 expect(node.staticElement, same(_typeProvider.dynamicType.element)); |
| 1899 expect(node.staticType, same(_typeProvider.typeType)); |
| 1900 _listener.assertNoErrors(); |
| 1901 } |
| 1902 |
| 1903 void test_visitSimpleIdentifier_lexicalScope() { |
| 1904 SimpleIdentifier node = AstFactory.identifier3("i"); |
| 1905 VariableElementImpl element = ElementFactory.localVariableElement(node); |
| 1906 expect(_resolveIdentifier(node, [element]), same(element)); |
| 1907 _listener.assertNoErrors(); |
| 1908 } |
| 1909 |
| 1910 void test_visitSimpleIdentifier_lexicalScope_field_setter() { |
| 1911 InterfaceType intType = _typeProvider.intType; |
| 1912 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 1913 String fieldName = "a"; |
| 1914 FieldElement field = |
| 1915 ElementFactory.fieldElement(fieldName, false, false, false, intType); |
| 1916 classA.fields = <FieldElement>[field]; |
| 1917 classA.accessors = <PropertyAccessorElement>[field.getter, field.setter]; |
| 1918 SimpleIdentifier node = AstFactory.identifier3(fieldName); |
| 1919 AstFactory.assignmentExpression(node, TokenType.EQ, AstFactory.integer(0)); |
| 1920 _resolveInClass(node, classA); |
| 1921 Element element = node.staticElement; |
| 1922 EngineTestCase.assertInstanceOf((obj) => obj is PropertyAccessorElement, |
| 1923 PropertyAccessorElement, element); |
| 1924 expect((element as PropertyAccessorElement).isSetter, isTrue); |
| 1925 _listener.assertNoErrors(); |
| 1926 } |
| 1927 |
| 1928 void test_visitSuperConstructorInvocation() { |
| 1929 ClassElementImpl superclass = ElementFactory.classElement2("A"); |
| 1930 ConstructorElementImpl superConstructor = |
| 1931 ElementFactory.constructorElement2(superclass, null); |
| 1932 superclass.constructors = <ConstructorElement>[superConstructor]; |
| 1933 ClassElementImpl subclass = |
| 1934 ElementFactory.classElement("B", superclass.type); |
| 1935 ConstructorElementImpl subConstructor = |
| 1936 ElementFactory.constructorElement2(subclass, null); |
| 1937 subclass.constructors = <ConstructorElement>[subConstructor]; |
| 1938 SuperConstructorInvocation invocation = |
| 1939 AstFactory.superConstructorInvocation(); |
| 1940 _resolveInClass(invocation, subclass); |
| 1941 expect(invocation.staticElement, superConstructor); |
| 1942 _listener.assertNoErrors(); |
| 1943 } |
| 1944 |
| 1945 void test_visitSuperConstructorInvocation_namedParameter() { |
| 1946 ClassElementImpl superclass = ElementFactory.classElement2("A"); |
| 1947 ConstructorElementImpl superConstructor = |
| 1948 ElementFactory.constructorElement2(superclass, null); |
| 1949 String parameterName = "p"; |
| 1950 ParameterElement parameter = ElementFactory.namedParameter(parameterName); |
| 1951 superConstructor.parameters = <ParameterElement>[parameter]; |
| 1952 superclass.constructors = <ConstructorElement>[superConstructor]; |
| 1953 ClassElementImpl subclass = |
| 1954 ElementFactory.classElement("B", superclass.type); |
| 1955 ConstructorElementImpl subConstructor = |
| 1956 ElementFactory.constructorElement2(subclass, null); |
| 1957 subclass.constructors = <ConstructorElement>[subConstructor]; |
| 1958 SuperConstructorInvocation invocation = AstFactory |
| 1959 .superConstructorInvocation([ |
| 1960 AstFactory.namedExpression2(parameterName, AstFactory.integer(0)) |
| 1961 ]); |
| 1962 _resolveInClass(invocation, subclass); |
| 1963 expect(invocation.staticElement, superConstructor); |
| 1964 expect( |
| 1965 (invocation.argumentList.arguments[0] as NamedExpression) |
| 1966 .name |
| 1967 .label |
| 1968 .staticElement, |
| 1969 same(parameter)); |
| 1970 _listener.assertNoErrors(); |
| 1971 } |
| 1972 |
| 1973 /** |
| 1974 * Create the resolver used by the tests. |
| 1975 * |
| 1976 * @return the resolver that was created |
| 1977 */ |
| 1978 ElementResolver _createResolver() { |
| 1979 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 1980 FileBasedSource source = |
| 1981 new FileBasedSource(FileUtilities2.createFile("/test.dart")); |
| 1982 CompilationUnitElementImpl definingCompilationUnit = |
| 1983 new CompilationUnitElementImpl("test.dart"); |
| 1984 definingCompilationUnit.librarySource = |
| 1985 definingCompilationUnit.source = source; |
| 1986 _definingLibrary = ElementFactory.library(context, "test"); |
| 1987 _definingLibrary.definingCompilationUnit = definingCompilationUnit; |
| 1988 Library library = new Library(context, _listener, source); |
| 1989 library.libraryElement = _definingLibrary; |
| 1990 _visitor = new ResolverVisitor( |
| 1991 library.libraryElement, source, _typeProvider, library.errorListener, |
| 1992 nameScope: library.libraryScope, |
| 1993 inheritanceManager: library.inheritanceManager); |
| 1994 try { |
| 1995 return _visitor.elementResolver; |
| 1996 } catch (exception) { |
| 1997 throw new IllegalArgumentException( |
| 1998 "Could not create resolver", exception); |
| 1999 } |
| 2000 } |
| 2001 |
| 2002 /** |
| 2003 * Return the element associated with the label of [statement] after the |
| 2004 * resolver has resolved it. [labelElement] is the label element to be |
| 2005 * defined in the statement's label scope, and [labelTarget] is the statement |
| 2006 * the label resolves to. |
| 2007 */ |
| 2008 Element _resolveBreak(BreakStatement statement, LabelElementImpl labelElement, |
| 2009 Statement labelTarget) { |
| 2010 _resolveStatement(statement, labelElement, labelTarget); |
| 2011 return statement.label.staticElement; |
| 2012 } |
| 2013 |
| 2014 /** |
| 2015 * Return the element associated with the label [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 AST node |
| 2018 * the label resolves to. |
| 2019 * |
| 2020 * @param statement the statement to be resolved |
| 2021 * @param labelElement the label element to be defined in the statement's labe
l scope |
| 2022 * @return the element to which the statement's label was resolved |
| 2023 */ |
| 2024 Element _resolveContinue(ContinueStatement statement, |
| 2025 LabelElementImpl labelElement, AstNode labelTarget) { |
| 2026 _resolveStatement(statement, labelElement, labelTarget); |
| 2027 return statement.label.staticElement; |
| 2028 } |
| 2029 |
| 2030 /** |
| 2031 * Return the element associated with the given identifier after the resolver
has resolved the |
| 2032 * identifier. |
| 2033 * |
| 2034 * @param node the expression to be resolved |
| 2035 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 2036 * being resolved |
| 2037 * @return the element to which the expression was resolved |
| 2038 */ |
| 2039 Element _resolveIdentifier(Identifier node, [List<Element> definedElements]) { |
| 2040 _resolveNode(node, definedElements); |
| 2041 return node.staticElement; |
| 2042 } |
| 2043 |
| 2044 /** |
| 2045 * Return the element associated with the given identifier after the resolver
has resolved the |
| 2046 * identifier. |
| 2047 * |
| 2048 * @param node the expression to be resolved |
| 2049 * @param enclosingClass the element representing the class enclosing the iden
tifier |
| 2050 * @return the element to which the expression was resolved |
| 2051 */ |
| 2052 void _resolveInClass(AstNode node, ClassElement enclosingClass) { |
| 2053 try { |
| 2054 Scope outerScope = _visitor.nameScope; |
| 2055 try { |
| 2056 _visitor.enclosingClass = enclosingClass; |
| 2057 EnclosedScope innerScope = new ClassScope( |
| 2058 new TypeParameterScope(outerScope, enclosingClass), enclosingClass); |
| 2059 _visitor.nameScope = innerScope; |
| 2060 node.accept(_resolver); |
| 2061 } finally { |
| 2062 _visitor.enclosingClass = null; |
| 2063 _visitor.nameScope = outerScope; |
| 2064 } |
| 2065 } catch (exception) { |
| 2066 throw new IllegalArgumentException("Could not resolve node", exception); |
| 2067 } |
| 2068 } |
| 2069 |
| 2070 /** |
| 2071 * Return the element associated with the given expression after the resolver
has resolved the |
| 2072 * expression. |
| 2073 * |
| 2074 * @param node the expression to be resolved |
| 2075 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 2076 * being resolved |
| 2077 * @return the element to which the expression was resolved |
| 2078 */ |
| 2079 Element _resolveIndexExpression(IndexExpression node, |
| 2080 [List<Element> definedElements]) { |
| 2081 _resolveNode(node, definedElements); |
| 2082 return node.staticElement; |
| 2083 } |
| 2084 |
| 2085 /** |
| 2086 * Return the element associated with the given identifier after the resolver
has resolved the |
| 2087 * identifier. |
| 2088 * |
| 2089 * @param node the expression to be resolved |
| 2090 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 2091 * being resolved |
| 2092 * @return the element to which the expression was resolved |
| 2093 */ |
| 2094 void _resolveNode(AstNode node, [List<Element> definedElements]) { |
| 2095 try { |
| 2096 Scope outerScope = _visitor.nameScope; |
| 2097 try { |
| 2098 EnclosedScope innerScope = new EnclosedScope(outerScope); |
| 2099 if (definedElements != null) { |
| 2100 for (Element element in definedElements) { |
| 2101 innerScope.define(element); |
| 2102 } |
| 2103 } |
| 2104 _visitor.nameScope = innerScope; |
| 2105 node.accept(_resolver); |
| 2106 } finally { |
| 2107 _visitor.nameScope = outerScope; |
| 2108 } |
| 2109 } catch (exception) { |
| 2110 throw new IllegalArgumentException("Could not resolve node", exception); |
| 2111 } |
| 2112 } |
| 2113 |
| 2114 /** |
| 2115 * Return the element associated with the label of the given statement after t
he resolver has |
| 2116 * resolved the statement. |
| 2117 * |
| 2118 * @param statement the statement to be resolved |
| 2119 * @param labelElement the label element to be defined in the statement's labe
l scope |
| 2120 * @return the element to which the statement's label was resolved |
| 2121 */ |
| 2122 void _resolveStatement( |
| 2123 Statement statement, LabelElementImpl labelElement, AstNode labelTarget) { |
| 2124 try { |
| 2125 LabelScope outerScope = _visitor.labelScope; |
| 2126 try { |
| 2127 LabelScope innerScope; |
| 2128 if (labelElement == null) { |
| 2129 innerScope = outerScope; |
| 2130 } else { |
| 2131 innerScope = new LabelScope( |
| 2132 outerScope, labelElement.name, labelTarget, labelElement); |
| 2133 } |
| 2134 _visitor.labelScope = innerScope; |
| 2135 statement.accept(_resolver); |
| 2136 } finally { |
| 2137 _visitor.labelScope = outerScope; |
| 2138 } |
| 2139 } catch (exception) { |
| 2140 throw new IllegalArgumentException("Could not resolve node", exception); |
| 2141 } |
| 2142 } |
| 2143 } |
| 2144 |
| 2145 @reflectiveTest |
| 2146 class EnclosedScopeTest extends ResolverTestCase { |
| 2147 void test_define_duplicate() { |
| 2148 GatheringErrorListener listener = new GatheringErrorListener(); |
| 2149 Scope rootScope = |
| 2150 new Scope_EnclosedScopeTest_test_define_duplicate(listener); |
| 2151 EnclosedScope scope = new EnclosedScope(rootScope); |
| 2152 VariableElement element1 = |
| 2153 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 2154 VariableElement element2 = |
| 2155 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 2156 scope.define(element1); |
| 2157 scope.define(element2); |
| 2158 listener.assertErrorsWithSeverities([ErrorSeverity.ERROR]); |
| 2159 } |
| 2160 |
| 2161 void test_define_normal() { |
| 2162 GatheringErrorListener listener = new GatheringErrorListener(); |
| 2163 Scope rootScope = new Scope_EnclosedScopeTest_test_define_normal(listener); |
| 2164 EnclosedScope outerScope = new EnclosedScope(rootScope); |
| 2165 EnclosedScope innerScope = new EnclosedScope(outerScope); |
| 2166 VariableElement element1 = |
| 2167 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 2168 VariableElement element2 = |
| 2169 ElementFactory.localVariableElement(AstFactory.identifier3("v2")); |
| 2170 outerScope.define(element1); |
| 2171 innerScope.define(element2); |
| 2172 listener.assertNoErrors(); |
| 2173 } |
| 2174 } |
| 2175 |
| 2176 @reflectiveTest |
| 2177 class ErrorResolverTest extends ResolverTestCase { |
| 2178 void test_breakLabelOnSwitchMember() { |
| 2179 Source source = addSource(r''' |
| 2180 class A { |
| 2181 void m(int i) { |
| 2182 switch (i) { |
| 2183 l: case 0: |
| 2184 break; |
| 2185 case 1: |
| 2186 break l; |
| 2187 } |
| 2188 } |
| 2189 }'''); |
| 2190 computeLibrarySourceErrors(source); |
| 2191 assertErrors(source, [ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER]); |
| 2192 verify([source]); |
| 2193 } |
| 2194 |
| 2195 void test_continueLabelOnSwitch() { |
| 2196 Source source = addSource(r''' |
| 2197 class A { |
| 2198 void m(int i) { |
| 2199 l: switch (i) { |
| 2200 case 0: |
| 2201 continue l; |
| 2202 } |
| 2203 } |
| 2204 }'''); |
| 2205 computeLibrarySourceErrors(source); |
| 2206 assertErrors(source, [ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH]); |
| 2207 verify([source]); |
| 2208 } |
| 2209 |
| 2210 void test_enclosingElement_invalidLocalFunction() { |
| 2211 Source source = addSource(r''' |
| 2212 class C { |
| 2213 C() { |
| 2214 int get x => 0; |
| 2215 } |
| 2216 }'''); |
| 2217 LibraryElement library = resolve2(source); |
| 2218 expect(library, isNotNull); |
| 2219 var unit = library.definingCompilationUnit; |
| 2220 expect(unit, isNotNull); |
| 2221 var types = unit.types; |
| 2222 expect(types, isNotNull); |
| 2223 expect(types, hasLength(1)); |
| 2224 var type = types[0]; |
| 2225 expect(type, isNotNull); |
| 2226 var constructors = type.constructors; |
| 2227 expect(constructors, isNotNull); |
| 2228 expect(constructors, hasLength(1)); |
| 2229 ConstructorElement constructor = constructors[0]; |
| 2230 expect(constructor, isNotNull); |
| 2231 List<FunctionElement> functions = constructor.functions; |
| 2232 expect(functions, isNotNull); |
| 2233 expect(functions, hasLength(1)); |
| 2234 expect(functions[0].enclosingElement, constructor); |
| 2235 assertErrors(source, [ParserErrorCode.GETTER_IN_FUNCTION]); |
| 2236 } |
| 2237 } |
| 2238 |
| 2239 @reflectiveTest |
| 2240 class HintCodeTest extends ResolverTestCase { |
| 2241 void fail_deadCode_statementAfterRehrow() { |
| 2242 Source source = addSource(r''' |
| 2243 f() { |
| 2244 try { |
| 2245 var one = 1; |
| 2246 } catch (e) { |
| 2247 rethrow; |
| 2248 var two = 2; |
| 2249 } |
| 2250 }'''); |
| 2251 computeLibrarySourceErrors(source); |
| 2252 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2253 verify([source]); |
| 2254 } |
| 2255 |
| 2256 void fail_deadCode_statementAfterThrow() { |
| 2257 Source source = addSource(r''' |
| 2258 f() { |
| 2259 var one = 1; |
| 2260 throw 'Stop here'; |
| 2261 var two = 2; |
| 2262 }'''); |
| 2263 computeLibrarySourceErrors(source); |
| 2264 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2265 verify([source]); |
| 2266 } |
| 2267 |
| 2268 void fail_isInt() { |
| 2269 Source source = addSource("var v = 1 is int;"); |
| 2270 computeLibrarySourceErrors(source); |
| 2271 assertErrors(source, [HintCode.IS_INT]); |
| 2272 verify([source]); |
| 2273 } |
| 2274 |
| 2275 void fail_isNotInt() { |
| 2276 Source source = addSource("var v = 1 is! int;"); |
| 2277 computeLibrarySourceErrors(source); |
| 2278 assertErrors(source, [HintCode.IS_NOT_INT]); |
| 2279 verify([source]); |
| 2280 } |
| 2281 |
| 2282 void fail_overrideEqualsButNotHashCode() { |
| 2283 Source source = addSource(r''' |
| 2284 class A { |
| 2285 bool operator ==(x) {} |
| 2286 }'''); |
| 2287 computeLibrarySourceErrors(source); |
| 2288 assertErrors(source, [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE]); |
| 2289 verify([source]); |
| 2290 } |
| 2291 |
| 2292 void fail_unusedImport_as_equalPrefixes() { |
| 2293 // See todo at ImportsVerifier.prefixElementMap. |
| 2294 Source source = addSource(r''' |
| 2295 library L; |
| 2296 import 'lib1.dart' as one; |
| 2297 import 'lib2.dart' as one; |
| 2298 one.A a;'''); |
| 2299 Source source2 = addNamedSource( |
| 2300 "/lib1.dart", |
| 2301 r''' |
| 2302 library lib1; |
| 2303 class A {}'''); |
| 2304 Source source3 = addNamedSource( |
| 2305 "/lib2.dart", |
| 2306 r''' |
| 2307 library lib2; |
| 2308 class B {}'''); |
| 2309 computeLibrarySourceErrors(source); |
| 2310 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 2311 assertNoErrors(source2); |
| 2312 assertNoErrors(source3); |
| 2313 verify([source, source2, source3]); |
| 2314 } |
| 2315 |
| 2316 void test_argumentTypeNotAssignable_functionType() { |
| 2317 Source source = addSource(r''' |
| 2318 m() { |
| 2319 var a = new A(); |
| 2320 a.n(() => 0); |
| 2321 } |
| 2322 class A { |
| 2323 n(void f(int i)) {} |
| 2324 }'''); |
| 2325 computeLibrarySourceErrors(source); |
| 2326 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); |
| 2327 verify([source]); |
| 2328 } |
| 2329 |
| 2330 void test_argumentTypeNotAssignable_message() { |
| 2331 // The implementation of HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE assumes that |
| 2332 // StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE has the same message. |
| 2333 expect(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE.message, |
| 2334 HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE.message); |
| 2335 } |
| 2336 |
| 2337 void test_argumentTypeNotAssignable_type() { |
| 2338 Source source = addSource(r''' |
| 2339 m() { |
| 2340 var i = ''; |
| 2341 n(i); |
| 2342 } |
| 2343 n(int i) {}'''); |
| 2344 computeLibrarySourceErrors(source); |
| 2345 assertErrors(source, [HintCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); |
| 2346 verify([source]); |
| 2347 } |
| 2348 |
| 2349 void test_deadCode_deadBlock_conditionalElse() { |
| 2350 Source source = addSource(r''' |
| 2351 f() { |
| 2352 true ? 1 : 2; |
| 2353 }'''); |
| 2354 computeLibrarySourceErrors(source); |
| 2355 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2356 verify([source]); |
| 2357 } |
| 2358 |
| 2359 void test_deadCode_deadBlock_conditionalElse_nested() { |
| 2360 // test that a dead else-statement can't generate additional violations |
| 2361 Source source = addSource(r''' |
| 2362 f() { |
| 2363 true ? true : false && false; |
| 2364 }'''); |
| 2365 computeLibrarySourceErrors(source); |
| 2366 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2367 verify([source]); |
| 2368 } |
| 2369 |
| 2370 void test_deadCode_deadBlock_conditionalIf() { |
| 2371 Source source = addSource(r''' |
| 2372 f() { |
| 2373 false ? 1 : 2; |
| 2374 }'''); |
| 2375 computeLibrarySourceErrors(source); |
| 2376 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2377 verify([source]); |
| 2378 } |
| 2379 |
| 2380 void test_deadCode_deadBlock_conditionalIf_nested() { |
| 2381 // test that a dead then-statement can't generate additional violations |
| 2382 Source source = addSource(r''' |
| 2383 f() { |
| 2384 false ? false && false : true; |
| 2385 }'''); |
| 2386 computeLibrarySourceErrors(source); |
| 2387 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2388 verify([source]); |
| 2389 } |
| 2390 |
| 2391 void test_deadCode_deadBlock_else() { |
| 2392 Source source = addSource(r''' |
| 2393 f() { |
| 2394 if(true) {} else {} |
| 2395 }'''); |
| 2396 computeLibrarySourceErrors(source); |
| 2397 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2398 verify([source]); |
| 2399 } |
| 2400 |
| 2401 void test_deadCode_deadBlock_else_nested() { |
| 2402 // test that a dead else-statement can't generate additional violations |
| 2403 Source source = addSource(r''' |
| 2404 f() { |
| 2405 if(true) {} else {if (false) {}} |
| 2406 }'''); |
| 2407 computeLibrarySourceErrors(source); |
| 2408 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2409 verify([source]); |
| 2410 } |
| 2411 |
| 2412 void test_deadCode_deadBlock_if() { |
| 2413 Source source = addSource(r''' |
| 2414 f() { |
| 2415 if(false) {} |
| 2416 }'''); |
| 2417 computeLibrarySourceErrors(source); |
| 2418 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2419 verify([source]); |
| 2420 } |
| 2421 |
| 2422 void test_deadCode_deadBlock_if_nested() { |
| 2423 // test that a dead then-statement can't generate additional violations |
| 2424 Source source = addSource(r''' |
| 2425 f() { |
| 2426 if(false) {if(false) {}} |
| 2427 }'''); |
| 2428 computeLibrarySourceErrors(source); |
| 2429 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2430 verify([source]); |
| 2431 } |
| 2432 |
| 2433 void test_deadCode_deadBlock_while() { |
| 2434 Source source = addSource(r''' |
| 2435 f() { |
| 2436 while(false) {} |
| 2437 }'''); |
| 2438 computeLibrarySourceErrors(source); |
| 2439 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2440 verify([source]); |
| 2441 } |
| 2442 |
| 2443 void test_deadCode_deadBlock_while_nested() { |
| 2444 // test that a dead while body can't generate additional violations |
| 2445 Source source = addSource(r''' |
| 2446 f() { |
| 2447 while(false) {if(false) {}} |
| 2448 }'''); |
| 2449 computeLibrarySourceErrors(source); |
| 2450 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2451 verify([source]); |
| 2452 } |
| 2453 |
| 2454 void test_deadCode_deadCatch_catchFollowingCatch() { |
| 2455 Source source = addSource(r''' |
| 2456 class A {} |
| 2457 f() { |
| 2458 try {} catch (e) {} catch (e) {} |
| 2459 }'''); |
| 2460 computeLibrarySourceErrors(source); |
| 2461 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); |
| 2462 verify([source]); |
| 2463 } |
| 2464 |
| 2465 void test_deadCode_deadCatch_catchFollowingCatch_nested() { |
| 2466 // test that a dead catch clause can't generate additional violations |
| 2467 Source source = addSource(r''' |
| 2468 class A {} |
| 2469 f() { |
| 2470 try {} catch (e) {} catch (e) {if(false) {}} |
| 2471 }'''); |
| 2472 computeLibrarySourceErrors(source); |
| 2473 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); |
| 2474 verify([source]); |
| 2475 } |
| 2476 |
| 2477 void test_deadCode_deadCatch_catchFollowingCatch_object() { |
| 2478 Source source = addSource(r''' |
| 2479 f() { |
| 2480 try {} on Object catch (e) {} catch (e) {} |
| 2481 }'''); |
| 2482 computeLibrarySourceErrors(source); |
| 2483 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); |
| 2484 verify([source]); |
| 2485 } |
| 2486 |
| 2487 void test_deadCode_deadCatch_catchFollowingCatch_object_nested() { |
| 2488 // test that a dead catch clause can't generate additional violations |
| 2489 Source source = addSource(r''' |
| 2490 f() { |
| 2491 try {} on Object catch (e) {} catch (e) {if(false) {}} |
| 2492 }'''); |
| 2493 computeLibrarySourceErrors(source); |
| 2494 assertErrors(source, [HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH]); |
| 2495 verify([source]); |
| 2496 } |
| 2497 |
| 2498 void test_deadCode_deadCatch_onCatchSubtype() { |
| 2499 Source source = addSource(r''' |
| 2500 class A {} |
| 2501 class B extends A {} |
| 2502 f() { |
| 2503 try {} on A catch (e) {} on B catch (e) {} |
| 2504 }'''); |
| 2505 computeLibrarySourceErrors(source); |
| 2506 assertErrors(source, [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]); |
| 2507 verify([source]); |
| 2508 } |
| 2509 |
| 2510 void test_deadCode_deadCatch_onCatchSubtype_nested() { |
| 2511 // test that a dead catch clause can't generate additional violations |
| 2512 Source source = addSource(r''' |
| 2513 class A {} |
| 2514 class B extends A {} |
| 2515 f() { |
| 2516 try {} on A catch (e) {} on B catch (e) {if(false) {}} |
| 2517 }'''); |
| 2518 computeLibrarySourceErrors(source); |
| 2519 assertErrors(source, [HintCode.DEAD_CODE_ON_CATCH_SUBTYPE]); |
| 2520 verify([source]); |
| 2521 } |
| 2522 |
| 2523 void test_deadCode_deadOperandLHS_and() { |
| 2524 Source source = addSource(r''' |
| 2525 f() { |
| 2526 bool b = false && false; |
| 2527 }'''); |
| 2528 computeLibrarySourceErrors(source); |
| 2529 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2530 verify([source]); |
| 2531 } |
| 2532 |
| 2533 void test_deadCode_deadOperandLHS_and_nested() { |
| 2534 Source source = addSource(r''' |
| 2535 f() { |
| 2536 bool b = false && (false && false); |
| 2537 }'''); |
| 2538 computeLibrarySourceErrors(source); |
| 2539 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2540 verify([source]); |
| 2541 } |
| 2542 |
| 2543 void test_deadCode_deadOperandLHS_or() { |
| 2544 Source source = addSource(r''' |
| 2545 f() { |
| 2546 bool b = true || true; |
| 2547 }'''); |
| 2548 computeLibrarySourceErrors(source); |
| 2549 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2550 verify([source]); |
| 2551 } |
| 2552 |
| 2553 void test_deadCode_deadOperandLHS_or_nested() { |
| 2554 Source source = addSource(r''' |
| 2555 f() { |
| 2556 bool b = true || (false && false); |
| 2557 }'''); |
| 2558 computeLibrarySourceErrors(source); |
| 2559 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2560 verify([source]); |
| 2561 } |
| 2562 |
| 2563 void test_deadCode_statementAfterBreak_inDefaultCase() { |
| 2564 Source source = addSource(r''' |
| 2565 f(v) { |
| 2566 switch(v) { |
| 2567 case 1: |
| 2568 default: |
| 2569 break; |
| 2570 var a; |
| 2571 } |
| 2572 }'''); |
| 2573 computeLibrarySourceErrors(source); |
| 2574 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2575 verify([source]); |
| 2576 } |
| 2577 |
| 2578 void test_deadCode_statementAfterBreak_inForEachStatement() { |
| 2579 Source source = addSource(r''' |
| 2580 f() { |
| 2581 var list; |
| 2582 for(var l in list) { |
| 2583 break; |
| 2584 var a; |
| 2585 } |
| 2586 }'''); |
| 2587 computeLibrarySourceErrors(source); |
| 2588 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2589 verify([source]); |
| 2590 } |
| 2591 |
| 2592 void test_deadCode_statementAfterBreak_inForStatement() { |
| 2593 Source source = addSource(r''' |
| 2594 f() { |
| 2595 for(;;) { |
| 2596 break; |
| 2597 var a; |
| 2598 } |
| 2599 }'''); |
| 2600 computeLibrarySourceErrors(source); |
| 2601 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2602 verify([source]); |
| 2603 } |
| 2604 |
| 2605 void test_deadCode_statementAfterBreak_inSwitchCase() { |
| 2606 Source source = addSource(r''' |
| 2607 f(v) { |
| 2608 switch(v) { |
| 2609 case 1: |
| 2610 break; |
| 2611 var a; |
| 2612 } |
| 2613 }'''); |
| 2614 computeLibrarySourceErrors(source); |
| 2615 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2616 verify([source]); |
| 2617 } |
| 2618 |
| 2619 void test_deadCode_statementAfterBreak_inWhileStatement() { |
| 2620 Source source = addSource(r''' |
| 2621 f(v) { |
| 2622 while(v) { |
| 2623 break; |
| 2624 var a; |
| 2625 } |
| 2626 }'''); |
| 2627 computeLibrarySourceErrors(source); |
| 2628 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2629 verify([source]); |
| 2630 } |
| 2631 |
| 2632 void test_deadCode_statementAfterContinue_inForEachStatement() { |
| 2633 Source source = addSource(r''' |
| 2634 f() { |
| 2635 var list; |
| 2636 for(var l in list) { |
| 2637 continue; |
| 2638 var a; |
| 2639 } |
| 2640 }'''); |
| 2641 computeLibrarySourceErrors(source); |
| 2642 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2643 verify([source]); |
| 2644 } |
| 2645 |
| 2646 void test_deadCode_statementAfterContinue_inForStatement() { |
| 2647 Source source = addSource(r''' |
| 2648 f() { |
| 2649 for(;;) { |
| 2650 continue; |
| 2651 var a; |
| 2652 } |
| 2653 }'''); |
| 2654 computeLibrarySourceErrors(source); |
| 2655 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2656 verify([source]); |
| 2657 } |
| 2658 |
| 2659 void test_deadCode_statementAfterContinue_inWhileStatement() { |
| 2660 Source source = addSource(r''' |
| 2661 f(v) { |
| 2662 while(v) { |
| 2663 continue; |
| 2664 var a; |
| 2665 } |
| 2666 }'''); |
| 2667 computeLibrarySourceErrors(source); |
| 2668 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2669 verify([source]); |
| 2670 } |
| 2671 |
| 2672 void test_deadCode_statementAfterReturn_function() { |
| 2673 Source source = addSource(r''' |
| 2674 f() { |
| 2675 var one = 1; |
| 2676 return; |
| 2677 var two = 2; |
| 2678 }'''); |
| 2679 computeLibrarySourceErrors(source); |
| 2680 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2681 verify([source]); |
| 2682 } |
| 2683 |
| 2684 void test_deadCode_statementAfterReturn_ifStatement() { |
| 2685 Source source = addSource(r''' |
| 2686 f(bool b) { |
| 2687 if(b) { |
| 2688 var one = 1; |
| 2689 return; |
| 2690 var two = 2; |
| 2691 } |
| 2692 }'''); |
| 2693 computeLibrarySourceErrors(source); |
| 2694 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2695 verify([source]); |
| 2696 } |
| 2697 |
| 2698 void test_deadCode_statementAfterReturn_method() { |
| 2699 Source source = addSource(r''' |
| 2700 class A { |
| 2701 m() { |
| 2702 var one = 1; |
| 2703 return; |
| 2704 var two = 2; |
| 2705 } |
| 2706 }'''); |
| 2707 computeLibrarySourceErrors(source); |
| 2708 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2709 verify([source]); |
| 2710 } |
| 2711 |
| 2712 void test_deadCode_statementAfterReturn_nested() { |
| 2713 Source source = addSource(r''' |
| 2714 f() { |
| 2715 var one = 1; |
| 2716 return; |
| 2717 if(false) {} |
| 2718 }'''); |
| 2719 computeLibrarySourceErrors(source); |
| 2720 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2721 verify([source]); |
| 2722 } |
| 2723 |
| 2724 void test_deadCode_statementAfterReturn_twoReturns() { |
| 2725 Source source = addSource(r''' |
| 2726 f() { |
| 2727 var one = 1; |
| 2728 return; |
| 2729 var two = 2; |
| 2730 return; |
| 2731 var three = 3; |
| 2732 }'''); |
| 2733 computeLibrarySourceErrors(source); |
| 2734 assertErrors(source, [HintCode.DEAD_CODE]); |
| 2735 verify([source]); |
| 2736 } |
| 2737 |
| 2738 void test_deprecatedAnnotationUse_assignment() { |
| 2739 Source source = addSource(r''' |
| 2740 class A { |
| 2741 @deprecated |
| 2742 A operator+(A a) { return a; } |
| 2743 } |
| 2744 f(A a) { |
| 2745 A b; |
| 2746 a += b; |
| 2747 }'''); |
| 2748 computeLibrarySourceErrors(source); |
| 2749 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2750 verify([source]); |
| 2751 } |
| 2752 |
| 2753 void test_deprecatedAnnotationUse_Deprecated() { |
| 2754 Source source = addSource(r''' |
| 2755 class A { |
| 2756 @Deprecated('0.9') |
| 2757 m() {} |
| 2758 n() {m();} |
| 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 |
| 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_export() { |
| 2778 Source source = addSource("export 'deprecated_library.dart';"); |
| 2779 addNamedSource( |
| 2780 "/deprecated_library.dart", |
| 2781 r''' |
| 2782 @deprecated |
| 2783 library deprecated_library; |
| 2784 class A {}'''); |
| 2785 computeLibrarySourceErrors(source); |
| 2786 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2787 verify([source]); |
| 2788 } |
| 2789 |
| 2790 void test_deprecatedAnnotationUse_getter() { |
| 2791 Source source = addSource(r''' |
| 2792 class A { |
| 2793 @deprecated |
| 2794 get m => 1; |
| 2795 } |
| 2796 f(A a) { |
| 2797 return a.m; |
| 2798 }'''); |
| 2799 computeLibrarySourceErrors(source); |
| 2800 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2801 verify([source]); |
| 2802 } |
| 2803 |
| 2804 void test_deprecatedAnnotationUse_import() { |
| 2805 Source source = addSource(r''' |
| 2806 import 'deprecated_library.dart'; |
| 2807 f(A a) {}'''); |
| 2808 addNamedSource( |
| 2809 "/deprecated_library.dart", |
| 2810 r''' |
| 2811 @deprecated |
| 2812 library deprecated_library; |
| 2813 class A {}'''); |
| 2814 computeLibrarySourceErrors(source); |
| 2815 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2816 verify([source]); |
| 2817 } |
| 2818 |
| 2819 void test_deprecatedAnnotationUse_indexExpression() { |
| 2820 Source source = addSource(r''' |
| 2821 class A { |
| 2822 @deprecated |
| 2823 operator[](int i) {} |
| 2824 } |
| 2825 f(A a) { |
| 2826 return a[1]; |
| 2827 }'''); |
| 2828 computeLibrarySourceErrors(source); |
| 2829 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2830 verify([source]); |
| 2831 } |
| 2832 |
| 2833 void test_deprecatedAnnotationUse_instanceCreation() { |
| 2834 Source source = addSource(r''' |
| 2835 class A { |
| 2836 @deprecated |
| 2837 A(int i) {} |
| 2838 } |
| 2839 f() { |
| 2840 A a = new A(1); |
| 2841 }'''); |
| 2842 computeLibrarySourceErrors(source); |
| 2843 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2844 verify([source]); |
| 2845 } |
| 2846 |
| 2847 void test_deprecatedAnnotationUse_instanceCreation_namedConstructor() { |
| 2848 Source source = addSource(r''' |
| 2849 class A { |
| 2850 @deprecated |
| 2851 A.named(int i) {} |
| 2852 } |
| 2853 f() { |
| 2854 A a = new A.named(1); |
| 2855 }'''); |
| 2856 computeLibrarySourceErrors(source); |
| 2857 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2858 verify([source]); |
| 2859 } |
| 2860 |
| 2861 void test_deprecatedAnnotationUse_operator() { |
| 2862 Source source = addSource(r''' |
| 2863 class A { |
| 2864 @deprecated |
| 2865 operator+(A a) {} |
| 2866 } |
| 2867 f(A a) { |
| 2868 A b; |
| 2869 return a + b; |
| 2870 }'''); |
| 2871 computeLibrarySourceErrors(source); |
| 2872 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2873 verify([source]); |
| 2874 } |
| 2875 |
| 2876 void test_deprecatedAnnotationUse_setter() { |
| 2877 Source source = addSource(r''' |
| 2878 class A { |
| 2879 @deprecated |
| 2880 set s(v) {} |
| 2881 } |
| 2882 f(A a) { |
| 2883 return a.s = 1; |
| 2884 }'''); |
| 2885 computeLibrarySourceErrors(source); |
| 2886 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2887 verify([source]); |
| 2888 } |
| 2889 |
| 2890 void test_deprecatedAnnotationUse_superConstructor() { |
| 2891 Source source = addSource(r''' |
| 2892 class A { |
| 2893 @deprecated |
| 2894 A() {} |
| 2895 } |
| 2896 class B extends A { |
| 2897 B() : super() {} |
| 2898 }'''); |
| 2899 computeLibrarySourceErrors(source); |
| 2900 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2901 verify([source]); |
| 2902 } |
| 2903 |
| 2904 void test_deprecatedAnnotationUse_superConstructor_namedConstructor() { |
| 2905 Source source = addSource(r''' |
| 2906 class A { |
| 2907 @deprecated |
| 2908 A.named() {} |
| 2909 } |
| 2910 class B extends A { |
| 2911 B() : super.named() {} |
| 2912 }'''); |
| 2913 computeLibrarySourceErrors(source); |
| 2914 assertErrors(source, [HintCode.DEPRECATED_MEMBER_USE]); |
| 2915 verify([source]); |
| 2916 } |
| 2917 |
| 2918 void test_divisionOptimization_double() { |
| 2919 Source source = addSource(r''' |
| 2920 f(double x, double y) { |
| 2921 var v = (x / y).toInt(); |
| 2922 }'''); |
| 2923 computeLibrarySourceErrors(source); |
| 2924 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); |
| 2925 verify([source]); |
| 2926 } |
| 2927 |
| 2928 void test_divisionOptimization_int() { |
| 2929 Source source = addSource(r''' |
| 2930 f(int x, int y) { |
| 2931 var v = (x / y).toInt(); |
| 2932 }'''); |
| 2933 computeLibrarySourceErrors(source); |
| 2934 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); |
| 2935 verify([source]); |
| 2936 } |
| 2937 |
| 2938 void test_divisionOptimization_propagatedType() { |
| 2939 // Tests the propagated type information of the '/' method |
| 2940 Source source = addSource(r''' |
| 2941 f(x, y) { |
| 2942 x = 1; |
| 2943 y = 1; |
| 2944 var v = (x / y).toInt(); |
| 2945 }'''); |
| 2946 computeLibrarySourceErrors(source); |
| 2947 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); |
| 2948 verify([source]); |
| 2949 } |
| 2950 |
| 2951 void test_divisionOptimization_wrappedBinaryExpression() { |
| 2952 Source source = addSource(r''' |
| 2953 f(int x, int y) { |
| 2954 var v = (((x / y))).toInt(); |
| 2955 }'''); |
| 2956 computeLibrarySourceErrors(source); |
| 2957 assertErrors(source, [HintCode.DIVISION_OPTIMIZATION]); |
| 2958 verify([source]); |
| 2959 } |
| 2960 |
| 2961 void test_duplicateImport() { |
| 2962 Source source = addSource(r''' |
| 2963 library L; |
| 2964 import 'lib1.dart'; |
| 2965 import 'lib1.dart'; |
| 2966 A a;'''); |
| 2967 addNamedSource( |
| 2968 "/lib1.dart", |
| 2969 r''' |
| 2970 library lib1; |
| 2971 class A {}'''); |
| 2972 computeLibrarySourceErrors(source); |
| 2973 assertErrors(source, [HintCode.DUPLICATE_IMPORT]); |
| 2974 verify([source]); |
| 2975 } |
| 2976 |
| 2977 void test_duplicateImport2() { |
| 2978 Source source = addSource(r''' |
| 2979 library L; |
| 2980 import 'lib1.dart'; |
| 2981 import 'lib1.dart'; |
| 2982 import 'lib1.dart'; |
| 2983 A a;'''); |
| 2984 addNamedSource( |
| 2985 "/lib1.dart", |
| 2986 r''' |
| 2987 library lib1; |
| 2988 class A {}'''); |
| 2989 computeLibrarySourceErrors(source); |
| 2990 assertErrors( |
| 2991 source, [HintCode.DUPLICATE_IMPORT, HintCode.DUPLICATE_IMPORT]); |
| 2992 verify([source]); |
| 2993 } |
| 2994 |
| 2995 void test_duplicateImport3() { |
| 2996 Source source = addSource(r''' |
| 2997 library L; |
| 2998 import 'lib1.dart' as M show A hide B; |
| 2999 import 'lib1.dart' as M show A hide B; |
| 3000 M.A a;'''); |
| 3001 addNamedSource( |
| 3002 "/lib1.dart", |
| 3003 r''' |
| 3004 library lib1; |
| 3005 class A {} |
| 3006 class B {}'''); |
| 3007 computeLibrarySourceErrors(source); |
| 3008 assertErrors(source, [HintCode.DUPLICATE_IMPORT]); |
| 3009 verify([source]); |
| 3010 } |
| 3011 |
| 3012 void test_importDeferredLibraryWithLoadFunction() { |
| 3013 resolveWithErrors(<String>[ |
| 3014 r''' |
| 3015 library lib1; |
| 3016 loadLibrary() {} |
| 3017 f() {}''', |
| 3018 r''' |
| 3019 library root; |
| 3020 import 'lib1.dart' deferred as lib1; |
| 3021 main() { lib1.f(); }''' |
| 3022 ], <ErrorCode>[ |
| 3023 HintCode.IMPORT_DEFERRED_LIBRARY_WITH_LOAD_FUNCTION |
| 3024 ]); |
| 3025 } |
| 3026 |
| 3027 void test_invalidAssignment_instanceVariable() { |
| 3028 Source source = addSource(r''' |
| 3029 class A { |
| 3030 int x; |
| 3031 } |
| 3032 f(var y) { |
| 3033 A a; |
| 3034 if(y is String) { |
| 3035 a.x = y; |
| 3036 } |
| 3037 }'''); |
| 3038 computeLibrarySourceErrors(source); |
| 3039 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 3040 verify([source]); |
| 3041 } |
| 3042 |
| 3043 void test_invalidAssignment_localVariable() { |
| 3044 Source source = addSource(r''' |
| 3045 f(var y) { |
| 3046 if(y is String) { |
| 3047 int x = y; |
| 3048 } |
| 3049 }'''); |
| 3050 computeLibrarySourceErrors(source); |
| 3051 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 3052 verify([source]); |
| 3053 } |
| 3054 |
| 3055 void test_invalidAssignment_message() { |
| 3056 // The implementation of HintCode.INVALID_ASSIGNMENT assumes that |
| 3057 // StaticTypeWarningCode.INVALID_ASSIGNMENT has the same message. |
| 3058 expect(StaticTypeWarningCode.INVALID_ASSIGNMENT.message, |
| 3059 HintCode.INVALID_ASSIGNMENT.message); |
| 3060 } |
| 3061 |
| 3062 void test_invalidAssignment_staticVariable() { |
| 3063 Source source = addSource(r''' |
| 3064 class A { |
| 3065 static int x; |
| 3066 } |
| 3067 f(var y) { |
| 3068 if(y is String) { |
| 3069 A.x = y; |
| 3070 } |
| 3071 }'''); |
| 3072 computeLibrarySourceErrors(source); |
| 3073 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 3074 verify([source]); |
| 3075 } |
| 3076 |
| 3077 void test_invalidAssignment_variableDeclaration() { |
| 3078 // 17971 |
| 3079 Source source = addSource(r''' |
| 3080 class Point { |
| 3081 final num x, y; |
| 3082 Point(this.x, this.y); |
| 3083 Point operator +(Point other) { |
| 3084 return new Point(x+other.x, y+other.y); |
| 3085 } |
| 3086 } |
| 3087 main() { |
| 3088 var p1 = new Point(0, 0); |
| 3089 var p2 = new Point(10, 10); |
| 3090 int n = p1 + p2; |
| 3091 }'''); |
| 3092 computeLibrarySourceErrors(source); |
| 3093 assertErrors(source, [HintCode.INVALID_ASSIGNMENT]); |
| 3094 verify([source]); |
| 3095 } |
| 3096 |
| 3097 void test_isDouble() { |
| 3098 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 3099 options.dart2jsHint = true; |
| 3100 resetWithOptions(options); |
| 3101 Source source = addSource("var v = 1 is double;"); |
| 3102 computeLibrarySourceErrors(source); |
| 3103 assertErrors(source, [HintCode.IS_DOUBLE]); |
| 3104 verify([source]); |
| 3105 } |
| 3106 |
| 3107 void test_isNotDouble() { |
| 3108 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 3109 options.dart2jsHint = true; |
| 3110 resetWithOptions(options); |
| 3111 Source source = addSource("var v = 1 is! double;"); |
| 3112 computeLibrarySourceErrors(source); |
| 3113 assertErrors(source, [HintCode.IS_NOT_DOUBLE]); |
| 3114 verify([source]); |
| 3115 } |
| 3116 |
| 3117 void test_missingReturn_async() { |
| 3118 Source source = addSource(''' |
| 3119 import 'dart:async'; |
| 3120 Future<int> f() async {} |
| 3121 '''); |
| 3122 computeLibrarySourceErrors(source); |
| 3123 assertErrors(source, [HintCode.MISSING_RETURN]); |
| 3124 verify([source]); |
| 3125 } |
| 3126 |
| 3127 void test_missingReturn_function() { |
| 3128 Source source = addSource("int f() {}"); |
| 3129 computeLibrarySourceErrors(source); |
| 3130 assertErrors(source, [HintCode.MISSING_RETURN]); |
| 3131 verify([source]); |
| 3132 } |
| 3133 |
| 3134 void test_missingReturn_method() { |
| 3135 Source source = addSource(r''' |
| 3136 class A { |
| 3137 int m() {} |
| 3138 }'''); |
| 3139 computeLibrarySourceErrors(source); |
| 3140 assertErrors(source, [HintCode.MISSING_RETURN]); |
| 3141 verify([source]); |
| 3142 } |
| 3143 |
| 3144 void test_overrideOnNonOverridingGetter_invalid() { |
| 3145 Source source = addSource(r''' |
| 3146 library dart.core; |
| 3147 const override = null; |
| 3148 class A { |
| 3149 } |
| 3150 class B extends A { |
| 3151 @override |
| 3152 int get m => 1; |
| 3153 }'''); |
| 3154 computeLibrarySourceErrors(source); |
| 3155 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER]); |
| 3156 verify([source]); |
| 3157 } |
| 3158 |
| 3159 void test_overrideOnNonOverridingMethod_invalid() { |
| 3160 Source source = addSource(r''' |
| 3161 library dart.core; |
| 3162 const override = null; |
| 3163 class A { |
| 3164 } |
| 3165 class B extends A { |
| 3166 @override |
| 3167 int m() => 1; |
| 3168 }'''); |
| 3169 computeLibrarySourceErrors(source); |
| 3170 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD]); |
| 3171 verify([source]); |
| 3172 } |
| 3173 |
| 3174 void test_overrideOnNonOverridingSetter_invalid() { |
| 3175 Source source = addSource(r''' |
| 3176 library dart.core; |
| 3177 const override = null; |
| 3178 class A { |
| 3179 } |
| 3180 class B extends A { |
| 3181 @override |
| 3182 set m(int x) {} |
| 3183 }'''); |
| 3184 computeLibrarySourceErrors(source); |
| 3185 assertErrors(source, [HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER]); |
| 3186 verify([source]); |
| 3187 } |
| 3188 |
| 3189 void test_typeCheck_type_is_Null() { |
| 3190 Source source = addSource(r''' |
| 3191 m(i) { |
| 3192 bool b = i is Null; |
| 3193 }'''); |
| 3194 computeLibrarySourceErrors(source); |
| 3195 assertErrors(source, [HintCode.TYPE_CHECK_IS_NULL]); |
| 3196 verify([source]); |
| 3197 } |
| 3198 |
| 3199 void test_typeCheck_type_not_Null() { |
| 3200 Source source = addSource(r''' |
| 3201 m(i) { |
| 3202 bool b = i is! Null; |
| 3203 }'''); |
| 3204 computeLibrarySourceErrors(source); |
| 3205 assertErrors(source, [HintCode.TYPE_CHECK_IS_NOT_NULL]); |
| 3206 verify([source]); |
| 3207 } |
| 3208 |
| 3209 void test_undefinedGetter() { |
| 3210 Source source = addSource(r''' |
| 3211 class A {} |
| 3212 f(var a) { |
| 3213 if(a is A) { |
| 3214 return a.m; |
| 3215 } |
| 3216 }'''); |
| 3217 computeLibrarySourceErrors(source); |
| 3218 assertErrors(source, [HintCode.UNDEFINED_GETTER]); |
| 3219 } |
| 3220 |
| 3221 void test_undefinedGetter_message() { |
| 3222 // The implementation of HintCode.UNDEFINED_SETTER assumes that |
| 3223 // UNDEFINED_SETTER in StaticTypeWarningCode and StaticWarningCode are the |
| 3224 // same, this verifies that assumption. |
| 3225 expect(StaticWarningCode.UNDEFINED_GETTER.message, |
| 3226 StaticTypeWarningCode.UNDEFINED_GETTER.message); |
| 3227 } |
| 3228 |
| 3229 void test_undefinedMethod() { |
| 3230 Source source = addSource(r''' |
| 3231 f() { |
| 3232 var a = 'str'; |
| 3233 a.notAMethodOnString(); |
| 3234 }'''); |
| 3235 computeLibrarySourceErrors(source); |
| 3236 assertErrors(source, [HintCode.UNDEFINED_METHOD]); |
| 3237 } |
| 3238 |
| 3239 void test_undefinedMethod_assignmentExpression() { |
| 3240 Source source = addSource(r''' |
| 3241 class A {} |
| 3242 class B { |
| 3243 f(var a, var a2) { |
| 3244 a = new A(); |
| 3245 a2 = new A(); |
| 3246 a += a2; |
| 3247 } |
| 3248 }'''); |
| 3249 computeLibrarySourceErrors(source); |
| 3250 assertErrors(source, [HintCode.UNDEFINED_METHOD]); |
| 3251 } |
| 3252 |
| 3253 void test_undefinedOperator_binaryExpression() { |
| 3254 Source source = addSource(r''' |
| 3255 class A {} |
| 3256 f(var a) { |
| 3257 if(a is A) { |
| 3258 a + 1; |
| 3259 } |
| 3260 }'''); |
| 3261 computeLibrarySourceErrors(source); |
| 3262 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3263 } |
| 3264 |
| 3265 void test_undefinedOperator_indexBoth() { |
| 3266 Source source = addSource(r''' |
| 3267 class A {} |
| 3268 f(var a) { |
| 3269 if(a is A) { |
| 3270 a[0]++; |
| 3271 } |
| 3272 }'''); |
| 3273 computeLibrarySourceErrors(source); |
| 3274 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3275 } |
| 3276 |
| 3277 void test_undefinedOperator_indexGetter() { |
| 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_indexSetter() { |
| 3290 Source source = addSource(r''' |
| 3291 class A {} |
| 3292 f(var a) { |
| 3293 if(a is A) { |
| 3294 a[0] = 1; |
| 3295 } |
| 3296 }'''); |
| 3297 computeLibrarySourceErrors(source); |
| 3298 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3299 } |
| 3300 |
| 3301 void test_undefinedOperator_postfixExpression() { |
| 3302 Source source = addSource(r''' |
| 3303 class A {} |
| 3304 f(var a) { |
| 3305 if(a is A) { |
| 3306 a++; |
| 3307 } |
| 3308 }'''); |
| 3309 computeLibrarySourceErrors(source); |
| 3310 assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); |
| 3311 } |
| 3312 |
| 3313 void test_undefinedOperator_prefixExpression() { |
| 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_undefinedSetter() { |
| 3326 Source source = addSource(r''' |
| 3327 class A {} |
| 3328 f(var a) { |
| 3329 if(a is A) { |
| 3330 a.m = 0; |
| 3331 } |
| 3332 }'''); |
| 3333 computeLibrarySourceErrors(source); |
| 3334 assertErrors(source, [HintCode.UNDEFINED_SETTER]); |
| 3335 } |
| 3336 |
| 3337 void test_undefinedSetter_message() { |
| 3338 // The implementation of HintCode.UNDEFINED_SETTER assumes that |
| 3339 // UNDEFINED_SETTER in StaticTypeWarningCode and StaticWarningCode are the |
| 3340 // same, this verifies that assumption. |
| 3341 expect(StaticWarningCode.UNDEFINED_SETTER.message, |
| 3342 StaticTypeWarningCode.UNDEFINED_SETTER.message); |
| 3343 } |
| 3344 |
| 3345 void test_unnecessaryCast_type_supertype() { |
| 3346 Source source = addSource(r''' |
| 3347 m(int i) { |
| 3348 var b = i as Object; |
| 3349 }'''); |
| 3350 computeLibrarySourceErrors(source); |
| 3351 assertErrors(source, [HintCode.UNNECESSARY_CAST]); |
| 3352 verify([source]); |
| 3353 } |
| 3354 |
| 3355 void test_unnecessaryCast_type_type() { |
| 3356 Source source = addSource(r''' |
| 3357 m(num i) { |
| 3358 var b = i as num; |
| 3359 }'''); |
| 3360 computeLibrarySourceErrors(source); |
| 3361 assertErrors(source, [HintCode.UNNECESSARY_CAST]); |
| 3362 verify([source]); |
| 3363 } |
| 3364 |
| 3365 void test_unnecessaryTypeCheck_null_is_Null() { |
| 3366 Source source = addSource("bool b = null is Null;"); |
| 3367 computeLibrarySourceErrors(source); |
| 3368 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); |
| 3369 verify([source]); |
| 3370 } |
| 3371 |
| 3372 void test_unnecessaryTypeCheck_null_not_Null() { |
| 3373 Source source = addSource("bool b = null is! Null;"); |
| 3374 computeLibrarySourceErrors(source); |
| 3375 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); |
| 3376 verify([source]); |
| 3377 } |
| 3378 |
| 3379 void test_unnecessaryTypeCheck_type_is_dynamic() { |
| 3380 Source source = addSource(r''' |
| 3381 m(i) { |
| 3382 bool b = i is dynamic; |
| 3383 }'''); |
| 3384 computeLibrarySourceErrors(source); |
| 3385 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); |
| 3386 verify([source]); |
| 3387 } |
| 3388 |
| 3389 void test_unnecessaryTypeCheck_type_is_object() { |
| 3390 Source source = addSource(r''' |
| 3391 m(i) { |
| 3392 bool b = i is Object; |
| 3393 }'''); |
| 3394 computeLibrarySourceErrors(source); |
| 3395 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]); |
| 3396 verify([source]); |
| 3397 } |
| 3398 |
| 3399 void test_unnecessaryTypeCheck_type_not_dynamic() { |
| 3400 Source source = addSource(r''' |
| 3401 m(i) { |
| 3402 bool b = i is! dynamic; |
| 3403 }'''); |
| 3404 computeLibrarySourceErrors(source); |
| 3405 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); |
| 3406 verify([source]); |
| 3407 } |
| 3408 |
| 3409 void test_unnecessaryTypeCheck_type_not_object() { |
| 3410 Source source = addSource(r''' |
| 3411 m(i) { |
| 3412 bool b = i is! Object; |
| 3413 }'''); |
| 3414 computeLibrarySourceErrors(source); |
| 3415 assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]); |
| 3416 verify([source]); |
| 3417 } |
| 3418 |
| 3419 void test_unusedElement_class_isUsed_extends() { |
| 3420 enableUnusedElement = true; |
| 3421 Source source = addSource(r''' |
| 3422 class _A {} |
| 3423 class B extends _A {} |
| 3424 '''); |
| 3425 computeLibrarySourceErrors(source); |
| 3426 assertNoErrors(source); |
| 3427 verify([source]); |
| 3428 } |
| 3429 |
| 3430 void test_unusedElement_class_isUsed_implements() { |
| 3431 enableUnusedElement = true; |
| 3432 Source source = addSource(r''' |
| 3433 class _A {} |
| 3434 class B implements _A {} |
| 3435 '''); |
| 3436 computeLibrarySourceErrors(source); |
| 3437 assertNoErrors(source); |
| 3438 verify([source]); |
| 3439 } |
| 3440 |
| 3441 void test_unusedElement_class_isUsed_instanceCreation() { |
| 3442 enableUnusedElement = true; |
| 3443 Source source = addSource(r''' |
| 3444 class _A {} |
| 3445 main() { |
| 3446 new _A(); |
| 3447 }'''); |
| 3448 computeLibrarySourceErrors(source); |
| 3449 assertNoErrors(source); |
| 3450 verify([source]); |
| 3451 } |
| 3452 |
| 3453 void test_unusedElement_class_isUsed_staticFieldAccess() { |
| 3454 enableUnusedElement = true; |
| 3455 Source source = addSource(r''' |
| 3456 class _A { |
| 3457 static const F = 42; |
| 3458 } |
| 3459 main() { |
| 3460 _A.F; |
| 3461 }'''); |
| 3462 computeLibrarySourceErrors(source); |
| 3463 assertNoErrors(source); |
| 3464 verify([source]); |
| 3465 } |
| 3466 |
| 3467 void test_unusedElement_class_isUsed_staticMethodInvocation() { |
| 3468 enableUnusedElement = true; |
| 3469 Source source = addSource(r''' |
| 3470 class _A { |
| 3471 static m() {} |
| 3472 } |
| 3473 main() { |
| 3474 _A.m(); |
| 3475 }'''); |
| 3476 computeLibrarySourceErrors(source); |
| 3477 assertNoErrors(source); |
| 3478 verify([source]); |
| 3479 } |
| 3480 |
| 3481 void test_unusedElement_class_isUsed_typeArgument() { |
| 3482 enableUnusedElement = true; |
| 3483 Source source = addSource(r''' |
| 3484 class _A {} |
| 3485 main() { |
| 3486 var v = new List<_A>(); |
| 3487 print(v); |
| 3488 }'''); |
| 3489 computeLibrarySourceErrors(source); |
| 3490 assertNoErrors(source); |
| 3491 verify([source]); |
| 3492 } |
| 3493 |
| 3494 void test_unusedElement_class_notUsed_inClassMember() { |
| 3495 enableUnusedElement = true; |
| 3496 Source source = addSource(r''' |
| 3497 class _A { |
| 3498 static staticMethod() { |
| 3499 new _A(); |
| 3500 } |
| 3501 instanceMethod() { |
| 3502 new _A(); |
| 3503 } |
| 3504 } |
| 3505 '''); |
| 3506 computeLibrarySourceErrors(source); |
| 3507 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3508 verify([source]); |
| 3509 } |
| 3510 |
| 3511 void test_unusedElement_class_notUsed_inConstructorName() { |
| 3512 enableUnusedElement = true; |
| 3513 Source source = addSource(r''' |
| 3514 class _A { |
| 3515 _A() {} |
| 3516 _A.named() {} |
| 3517 } |
| 3518 '''); |
| 3519 computeLibrarySourceErrors(source); |
| 3520 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3521 verify([source]); |
| 3522 } |
| 3523 |
| 3524 void test_unusedElement_class_notUsed_isExpression() { |
| 3525 enableUnusedElement = true; |
| 3526 Source source = addSource(r''' |
| 3527 class _A {} |
| 3528 main(p) { |
| 3529 if (p is _A) { |
| 3530 } |
| 3531 } |
| 3532 '''); |
| 3533 computeLibrarySourceErrors(source); |
| 3534 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3535 verify([source]); |
| 3536 } |
| 3537 |
| 3538 void test_unusedElement_class_notUsed_noReference() { |
| 3539 enableUnusedElement = true; |
| 3540 Source source = addSource(r''' |
| 3541 class _A {} |
| 3542 main() { |
| 3543 }'''); |
| 3544 computeLibrarySourceErrors(source); |
| 3545 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3546 verify([source]); |
| 3547 } |
| 3548 |
| 3549 void test_unusedElement_class_notUsed_variableDeclaration() { |
| 3550 enableUnusedElement = true; |
| 3551 Source source = addSource(r''' |
| 3552 class _A {} |
| 3553 main() { |
| 3554 _A v; |
| 3555 print(v); |
| 3556 } |
| 3557 print(x) {} |
| 3558 '''); |
| 3559 computeLibrarySourceErrors(source); |
| 3560 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3561 verify([source]); |
| 3562 } |
| 3563 |
| 3564 void test_unusedElement_enum_isUsed_fieldReference() { |
| 3565 enableUnusedElement = true; |
| 3566 Source source = addSource(r''' |
| 3567 enum _MyEnum {A, B, C} |
| 3568 main() { |
| 3569 print(_MyEnum.B); |
| 3570 }'''); |
| 3571 computeLibrarySourceErrors(source); |
| 3572 assertNoErrors(source); |
| 3573 verify([source]); |
| 3574 } |
| 3575 |
| 3576 void test_unusedElement_enum_notUsed_noReference() { |
| 3577 enableUnusedElement = true; |
| 3578 Source source = addSource(r''' |
| 3579 enum _MyEnum {A, B, C} |
| 3580 main() { |
| 3581 }'''); |
| 3582 computeLibrarySourceErrors(source); |
| 3583 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3584 verify([source]); |
| 3585 } |
| 3586 |
| 3587 void test_unusedElement_functionLocal_isUsed_closure() { |
| 3588 enableUnusedElement = true; |
| 3589 Source source = addSource(r''' |
| 3590 main() { |
| 3591 print(() {}); |
| 3592 } |
| 3593 print(x) {} |
| 3594 '''); |
| 3595 computeLibrarySourceErrors(source); |
| 3596 assertNoErrors(source); |
| 3597 verify([source]); |
| 3598 } |
| 3599 |
| 3600 void test_unusedElement_functionLocal_isUsed_invocation() { |
| 3601 enableUnusedElement = true; |
| 3602 Source source = addSource(r''' |
| 3603 main() { |
| 3604 f() {} |
| 3605 f(); |
| 3606 }'''); |
| 3607 computeLibrarySourceErrors(source); |
| 3608 assertNoErrors(source); |
| 3609 verify([source]); |
| 3610 } |
| 3611 |
| 3612 void test_unusedElement_functionLocal_isUsed_reference() { |
| 3613 enableUnusedElement = true; |
| 3614 Source source = addSource(r''' |
| 3615 main() { |
| 3616 f() {} |
| 3617 print(f); |
| 3618 } |
| 3619 print(x) {} |
| 3620 '''); |
| 3621 computeLibrarySourceErrors(source); |
| 3622 assertNoErrors(source); |
| 3623 verify([source]); |
| 3624 } |
| 3625 |
| 3626 void test_unusedElement_functionLocal_notUsed_noReference() { |
| 3627 enableUnusedElement = true; |
| 3628 Source source = addSource(r''' |
| 3629 main() { |
| 3630 f() {} |
| 3631 }'''); |
| 3632 computeLibrarySourceErrors(source); |
| 3633 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3634 verify([source]); |
| 3635 } |
| 3636 |
| 3637 void test_unusedElement_functionLocal_notUsed_referenceFromItself() { |
| 3638 enableUnusedElement = true; |
| 3639 Source source = addSource(r''' |
| 3640 main() { |
| 3641 _f(int p) { |
| 3642 _f(p - 1); |
| 3643 } |
| 3644 }'''); |
| 3645 computeLibrarySourceErrors(source); |
| 3646 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3647 verify([source]); |
| 3648 } |
| 3649 |
| 3650 void test_unusedElement_functionTop_isUsed_invocation() { |
| 3651 enableUnusedElement = true; |
| 3652 Source source = addSource(r''' |
| 3653 _f() {} |
| 3654 main() { |
| 3655 _f(); |
| 3656 }'''); |
| 3657 computeLibrarySourceErrors(source); |
| 3658 assertNoErrors(source); |
| 3659 verify([source]); |
| 3660 } |
| 3661 |
| 3662 void test_unusedElement_functionTop_isUsed_reference() { |
| 3663 enableUnusedElement = true; |
| 3664 Source source = addSource(r''' |
| 3665 _f() {} |
| 3666 main() { |
| 3667 print(_f); |
| 3668 } |
| 3669 print(x) {} |
| 3670 '''); |
| 3671 computeLibrarySourceErrors(source); |
| 3672 assertNoErrors(source); |
| 3673 verify([source]); |
| 3674 } |
| 3675 |
| 3676 void test_unusedElement_functionTop_notUsed_noReference() { |
| 3677 enableUnusedElement = true; |
| 3678 Source source = addSource(r''' |
| 3679 _f() {} |
| 3680 main() { |
| 3681 }'''); |
| 3682 computeLibrarySourceErrors(source); |
| 3683 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3684 verify([source]); |
| 3685 } |
| 3686 |
| 3687 void test_unusedElement_functionTop_notUsed_referenceFromItself() { |
| 3688 enableUnusedElement = true; |
| 3689 Source source = addSource(r''' |
| 3690 _f(int p) { |
| 3691 _f(p - 1); |
| 3692 } |
| 3693 main() { |
| 3694 }'''); |
| 3695 computeLibrarySourceErrors(source); |
| 3696 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3697 verify([source]); |
| 3698 } |
| 3699 |
| 3700 void test_unusedElement_functionTypeAlias_isUsed_isExpression() { |
| 3701 enableUnusedElement = true; |
| 3702 Source source = addSource(r''' |
| 3703 typedef _F(a, b); |
| 3704 main(f) { |
| 3705 if (f is _F) { |
| 3706 print('F'); |
| 3707 } |
| 3708 }'''); |
| 3709 computeLibrarySourceErrors(source); |
| 3710 assertNoErrors(source); |
| 3711 verify([source]); |
| 3712 } |
| 3713 |
| 3714 void test_unusedElement_functionTypeAlias_isUsed_reference() { |
| 3715 enableUnusedElement = true; |
| 3716 Source source = addSource(r''' |
| 3717 typedef _F(a, b); |
| 3718 main(_F f) { |
| 3719 }'''); |
| 3720 computeLibrarySourceErrors(source); |
| 3721 assertNoErrors(source); |
| 3722 verify([source]); |
| 3723 } |
| 3724 |
| 3725 void test_unusedElement_functionTypeAlias_isUsed_typeArgument() { |
| 3726 enableUnusedElement = true; |
| 3727 Source source = addSource(r''' |
| 3728 typedef _F(a, b); |
| 3729 main() { |
| 3730 var v = new List<_F>(); |
| 3731 print(v); |
| 3732 }'''); |
| 3733 computeLibrarySourceErrors(source); |
| 3734 assertNoErrors(source); |
| 3735 verify([source]); |
| 3736 } |
| 3737 |
| 3738 void test_unusedElement_functionTypeAlias_isUsed_variableDeclaration() { |
| 3739 enableUnusedElement = true; |
| 3740 Source source = addSource(r''' |
| 3741 typedef _F(a, b); |
| 3742 class A { |
| 3743 _F f; |
| 3744 }'''); |
| 3745 computeLibrarySourceErrors(source); |
| 3746 assertNoErrors(source); |
| 3747 verify([source]); |
| 3748 } |
| 3749 |
| 3750 void test_unusedElement_functionTypeAlias_notUsed_noReference() { |
| 3751 enableUnusedElement = true; |
| 3752 Source source = addSource(r''' |
| 3753 typedef _F(a, b); |
| 3754 main() { |
| 3755 }'''); |
| 3756 computeLibrarySourceErrors(source); |
| 3757 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3758 verify([source]); |
| 3759 } |
| 3760 |
| 3761 void test_unusedElement_getter_isUsed_invocation_implicitThis() { |
| 3762 enableUnusedElement = true; |
| 3763 Source source = addSource(r''' |
| 3764 class A { |
| 3765 get _g => null; |
| 3766 useGetter() { |
| 3767 var v = _g; |
| 3768 } |
| 3769 }'''); |
| 3770 computeLibrarySourceErrors(source); |
| 3771 assertNoErrors(source); |
| 3772 verify([source]); |
| 3773 } |
| 3774 |
| 3775 void test_unusedElement_getter_isUsed_invocation_PrefixedIdentifier() { |
| 3776 enableUnusedElement = true; |
| 3777 Source source = addSource(r''' |
| 3778 class A { |
| 3779 get _g => null; |
| 3780 } |
| 3781 main(A a) { |
| 3782 var v = a._g; |
| 3783 } |
| 3784 '''); |
| 3785 computeLibrarySourceErrors(source); |
| 3786 assertNoErrors(source); |
| 3787 verify([source]); |
| 3788 } |
| 3789 |
| 3790 void test_unusedElement_getter_isUsed_invocation_PropertyAccess() { |
| 3791 enableUnusedElement = true; |
| 3792 Source source = addSource(r''' |
| 3793 class A { |
| 3794 get _g => null; |
| 3795 } |
| 3796 main() { |
| 3797 var v = new A()._g; |
| 3798 } |
| 3799 '''); |
| 3800 computeLibrarySourceErrors(source); |
| 3801 assertNoErrors(source); |
| 3802 verify([source]); |
| 3803 } |
| 3804 |
| 3805 void test_unusedElement_getter_notUsed_noReference() { |
| 3806 enableUnusedElement = true; |
| 3807 Source source = addSource(r''' |
| 3808 class A { |
| 3809 get _g => null; |
| 3810 }'''); |
| 3811 computeLibrarySourceErrors(source); |
| 3812 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3813 verify([source]); |
| 3814 } |
| 3815 |
| 3816 void test_unusedElement_getter_notUsed_referenceFromItself() { |
| 3817 enableUnusedElement = true; |
| 3818 Source source = addSource(r''' |
| 3819 class A { |
| 3820 get _g { |
| 3821 return _g; |
| 3822 } |
| 3823 }'''); |
| 3824 computeLibrarySourceErrors(source); |
| 3825 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 3826 verify([source]); |
| 3827 } |
| 3828 |
| 3829 void test_unusedElement_method_isUsed_hasReference_implicitThis() { |
| 3830 enableUnusedElement = true; |
| 3831 Source source = addSource(r''' |
| 3832 class A { |
| 3833 _m() {} |
| 3834 useMethod() { |
| 3835 print(_m); |
| 3836 } |
| 3837 } |
| 3838 print(x) {} |
| 3839 '''); |
| 3840 computeLibrarySourceErrors(source); |
| 3841 assertNoErrors(source); |
| 3842 verify([source]); |
| 3843 } |
| 3844 |
| 3845 void test_unusedElement_method_isUsed_hasReference_implicitThis_subclass() { |
| 3846 enableUnusedElement = true; |
| 3847 Source source = addSource(r''' |
| 3848 class A { |
| 3849 _m() {} |
| 3850 useMethod() { |
| 3851 print(_m); |
| 3852 } |
| 3853 } |
| 3854 class B extends A { |
| 3855 _m() {} |
| 3856 } |
| 3857 print(x) {} |
| 3858 '''); |
| 3859 computeLibrarySourceErrors(source); |
| 3860 assertNoErrors(source); |
| 3861 verify([source]); |
| 3862 } |
| 3863 |
| 3864 void test_unusedElement_method_isUsed_hasReference_PrefixedIdentifier() { |
| 3865 enableUnusedElement = true; |
| 3866 Source source = addSource(r''' |
| 3867 class A { |
| 3868 _m() {} |
| 3869 } |
| 3870 main(A a) { |
| 3871 a._m; |
| 3872 }'''); |
| 3873 computeLibrarySourceErrors(source); |
| 3874 assertNoErrors(source); |
| 3875 verify([source]); |
| 3876 } |
| 3877 |
| 3878 void test_unusedElement_method_isUsed_hasReference_PropertyAccess() { |
| 3879 enableUnusedElement = true; |
| 3880 Source source = addSource(r''' |
| 3881 class A { |
| 3882 _m() {} |
| 3883 } |
| 3884 main() { |
| 3885 new A()._m; |
| 3886 }'''); |
| 3887 computeLibrarySourceErrors(source); |
| 3888 assertNoErrors(source); |
| 3889 verify([source]); |
| 3890 } |
| 3891 |
| 3892 void test_unusedElement_method_isUsed_invocation_implicitThis() { |
| 3893 enableUnusedElement = true; |
| 3894 Source source = addSource(r''' |
| 3895 class A { |
| 3896 _m() {} |
| 3897 useMethod() { |
| 3898 _m(); |
| 3899 } |
| 3900 }'''); |
| 3901 computeLibrarySourceErrors(source); |
| 3902 assertNoErrors(source); |
| 3903 verify([source]); |
| 3904 } |
| 3905 |
| 3906 void test_unusedElement_method_isUsed_invocation_implicitThis_subclass() { |
| 3907 enableUnusedElement = true; |
| 3908 Source source = addSource(r''' |
| 3909 class A { |
| 3910 _m() {} |
| 3911 useMethod() { |
| 3912 _m(); |
| 3913 } |
| 3914 } |
| 3915 class B extends A { |
| 3916 _m() {} |
| 3917 }'''); |
| 3918 computeLibrarySourceErrors(source); |
| 3919 assertNoErrors(source); |
| 3920 verify([source]); |
| 3921 } |
| 3922 |
| 3923 void test_unusedElement_method_isUsed_invocation_MemberElement() { |
| 3924 enableUnusedElement = true; |
| 3925 Source source = addSource(r''' |
| 3926 class A<T> { |
| 3927 _m(T t) {} |
| 3928 } |
| 3929 main(A<int> a) { |
| 3930 a._m(0); |
| 3931 }'''); |
| 3932 computeLibrarySourceErrors(source); |
| 3933 assertNoErrors(source); |
| 3934 verify([source]); |
| 3935 } |
| 3936 |
| 3937 void test_unusedElement_method_isUsed_invocation_propagated() { |
| 3938 enableUnusedElement = true; |
| 3939 Source source = addSource(r''' |
| 3940 class A { |
| 3941 _m() {} |
| 3942 } |
| 3943 main() { |
| 3944 var a = new A(); |
| 3945 a._m(); |
| 3946 }'''); |
| 3947 computeLibrarySourceErrors(source); |
| 3948 assertNoErrors(source); |
| 3949 verify([source]); |
| 3950 } |
| 3951 |
| 3952 void test_unusedElement_method_isUsed_invocation_static() { |
| 3953 enableUnusedElement = true; |
| 3954 Source source = addSource(r''' |
| 3955 class A { |
| 3956 _m() {} |
| 3957 } |
| 3958 main() { |
| 3959 A a = new A(); |
| 3960 a._m(); |
| 3961 }'''); |
| 3962 computeLibrarySourceErrors(source); |
| 3963 assertNoErrors(source); |
| 3964 verify([source]); |
| 3965 } |
| 3966 |
| 3967 void test_unusedElement_method_isUsed_invocation_subclass() { |
| 3968 enableUnusedElement = true; |
| 3969 Source source = addSource(r''' |
| 3970 class A { |
| 3971 _m() {} |
| 3972 } |
| 3973 class B extends A { |
| 3974 _m() {} |
| 3975 } |
| 3976 main(A a) { |
| 3977 a._m(); |
| 3978 }'''); |
| 3979 computeLibrarySourceErrors(source); |
| 3980 assertNoErrors(source); |
| 3981 verify([source]); |
| 3982 } |
| 3983 |
| 3984 void test_unusedElement_method_isUsed_notPrivate() { |
| 3985 enableUnusedElement = true; |
| 3986 Source source = addSource(r''' |
| 3987 class A { |
| 3988 m() {} |
| 3989 } |
| 3990 main() { |
| 3991 }'''); |
| 3992 computeLibrarySourceErrors(source); |
| 3993 assertNoErrors(source); |
| 3994 verify([source]); |
| 3995 } |
| 3996 |
| 3997 void test_unusedElement_method_isUsed_staticInvocation() { |
| 3998 enableUnusedElement = true; |
| 3999 Source source = addSource(r''' |
| 4000 class A { |
| 4001 static _m() {} |
| 4002 } |
| 4003 main() { |
| 4004 A._m(); |
| 4005 }'''); |
| 4006 computeLibrarySourceErrors(source); |
| 4007 assertNoErrors(source); |
| 4008 verify([source]); |
| 4009 } |
| 4010 |
| 4011 void test_unusedElement_method_notUsed_noReference() { |
| 4012 enableUnusedElement = true; |
| 4013 Source source = addSource(r''' |
| 4014 class A { |
| 4015 static _m() {} |
| 4016 }'''); |
| 4017 computeLibrarySourceErrors(source); |
| 4018 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 4019 verify([source]); |
| 4020 } |
| 4021 |
| 4022 void test_unusedElement_method_notUsed_referenceFromItself() { |
| 4023 enableUnusedElement = true; |
| 4024 Source source = addSource(r''' |
| 4025 class A { |
| 4026 static _m(int p) { |
| 4027 _m(p - 1); |
| 4028 } |
| 4029 }'''); |
| 4030 computeLibrarySourceErrors(source); |
| 4031 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 4032 verify([source]); |
| 4033 } |
| 4034 |
| 4035 void test_unusedElement_setter_isUsed_invocation_implicitThis() { |
| 4036 enableUnusedElement = true; |
| 4037 Source source = addSource(r''' |
| 4038 class A { |
| 4039 set _s(x) {} |
| 4040 useSetter() { |
| 4041 _s = 42; |
| 4042 } |
| 4043 }'''); |
| 4044 computeLibrarySourceErrors(source); |
| 4045 assertNoErrors(source); |
| 4046 verify([source]); |
| 4047 } |
| 4048 |
| 4049 void test_unusedElement_setter_isUsed_invocation_PrefixedIdentifier() { |
| 4050 enableUnusedElement = true; |
| 4051 Source source = addSource(r''' |
| 4052 class A { |
| 4053 set _s(x) {} |
| 4054 } |
| 4055 main(A a) { |
| 4056 a._s = 42; |
| 4057 } |
| 4058 '''); |
| 4059 computeLibrarySourceErrors(source); |
| 4060 assertNoErrors(source); |
| 4061 verify([source]); |
| 4062 } |
| 4063 |
| 4064 void test_unusedElement_setter_isUsed_invocation_PropertyAccess() { |
| 4065 enableUnusedElement = true; |
| 4066 Source source = addSource(r''' |
| 4067 class A { |
| 4068 set _s(x) {} |
| 4069 } |
| 4070 main() { |
| 4071 new A()._s = 42; |
| 4072 } |
| 4073 '''); |
| 4074 computeLibrarySourceErrors(source); |
| 4075 assertNoErrors(source); |
| 4076 verify([source]); |
| 4077 } |
| 4078 |
| 4079 void test_unusedElement_setter_notUsed_noReference() { |
| 4080 enableUnusedElement = true; |
| 4081 Source source = addSource(r''' |
| 4082 class A { |
| 4083 set _s(x) {} |
| 4084 }'''); |
| 4085 computeLibrarySourceErrors(source); |
| 4086 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 4087 verify([source]); |
| 4088 } |
| 4089 |
| 4090 void test_unusedElement_setter_notUsed_referenceFromItself() { |
| 4091 enableUnusedElement = true; |
| 4092 Source source = addSource(r''' |
| 4093 class A { |
| 4094 set _s(int x) { |
| 4095 if (x > 5) { |
| 4096 _s = x - 1; |
| 4097 } |
| 4098 } |
| 4099 }'''); |
| 4100 computeLibrarySourceErrors(source); |
| 4101 assertErrors(source, [HintCode.UNUSED_ELEMENT]); |
| 4102 verify([source]); |
| 4103 } |
| 4104 |
| 4105 void test_unusedField_isUsed_argument() { |
| 4106 enableUnusedElement = true; |
| 4107 Source source = addSource(r''' |
| 4108 class A { |
| 4109 int _f = 0; |
| 4110 main() { |
| 4111 print(++_f); |
| 4112 } |
| 4113 } |
| 4114 print(x) {}'''); |
| 4115 computeLibrarySourceErrors(source); |
| 4116 assertErrors(source); |
| 4117 verify([source]); |
| 4118 } |
| 4119 |
| 4120 void test_unusedField_isUsed_reference_implicitThis() { |
| 4121 enableUnusedElement = true; |
| 4122 Source source = addSource(r''' |
| 4123 class A { |
| 4124 int _f; |
| 4125 main() { |
| 4126 print(_f); |
| 4127 } |
| 4128 } |
| 4129 print(x) {}'''); |
| 4130 computeLibrarySourceErrors(source); |
| 4131 assertErrors(source); |
| 4132 verify([source]); |
| 4133 } |
| 4134 |
| 4135 void test_unusedField_isUsed_reference_implicitThis_expressionFunctionBody() { |
| 4136 enableUnusedElement = true; |
| 4137 Source source = addSource(r''' |
| 4138 class A { |
| 4139 int _f; |
| 4140 m() => _f; |
| 4141 }'''); |
| 4142 computeLibrarySourceErrors(source); |
| 4143 assertErrors(source); |
| 4144 verify([source]); |
| 4145 } |
| 4146 |
| 4147 void test_unusedField_isUsed_reference_implicitThis_subclass() { |
| 4148 enableUnusedElement = true; |
| 4149 Source source = addSource(r''' |
| 4150 class A { |
| 4151 int _f; |
| 4152 main() { |
| 4153 print(_f); |
| 4154 } |
| 4155 } |
| 4156 class B extends A { |
| 4157 int _f; |
| 4158 } |
| 4159 print(x) {}'''); |
| 4160 computeLibrarySourceErrors(source); |
| 4161 assertErrors(source); |
| 4162 verify([source]); |
| 4163 } |
| 4164 |
| 4165 void test_unusedField_isUsed_reference_qualified_propagatedElement() { |
| 4166 enableUnusedElement = true; |
| 4167 Source source = addSource(r''' |
| 4168 class A { |
| 4169 int _f; |
| 4170 } |
| 4171 main() { |
| 4172 var a = new A(); |
| 4173 print(a._f); |
| 4174 } |
| 4175 print(x) {}'''); |
| 4176 computeLibrarySourceErrors(source); |
| 4177 assertErrors(source); |
| 4178 verify([source]); |
| 4179 } |
| 4180 |
| 4181 void test_unusedField_isUsed_reference_qualified_staticElement() { |
| 4182 enableUnusedElement = true; |
| 4183 Source source = addSource(r''' |
| 4184 class A { |
| 4185 int _f; |
| 4186 } |
| 4187 main() { |
| 4188 A a = new A(); |
| 4189 print(a._f); |
| 4190 } |
| 4191 print(x) {}'''); |
| 4192 computeLibrarySourceErrors(source); |
| 4193 assertErrors(source); |
| 4194 verify([source]); |
| 4195 } |
| 4196 |
| 4197 void test_unusedField_isUsed_reference_qualified_unresolved() { |
| 4198 enableUnusedElement = true; |
| 4199 Source source = addSource(r''' |
| 4200 class A { |
| 4201 int _f; |
| 4202 } |
| 4203 main(a) { |
| 4204 print(a._f); |
| 4205 } |
| 4206 print(x) {}'''); |
| 4207 computeLibrarySourceErrors(source); |
| 4208 assertErrors(source); |
| 4209 verify([source]); |
| 4210 } |
| 4211 |
| 4212 void test_unusedField_notUsed_compoundAssign() { |
| 4213 enableUnusedElement = true; |
| 4214 Source source = addSource(r''' |
| 4215 class A { |
| 4216 int _f; |
| 4217 main() { |
| 4218 _f += 2; |
| 4219 } |
| 4220 }'''); |
| 4221 computeLibrarySourceErrors(source); |
| 4222 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4223 verify([source]); |
| 4224 } |
| 4225 |
| 4226 void test_unusedField_notUsed_noReference() { |
| 4227 enableUnusedElement = true; |
| 4228 Source source = addSource(r''' |
| 4229 class A { |
| 4230 int _f; |
| 4231 } |
| 4232 '''); |
| 4233 computeLibrarySourceErrors(source); |
| 4234 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4235 verify([source]); |
| 4236 } |
| 4237 |
| 4238 void test_unusedField_notUsed_postfixExpr() { |
| 4239 enableUnusedElement = true; |
| 4240 Source source = addSource(r''' |
| 4241 class A { |
| 4242 int _f = 0; |
| 4243 main() { |
| 4244 _f++; |
| 4245 } |
| 4246 }'''); |
| 4247 computeLibrarySourceErrors(source); |
| 4248 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4249 verify([source]); |
| 4250 } |
| 4251 |
| 4252 void test_unusedField_notUsed_prefixExpr() { |
| 4253 enableUnusedElement = true; |
| 4254 Source source = addSource(r''' |
| 4255 class A { |
| 4256 int _f = 0; |
| 4257 main() { |
| 4258 ++_f; |
| 4259 } |
| 4260 }'''); |
| 4261 computeLibrarySourceErrors(source); |
| 4262 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4263 verify([source]); |
| 4264 } |
| 4265 |
| 4266 void test_unusedField_notUsed_simpleAssignment() { |
| 4267 enableUnusedElement = true; |
| 4268 Source source = addSource(r''' |
| 4269 class A { |
| 4270 int _f; |
| 4271 m() { |
| 4272 _f = 1; |
| 4273 } |
| 4274 } |
| 4275 main(A a) { |
| 4276 a._f = 2; |
| 4277 } |
| 4278 '''); |
| 4279 computeLibrarySourceErrors(source); |
| 4280 assertErrors(source, [HintCode.UNUSED_FIELD]); |
| 4281 verify([source]); |
| 4282 } |
| 4283 |
| 4284 void test_unusedImport() { |
| 4285 Source source = addSource(r''' |
| 4286 library L; |
| 4287 import 'lib1.dart';'''); |
| 4288 Source source2 = addNamedSource("/lib1.dart", "library lib1;"); |
| 4289 computeLibrarySourceErrors(source); |
| 4290 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 4291 assertNoErrors(source2); |
| 4292 verify([source, source2]); |
| 4293 } |
| 4294 |
| 4295 void test_unusedImport_as() { |
| 4296 Source source = addSource(r''' |
| 4297 library L; |
| 4298 import 'lib1.dart'; |
| 4299 import 'lib1.dart' as one; |
| 4300 one.A a;'''); |
| 4301 Source source2 = addNamedSource( |
| 4302 "/lib1.dart", |
| 4303 r''' |
| 4304 library lib1; |
| 4305 class A {}'''); |
| 4306 computeLibrarySourceErrors(source); |
| 4307 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 4308 assertNoErrors(source2); |
| 4309 verify([source, source2]); |
| 4310 } |
| 4311 |
| 4312 void test_unusedImport_hide() { |
| 4313 Source source = addSource(r''' |
| 4314 library L; |
| 4315 import 'lib1.dart'; |
| 4316 import 'lib1.dart' hide A; |
| 4317 A a;'''); |
| 4318 Source source2 = addNamedSource( |
| 4319 "/lib1.dart", |
| 4320 r''' |
| 4321 library lib1; |
| 4322 class A {}'''); |
| 4323 computeLibrarySourceErrors(source); |
| 4324 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 4325 assertNoErrors(source2); |
| 4326 verify([source, source2]); |
| 4327 } |
| 4328 |
| 4329 void test_unusedImport_show() { |
| 4330 Source source = addSource(r''' |
| 4331 library L; |
| 4332 import 'lib1.dart' show A; |
| 4333 import 'lib1.dart' show B; |
| 4334 A a;'''); |
| 4335 Source source2 = addNamedSource( |
| 4336 "/lib1.dart", |
| 4337 r''' |
| 4338 library lib1; |
| 4339 class A {} |
| 4340 class B {}'''); |
| 4341 computeLibrarySourceErrors(source); |
| 4342 assertErrors(source, [HintCode.UNUSED_IMPORT]); |
| 4343 assertNoErrors(source2); |
| 4344 verify([source, source2]); |
| 4345 } |
| 4346 |
| 4347 void test_unusedLocalVariable_inCatch_exception() { |
| 4348 enableUnusedLocalVariable = true; |
| 4349 Source source = addSource(r''' |
| 4350 main() { |
| 4351 try { |
| 4352 } on String catch (exception) { |
| 4353 } |
| 4354 }'''); |
| 4355 computeLibrarySourceErrors(source); |
| 4356 assertErrors(source, [HintCode.UNUSED_CATCH_CLAUSE]); |
| 4357 verify([source]); |
| 4358 } |
| 4359 |
| 4360 void test_unusedLocalVariable_inCatch_exception_hasStack() { |
| 4361 enableUnusedLocalVariable = true; |
| 4362 Source source = addSource(r''' |
| 4363 main() { |
| 4364 try { |
| 4365 } catch (exception, stack) { |
| 4366 print(stack); |
| 4367 } |
| 4368 }'''); |
| 4369 computeLibrarySourceErrors(source); |
| 4370 assertNoErrors(source); |
| 4371 verify([source]); |
| 4372 } |
| 4373 |
| 4374 void test_unusedLocalVariable_inCatch_exception_noOnClause() { |
| 4375 enableUnusedLocalVariable = true; |
| 4376 Source source = addSource(r''' |
| 4377 main() { |
| 4378 try { |
| 4379 } catch (exception) { |
| 4380 } |
| 4381 }'''); |
| 4382 computeLibrarySourceErrors(source); |
| 4383 assertNoErrors(source); |
| 4384 verify([source]); |
| 4385 } |
| 4386 |
| 4387 void test_unusedLocalVariable_inCatch_stackTrace() { |
| 4388 enableUnusedLocalVariable = true; |
| 4389 Source source = addSource(r''' |
| 4390 main() { |
| 4391 try { |
| 4392 } catch (exception, stackTrace) { |
| 4393 } |
| 4394 }'''); |
| 4395 computeLibrarySourceErrors(source); |
| 4396 assertErrors(source, [HintCode.UNUSED_CATCH_STACK]); |
| 4397 verify([source]); |
| 4398 } |
| 4399 |
| 4400 void test_unusedLocalVariable_inCatch_stackTrace_used() { |
| 4401 enableUnusedLocalVariable = true; |
| 4402 Source source = addSource(r''' |
| 4403 main() { |
| 4404 try { |
| 4405 } catch (exception, stackTrace) { |
| 4406 print('exception at $stackTrace'); |
| 4407 } |
| 4408 } |
| 4409 print(x) {}'''); |
| 4410 computeLibrarySourceErrors(source); |
| 4411 assertErrors(source); |
| 4412 verify([source]); |
| 4413 } |
| 4414 |
| 4415 void test_unusedLocalVariable_inFor_underscore_ignored() { |
| 4416 enableUnusedLocalVariable = true; |
| 4417 Source source = addSource(r''' |
| 4418 main() { |
| 4419 for (var _ in [1,2,3]) { |
| 4420 for (var __ in [4,5,6]) { |
| 4421 // do something |
| 4422 } |
| 4423 } |
| 4424 }'''); |
| 4425 computeLibrarySourceErrors(source); |
| 4426 assertErrors(source); |
| 4427 verify([source]); |
| 4428 } |
| 4429 |
| 4430 void test_unusedLocalVariable_inFunction() { |
| 4431 enableUnusedLocalVariable = true; |
| 4432 Source source = addSource(r''' |
| 4433 main() { |
| 4434 var v = 1; |
| 4435 v = 2; |
| 4436 }'''); |
| 4437 computeLibrarySourceErrors(source); |
| 4438 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4439 verify([source]); |
| 4440 } |
| 4441 |
| 4442 void test_unusedLocalVariable_inMethod() { |
| 4443 enableUnusedLocalVariable = true; |
| 4444 Source source = addSource(r''' |
| 4445 class A { |
| 4446 foo() { |
| 4447 var v = 1; |
| 4448 v = 2; |
| 4449 } |
| 4450 }'''); |
| 4451 computeLibrarySourceErrors(source); |
| 4452 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4453 verify([source]); |
| 4454 } |
| 4455 |
| 4456 void test_unusedLocalVariable_isInvoked() { |
| 4457 enableUnusedLocalVariable = true; |
| 4458 Source source = addSource(r''' |
| 4459 typedef Foo(); |
| 4460 main() { |
| 4461 Foo foo; |
| 4462 foo(); |
| 4463 }'''); |
| 4464 computeLibrarySourceErrors(source); |
| 4465 assertErrors(source); |
| 4466 verify([source]); |
| 4467 } |
| 4468 |
| 4469 void test_unusedLocalVariable_isRead_notUsed_compoundAssign() { |
| 4470 enableUnusedLocalVariable = true; |
| 4471 Source source = addSource(r''' |
| 4472 main() { |
| 4473 var v = 1; |
| 4474 v += 2; |
| 4475 }'''); |
| 4476 computeLibrarySourceErrors(source); |
| 4477 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4478 verify([source]); |
| 4479 } |
| 4480 |
| 4481 void test_unusedLocalVariable_isRead_notUsed_postfixExpr() { |
| 4482 enableUnusedLocalVariable = true; |
| 4483 Source source = addSource(r''' |
| 4484 main() { |
| 4485 var v = 1; |
| 4486 v++; |
| 4487 }'''); |
| 4488 computeLibrarySourceErrors(source); |
| 4489 assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]); |
| 4490 verify([source]); |
| 4491 } |
| 4492 |
| 4493 void test_unusedLocalVariable_isRead_notUsed_prefixExpr() { |
| 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_usedArgument() { |
| 4506 enableUnusedLocalVariable = true; |
| 4507 Source source = addSource(r''' |
| 4508 main() { |
| 4509 var v = 1; |
| 4510 print(++v); |
| 4511 } |
| 4512 print(x) {}'''); |
| 4513 computeLibrarySourceErrors(source); |
| 4514 assertErrors(source); |
| 4515 verify([source]); |
| 4516 } |
| 4517 |
| 4518 void test_unusedLocalVariable_isRead_usedInvocationTarget() { |
| 4519 enableUnusedLocalVariable = true; |
| 4520 Source source = addSource(r''' |
| 4521 class A { |
| 4522 foo() {} |
| 4523 } |
| 4524 main() { |
| 4525 var a = new A(); |
| 4526 a.foo(); |
| 4527 } |
| 4528 '''); |
| 4529 computeLibrarySourceErrors(source); |
| 4530 assertErrors(source); |
| 4531 verify([source]); |
| 4532 } |
| 4533 |
| 4534 void test_useOfVoidResult_assignmentExpression_function() { |
| 4535 Source source = addSource(r''' |
| 4536 void f() {} |
| 4537 class A { |
| 4538 n() { |
| 4539 var a; |
| 4540 a = f(); |
| 4541 } |
| 4542 }'''); |
| 4543 computeLibrarySourceErrors(source); |
| 4544 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4545 verify([source]); |
| 4546 } |
| 4547 |
| 4548 void test_useOfVoidResult_assignmentExpression_method() { |
| 4549 Source source = addSource(r''' |
| 4550 class A { |
| 4551 void m() {} |
| 4552 n() { |
| 4553 var a; |
| 4554 a = m(); |
| 4555 } |
| 4556 }'''); |
| 4557 computeLibrarySourceErrors(source); |
| 4558 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4559 verify([source]); |
| 4560 } |
| 4561 |
| 4562 void test_useOfVoidResult_inForLoop() { |
| 4563 Source source = addSource(r''' |
| 4564 class A { |
| 4565 void m() {} |
| 4566 n() { |
| 4567 for(var a = m();;) {} |
| 4568 } |
| 4569 }'''); |
| 4570 computeLibrarySourceErrors(source); |
| 4571 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4572 verify([source]); |
| 4573 } |
| 4574 |
| 4575 void test_useOfVoidResult_variableDeclaration_function() { |
| 4576 Source source = addSource(r''' |
| 4577 void f() {} |
| 4578 class A { |
| 4579 n() { |
| 4580 var a = f(); |
| 4581 } |
| 4582 }'''); |
| 4583 computeLibrarySourceErrors(source); |
| 4584 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4585 verify([source]); |
| 4586 } |
| 4587 |
| 4588 void test_useOfVoidResult_variableDeclaration_method() { |
| 4589 Source source = addSource(r''' |
| 4590 class A { |
| 4591 void m() {} |
| 4592 n() { |
| 4593 var a = m(); |
| 4594 } |
| 4595 }'''); |
| 4596 computeLibrarySourceErrors(source); |
| 4597 assertErrors(source, [HintCode.USE_OF_VOID_RESULT]); |
| 4598 verify([source]); |
| 4599 } |
| 4600 |
| 4601 void test_useOfVoidResult_variableDeclaration_method2() { |
| 4602 Source source = addSource(r''' |
| 4603 class A { |
| 4604 void m() {} |
| 4605 n() { |
| 4606 var a = m(), b = m(); |
| 4607 } |
| 4608 }'''); |
| 4609 computeLibrarySourceErrors(source); |
| 4610 assertErrors( |
| 4611 source, [HintCode.USE_OF_VOID_RESULT, HintCode.USE_OF_VOID_RESULT]); |
| 4612 verify([source]); |
| 4613 } |
| 4614 } |
| 4615 |
| 4616 @reflectiveTest |
| 4617 class InheritanceManagerTest extends EngineTestCase { |
| 4618 /** |
| 4619 * The type provider used to access the types. |
| 4620 */ |
| 4621 TestTypeProvider _typeProvider; |
| 4622 |
| 4623 /** |
| 4624 * The library containing the code being resolved. |
| 4625 */ |
| 4626 LibraryElementImpl _definingLibrary; |
| 4627 |
| 4628 /** |
| 4629 * The inheritance manager being tested. |
| 4630 */ |
| 4631 InheritanceManager _inheritanceManager; |
| 4632 |
| 4633 /** |
| 4634 * The number of members that Object implements (as determined by [TestTypePro
vider]). |
| 4635 */ |
| 4636 int _numOfMembersInObject = 0; |
| 4637 |
| 4638 @override |
| 4639 void setUp() { |
| 4640 _typeProvider = new TestTypeProvider(); |
| 4641 _inheritanceManager = _createInheritanceManager(); |
| 4642 InterfaceType objectType = _typeProvider.objectType; |
| 4643 _numOfMembersInObject = |
| 4644 objectType.methods.length + objectType.accessors.length; |
| 4645 } |
| 4646 |
| 4647 void test_getMapOfMembersInheritedFromClasses_accessor_extends() { |
| 4648 // class A { int get g; } |
| 4649 // class B extends A {} |
| 4650 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4651 String getterName = "g"; |
| 4652 PropertyAccessorElement getterG = |
| 4653 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4654 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4655 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 4656 MemberMap mapB = |
| 4657 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4658 MemberMap mapA = |
| 4659 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4660 expect(mapA.size, _numOfMembersInObject); |
| 4661 expect(mapB.size, _numOfMembersInObject + 1); |
| 4662 expect(mapB.get(getterName), same(getterG)); |
| 4663 _assertNoErrors(classA); |
| 4664 _assertNoErrors(classB); |
| 4665 } |
| 4666 |
| 4667 void test_getMapOfMembersInheritedFromClasses_accessor_implements() { |
| 4668 // class A { int get g; } |
| 4669 // class B implements A {} |
| 4670 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4671 String getterName = "g"; |
| 4672 PropertyAccessorElement getterG = |
| 4673 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4674 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4675 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4676 classB.interfaces = <InterfaceType>[classA.type]; |
| 4677 MemberMap mapB = |
| 4678 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4679 MemberMap mapA = |
| 4680 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4681 expect(mapA.size, _numOfMembersInObject); |
| 4682 expect(mapB.size, _numOfMembersInObject); |
| 4683 expect(mapB.get(getterName), isNull); |
| 4684 _assertNoErrors(classA); |
| 4685 _assertNoErrors(classB); |
| 4686 } |
| 4687 |
| 4688 void test_getMapOfMembersInheritedFromClasses_accessor_with() { |
| 4689 // class A { int get g; } |
| 4690 // class B extends Object with A {} |
| 4691 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4692 String getterName = "g"; |
| 4693 PropertyAccessorElement getterG = |
| 4694 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4695 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4696 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4697 classB.mixins = <InterfaceType>[classA.type]; |
| 4698 MemberMap mapB = |
| 4699 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4700 MemberMap mapA = |
| 4701 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4702 expect(mapA.size, _numOfMembersInObject); |
| 4703 expect(mapB.size, _numOfMembersInObject + 1); |
| 4704 expect(mapB.get(getterName), same(getterG)); |
| 4705 _assertNoErrors(classA); |
| 4706 _assertNoErrors(classB); |
| 4707 } |
| 4708 |
| 4709 void test_getMapOfMembersInheritedFromClasses_implicitExtends() { |
| 4710 // class A {} |
| 4711 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4712 MemberMap mapA = |
| 4713 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4714 expect(mapA.size, _numOfMembersInObject); |
| 4715 _assertNoErrors(classA); |
| 4716 } |
| 4717 |
| 4718 void test_getMapOfMembersInheritedFromClasses_method_extends() { |
| 4719 // class A { int g(); } |
| 4720 // class B extends A {} |
| 4721 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4722 String methodName = "m"; |
| 4723 MethodElement methodM = |
| 4724 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4725 classA.methods = <MethodElement>[methodM]; |
| 4726 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4727 classB.supertype = classA.type; |
| 4728 MemberMap mapB = |
| 4729 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4730 MemberMap mapA = |
| 4731 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4732 expect(mapA.size, _numOfMembersInObject); |
| 4733 expect(mapB.size, _numOfMembersInObject + 1); |
| 4734 expect(mapB.get(methodName), same(methodM)); |
| 4735 _assertNoErrors(classA); |
| 4736 _assertNoErrors(classB); |
| 4737 } |
| 4738 |
| 4739 void test_getMapOfMembersInheritedFromClasses_method_implements() { |
| 4740 // class A { int g(); } |
| 4741 // class B implements A {} |
| 4742 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4743 String methodName = "m"; |
| 4744 MethodElement methodM = |
| 4745 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4746 classA.methods = <MethodElement>[methodM]; |
| 4747 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4748 classB.interfaces = <InterfaceType>[classA.type]; |
| 4749 MemberMap mapB = |
| 4750 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4751 MemberMap mapA = |
| 4752 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4753 expect(mapA.size, _numOfMembersInObject); |
| 4754 expect(mapB.size, _numOfMembersInObject); |
| 4755 expect(mapB.get(methodName), isNull); |
| 4756 _assertNoErrors(classA); |
| 4757 _assertNoErrors(classB); |
| 4758 } |
| 4759 |
| 4760 void test_getMapOfMembersInheritedFromClasses_method_with() { |
| 4761 // class A { int g(); } |
| 4762 // class B extends Object with A {} |
| 4763 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4764 String methodName = "m"; |
| 4765 MethodElement methodM = |
| 4766 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4767 classA.methods = <MethodElement>[methodM]; |
| 4768 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4769 classB.mixins = <InterfaceType>[classA.type]; |
| 4770 MemberMap mapB = |
| 4771 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4772 MemberMap mapA = |
| 4773 _inheritanceManager.getMapOfMembersInheritedFromClasses(classA); |
| 4774 expect(mapA.size, _numOfMembersInObject); |
| 4775 expect(mapB.size, _numOfMembersInObject + 1); |
| 4776 expect(mapB.get(methodName), same(methodM)); |
| 4777 _assertNoErrors(classA); |
| 4778 _assertNoErrors(classB); |
| 4779 } |
| 4780 |
| 4781 void test_getMapOfMembersInheritedFromClasses_method_with_two_mixins() { |
| 4782 // class A1 { int m(); } |
| 4783 // class A2 { int m(); } |
| 4784 // class B extends Object with A1, A2 {} |
| 4785 ClassElementImpl classA1 = ElementFactory.classElement2("A1"); |
| 4786 String methodName = "m"; |
| 4787 MethodElement methodA1M = |
| 4788 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4789 classA1.methods = <MethodElement>[methodA1M]; |
| 4790 ClassElementImpl classA2 = ElementFactory.classElement2("A2"); |
| 4791 MethodElement methodA2M = |
| 4792 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4793 classA2.methods = <MethodElement>[methodA2M]; |
| 4794 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4795 classB.mixins = <InterfaceType>[classA1.type, classA2.type]; |
| 4796 MemberMap mapB = |
| 4797 _inheritanceManager.getMapOfMembersInheritedFromClasses(classB); |
| 4798 expect(mapB.get(methodName), same(methodA2M)); |
| 4799 _assertNoErrors(classA1); |
| 4800 _assertNoErrors(classA2); |
| 4801 _assertNoErrors(classB); |
| 4802 } |
| 4803 |
| 4804 void test_getMapOfMembersInheritedFromInterfaces_accessor_extends() { |
| 4805 // class A { int get g; } |
| 4806 // class B extends A {} |
| 4807 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4808 String getterName = "g"; |
| 4809 PropertyAccessorElement getterG = |
| 4810 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4811 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4812 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 4813 MemberMap mapB = |
| 4814 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 4815 MemberMap mapA = |
| 4816 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4817 expect(mapA.size, _numOfMembersInObject); |
| 4818 expect(mapB.size, _numOfMembersInObject + 1); |
| 4819 expect(mapB.get(getterName), same(getterG)); |
| 4820 _assertNoErrors(classA); |
| 4821 _assertNoErrors(classB); |
| 4822 } |
| 4823 |
| 4824 void test_getMapOfMembersInheritedFromInterfaces_accessor_implements() { |
| 4825 // class A { int get g; } |
| 4826 // class B implements A {} |
| 4827 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4828 String getterName = "g"; |
| 4829 PropertyAccessorElement getterG = |
| 4830 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4831 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4832 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4833 classB.interfaces = <InterfaceType>[classA.type]; |
| 4834 MemberMap mapB = |
| 4835 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 4836 MemberMap mapA = |
| 4837 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4838 expect(mapA.size, _numOfMembersInObject); |
| 4839 expect(mapB.size, _numOfMembersInObject + 1); |
| 4840 expect(mapB.get(getterName), same(getterG)); |
| 4841 _assertNoErrors(classA); |
| 4842 _assertNoErrors(classB); |
| 4843 } |
| 4844 |
| 4845 void test_getMapOfMembersInheritedFromInterfaces_accessor_with() { |
| 4846 // class A { int get g; } |
| 4847 // class B extends Object with A {} |
| 4848 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4849 String getterName = "g"; |
| 4850 PropertyAccessorElement getterG = |
| 4851 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 4852 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 4853 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 4854 classB.mixins = <InterfaceType>[classA.type]; |
| 4855 MemberMap mapB = |
| 4856 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 4857 MemberMap mapA = |
| 4858 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4859 expect(mapA.size, _numOfMembersInObject); |
| 4860 expect(mapB.size, _numOfMembersInObject + 1); |
| 4861 expect(mapB.get(getterName), same(getterG)); |
| 4862 _assertNoErrors(classA); |
| 4863 _assertNoErrors(classB); |
| 4864 } |
| 4865 |
| 4866 void test_getMapOfMembersInheritedFromInterfaces_implicitExtends() { |
| 4867 // class A {} |
| 4868 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4869 MemberMap mapA = |
| 4870 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4871 expect(mapA.size, _numOfMembersInObject); |
| 4872 _assertNoErrors(classA); |
| 4873 } |
| 4874 |
| 4875 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_getter_method() { |
| 4876 // class I1 { int m(); } |
| 4877 // class I2 { int get m; } |
| 4878 // class A implements I2, I1 {} |
| 4879 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4880 String methodName = "m"; |
| 4881 MethodElement methodM = |
| 4882 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4883 classI1.methods = <MethodElement>[methodM]; |
| 4884 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 4885 PropertyAccessorElement getter = |
| 4886 ElementFactory.getterElement(methodName, false, _typeProvider.intType); |
| 4887 classI2.accessors = <PropertyAccessorElement>[getter]; |
| 4888 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4889 classA.interfaces = <InterfaceType>[classI2.type, classI1.type]; |
| 4890 MemberMap mapA = |
| 4891 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4892 expect(mapA.size, _numOfMembersInObject); |
| 4893 expect(mapA.get(methodName), isNull); |
| 4894 _assertErrors(classA, |
| 4895 [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]); |
| 4896 } |
| 4897 |
| 4898 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_int_str() { |
| 4899 // class I1 { int m(); } |
| 4900 // class I2 { String m(); } |
| 4901 // class A implements I1, I2 {} |
| 4902 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4903 String methodName = "m"; |
| 4904 MethodElement methodM1 = |
| 4905 ElementFactory.methodElement(methodName, null, [_typeProvider.intType]); |
| 4906 classI1.methods = <MethodElement>[methodM1]; |
| 4907 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 4908 MethodElement methodM2 = ElementFactory.methodElement( |
| 4909 methodName, null, [_typeProvider.stringType]); |
| 4910 classI2.methods = <MethodElement>[methodM2]; |
| 4911 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4912 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 4913 MemberMap mapA = |
| 4914 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4915 expect(mapA.size, _numOfMembersInObject); |
| 4916 expect(mapA.get(methodName), isNull); |
| 4917 _assertErrors( |
| 4918 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); |
| 4919 } |
| 4920 |
| 4921 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_method_getter() { |
| 4922 // class I1 { int m(); } |
| 4923 // class I2 { int get m; } |
| 4924 // class A implements I1, I2 {} |
| 4925 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4926 String methodName = "m"; |
| 4927 MethodElement methodM = |
| 4928 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 4929 classI1.methods = <MethodElement>[methodM]; |
| 4930 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 4931 PropertyAccessorElement getter = |
| 4932 ElementFactory.getterElement(methodName, false, _typeProvider.intType); |
| 4933 classI2.accessors = <PropertyAccessorElement>[getter]; |
| 4934 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4935 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 4936 MemberMap mapA = |
| 4937 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4938 expect(mapA.size, _numOfMembersInObject); |
| 4939 expect(mapA.get(methodName), isNull); |
| 4940 _assertErrors(classA, |
| 4941 [StaticWarningCode.INCONSISTENT_METHOD_INHERITANCE_GETTER_AND_METHOD]); |
| 4942 } |
| 4943 |
| 4944 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_numOfRequiredParams() { |
| 4945 // class I1 { dynamic m(int, [int]); } |
| 4946 // class I2 { dynamic m(int, int, int); } |
| 4947 // class A implements I1, I2 {} |
| 4948 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4949 String methodName = "m"; |
| 4950 MethodElementImpl methodM1 = |
| 4951 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 4952 ParameterElementImpl parameter1 = |
| 4953 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); |
| 4954 parameter1.type = _typeProvider.intType; |
| 4955 parameter1.parameterKind = ParameterKind.REQUIRED; |
| 4956 ParameterElementImpl parameter2 = |
| 4957 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); |
| 4958 parameter2.type = _typeProvider.intType; |
| 4959 parameter2.parameterKind = ParameterKind.POSITIONAL; |
| 4960 methodM1.parameters = <ParameterElement>[parameter1, parameter2]; |
| 4961 classI1.methods = <MethodElement>[methodM1]; |
| 4962 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 4963 MethodElementImpl methodM2 = |
| 4964 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 4965 ParameterElementImpl parameter3 = |
| 4966 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); |
| 4967 parameter3.type = _typeProvider.intType; |
| 4968 parameter3.parameterKind = ParameterKind.REQUIRED; |
| 4969 ParameterElementImpl parameter4 = |
| 4970 new ParameterElementImpl.forNode(AstFactory.identifier3("a4")); |
| 4971 parameter4.type = _typeProvider.intType; |
| 4972 parameter4.parameterKind = ParameterKind.REQUIRED; |
| 4973 ParameterElementImpl parameter5 = |
| 4974 new ParameterElementImpl.forNode(AstFactory.identifier3("a5")); |
| 4975 parameter5.type = _typeProvider.intType; |
| 4976 parameter5.parameterKind = ParameterKind.REQUIRED; |
| 4977 methodM2.parameters = <ParameterElement>[ |
| 4978 parameter3, |
| 4979 parameter4, |
| 4980 parameter5 |
| 4981 ]; |
| 4982 classI2.methods = <MethodElement>[methodM2]; |
| 4983 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 4984 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 4985 MemberMap mapA = |
| 4986 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 4987 expect(mapA.size, _numOfMembersInObject); |
| 4988 expect(mapA.get(methodName), isNull); |
| 4989 _assertErrors( |
| 4990 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); |
| 4991 } |
| 4992 |
| 4993 void test_getMapOfMembersInheritedFromInterfaces_inconsistentMethodInheritance
_str_int() { |
| 4994 // class I1 { int m(); } |
| 4995 // class I2 { String m(); } |
| 4996 // class A implements I2, I1 {} |
| 4997 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 4998 String methodName = "m"; |
| 4999 MethodElement methodM1 = ElementFactory.methodElement( |
| 5000 methodName, null, [_typeProvider.stringType]); |
| 5001 classI1.methods = <MethodElement>[methodM1]; |
| 5002 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5003 MethodElement methodM2 = |
| 5004 ElementFactory.methodElement(methodName, null, [_typeProvider.intType]); |
| 5005 classI2.methods = <MethodElement>[methodM2]; |
| 5006 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5007 classA.interfaces = <InterfaceType>[classI2.type, classI1.type]; |
| 5008 MemberMap mapA = |
| 5009 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5010 expect(mapA.size, _numOfMembersInObject); |
| 5011 expect(mapA.get(methodName), isNull); |
| 5012 _assertErrors( |
| 5013 classA, [StaticTypeWarningCode.INCONSISTENT_METHOD_INHERITANCE]); |
| 5014 } |
| 5015 |
| 5016 void test_getMapOfMembersInheritedFromInterfaces_method_extends() { |
| 5017 // class A { int g(); } |
| 5018 // class B extends A {} |
| 5019 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5020 String methodName = "m"; |
| 5021 MethodElement methodM = |
| 5022 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5023 classA.methods = <MethodElement>[methodM]; |
| 5024 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5025 MemberMap mapB = |
| 5026 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 5027 MemberMap mapA = |
| 5028 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5029 expect(mapA.size, _numOfMembersInObject); |
| 5030 expect(mapB.size, _numOfMembersInObject + 1); |
| 5031 expect(mapB.get(methodName), same(methodM)); |
| 5032 _assertNoErrors(classA); |
| 5033 _assertNoErrors(classB); |
| 5034 } |
| 5035 |
| 5036 void test_getMapOfMembersInheritedFromInterfaces_method_implements() { |
| 5037 // class A { int g(); } |
| 5038 // class B implements A {} |
| 5039 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5040 String methodName = "m"; |
| 5041 MethodElement methodM = |
| 5042 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5043 classA.methods = <MethodElement>[methodM]; |
| 5044 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5045 classB.interfaces = <InterfaceType>[classA.type]; |
| 5046 MemberMap mapB = |
| 5047 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 5048 MemberMap mapA = |
| 5049 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5050 expect(mapA.size, _numOfMembersInObject); |
| 5051 expect(mapB.size, _numOfMembersInObject + 1); |
| 5052 expect(mapB.get(methodName), same(methodM)); |
| 5053 _assertNoErrors(classA); |
| 5054 _assertNoErrors(classB); |
| 5055 } |
| 5056 |
| 5057 void test_getMapOfMembersInheritedFromInterfaces_method_with() { |
| 5058 // class A { int g(); } |
| 5059 // class B extends Object with A {} |
| 5060 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5061 String methodName = "m"; |
| 5062 MethodElement methodM = |
| 5063 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5064 classA.methods = <MethodElement>[methodM]; |
| 5065 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5066 classB.mixins = <InterfaceType>[classA.type]; |
| 5067 MemberMap mapB = |
| 5068 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classB); |
| 5069 MemberMap mapA = |
| 5070 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5071 expect(mapA.size, _numOfMembersInObject); |
| 5072 expect(mapB.size, _numOfMembersInObject + 1); |
| 5073 expect(mapB.get(methodName), same(methodM)); |
| 5074 _assertNoErrors(classA); |
| 5075 _assertNoErrors(classB); |
| 5076 } |
| 5077 |
| 5078 void test_getMapOfMembersInheritedFromInterfaces_union_differentNames() { |
| 5079 // class I1 { int m1(); } |
| 5080 // class I2 { int m2(); } |
| 5081 // class A implements I1, I2 {} |
| 5082 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5083 String methodName1 = "m1"; |
| 5084 MethodElement methodM1 = |
| 5085 ElementFactory.methodElement(methodName1, _typeProvider.intType); |
| 5086 classI1.methods = <MethodElement>[methodM1]; |
| 5087 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5088 String methodName2 = "m2"; |
| 5089 MethodElement methodM2 = |
| 5090 ElementFactory.methodElement(methodName2, _typeProvider.intType); |
| 5091 classI2.methods = <MethodElement>[methodM2]; |
| 5092 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5093 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5094 MemberMap mapA = |
| 5095 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5096 expect(mapA.size, _numOfMembersInObject + 2); |
| 5097 expect(mapA.get(methodName1), same(methodM1)); |
| 5098 expect(mapA.get(methodName2), same(methodM2)); |
| 5099 _assertNoErrors(classA); |
| 5100 } |
| 5101 |
| 5102 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_gett
ers() { |
| 5103 // class I1 { int get g; } |
| 5104 // class I2 { num get g; } |
| 5105 // class A implements I1, I2 {} |
| 5106 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5107 String accessorName = "g"; |
| 5108 PropertyAccessorElement getter1 = ElementFactory.getterElement( |
| 5109 accessorName, false, _typeProvider.intType); |
| 5110 classI1.accessors = <PropertyAccessorElement>[getter1]; |
| 5111 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5112 PropertyAccessorElement getter2 = ElementFactory.getterElement( |
| 5113 accessorName, false, _typeProvider.numType); |
| 5114 classI2.accessors = <PropertyAccessorElement>[getter2]; |
| 5115 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5116 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5117 MemberMap mapA = |
| 5118 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5119 expect(mapA.size, _numOfMembersInObject + 1); |
| 5120 PropertyAccessorElement syntheticAccessor = ElementFactory.getterElement( |
| 5121 accessorName, false, _typeProvider.dynamicType); |
| 5122 expect(mapA.get(accessorName).type, syntheticAccessor.type); |
| 5123 _assertNoErrors(classA); |
| 5124 } |
| 5125 |
| 5126 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_meth
ods() { |
| 5127 // class I1 { dynamic m(int); } |
| 5128 // class I2 { dynamic m(num); } |
| 5129 // class A implements I1, I2 {} |
| 5130 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5131 String methodName = "m"; |
| 5132 MethodElementImpl methodM1 = |
| 5133 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5134 ParameterElementImpl parameter1 = |
| 5135 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5136 parameter1.type = _typeProvider.intType; |
| 5137 parameter1.parameterKind = ParameterKind.REQUIRED; |
| 5138 methodM1.parameters = <ParameterElement>[parameter1]; |
| 5139 classI1.methods = <MethodElement>[methodM1]; |
| 5140 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5141 MethodElementImpl methodM2 = |
| 5142 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5143 ParameterElementImpl parameter2 = |
| 5144 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5145 parameter2.type = _typeProvider.numType; |
| 5146 parameter2.parameterKind = ParameterKind.REQUIRED; |
| 5147 methodM2.parameters = <ParameterElement>[parameter2]; |
| 5148 classI2.methods = <MethodElement>[methodM2]; |
| 5149 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5150 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5151 MemberMap mapA = |
| 5152 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5153 expect(mapA.size, _numOfMembersInObject + 1); |
| 5154 MethodElement syntheticMethod = ElementFactory.methodElement( |
| 5155 methodName, _typeProvider.dynamicType, [_typeProvider.dynamicType]); |
| 5156 expect(mapA.get(methodName).type, syntheticMethod.type); |
| 5157 _assertNoErrors(classA); |
| 5158 } |
| 5159 |
| 5160 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_2_sett
ers() { |
| 5161 // class I1 { set s(int); } |
| 5162 // class I2 { set s(num); } |
| 5163 // class A implements I1, I2 {} |
| 5164 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5165 String accessorName = "s"; |
| 5166 PropertyAccessorElement setter1 = ElementFactory.setterElement( |
| 5167 accessorName, false, _typeProvider.intType); |
| 5168 classI1.accessors = <PropertyAccessorElement>[setter1]; |
| 5169 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5170 PropertyAccessorElement setter2 = ElementFactory.setterElement( |
| 5171 accessorName, false, _typeProvider.numType); |
| 5172 classI2.accessors = <PropertyAccessorElement>[setter2]; |
| 5173 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5174 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5175 MemberMap mapA = |
| 5176 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5177 expect(mapA.size, _numOfMembersInObject + 1); |
| 5178 PropertyAccessorElementImpl syntheticAccessor = ElementFactory |
| 5179 .setterElement(accessorName, false, _typeProvider.dynamicType); |
| 5180 syntheticAccessor.returnType = _typeProvider.dynamicType; |
| 5181 expect(mapA.get("$accessorName=").type, syntheticAccessor.type); |
| 5182 _assertNoErrors(classA); |
| 5183 } |
| 5184 |
| 5185 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_gett
ers() { |
| 5186 // class A {} |
| 5187 // class B extends A {} |
| 5188 // class C extends B {} |
| 5189 // class I1 { A get g; } |
| 5190 // class I2 { B get g; } |
| 5191 // class I3 { C get g; } |
| 5192 // class D implements I1, I2, I3 {} |
| 5193 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5194 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5195 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); |
| 5196 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5197 String accessorName = "g"; |
| 5198 PropertyAccessorElement getter1 = |
| 5199 ElementFactory.getterElement(accessorName, false, classA.type); |
| 5200 classI1.accessors = <PropertyAccessorElement>[getter1]; |
| 5201 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5202 PropertyAccessorElement getter2 = |
| 5203 ElementFactory.getterElement(accessorName, false, classB.type); |
| 5204 classI2.accessors = <PropertyAccessorElement>[getter2]; |
| 5205 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5206 PropertyAccessorElement getter3 = |
| 5207 ElementFactory.getterElement(accessorName, false, classC.type); |
| 5208 classI3.accessors = <PropertyAccessorElement>[getter3]; |
| 5209 ClassElementImpl classD = ElementFactory.classElement2("D"); |
| 5210 classD.interfaces = <InterfaceType>[ |
| 5211 classI1.type, |
| 5212 classI2.type, |
| 5213 classI3.type |
| 5214 ]; |
| 5215 MemberMap mapD = |
| 5216 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); |
| 5217 expect(mapD.size, _numOfMembersInObject + 1); |
| 5218 PropertyAccessorElement syntheticAccessor = ElementFactory.getterElement( |
| 5219 accessorName, false, _typeProvider.dynamicType); |
| 5220 expect(mapD.get(accessorName).type, syntheticAccessor.type); |
| 5221 _assertNoErrors(classD); |
| 5222 } |
| 5223 |
| 5224 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_meth
ods() { |
| 5225 // class A {} |
| 5226 // class B extends A {} |
| 5227 // class C extends B {} |
| 5228 // class I1 { dynamic m(A a); } |
| 5229 // class I2 { dynamic m(B b); } |
| 5230 // class I3 { dynamic m(C c); } |
| 5231 // class D implements I1, I2, I3 {} |
| 5232 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5233 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5234 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); |
| 5235 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5236 String methodName = "m"; |
| 5237 MethodElementImpl methodM1 = |
| 5238 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5239 ParameterElementImpl parameter1 = |
| 5240 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5241 parameter1.type = classA.type; |
| 5242 parameter1.parameterKind = ParameterKind.REQUIRED; |
| 5243 methodM1.parameters = <ParameterElement>[parameter1]; |
| 5244 classI1.methods = <MethodElement>[methodM1]; |
| 5245 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5246 MethodElementImpl methodM2 = |
| 5247 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5248 ParameterElementImpl parameter2 = |
| 5249 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5250 parameter2.type = classB.type; |
| 5251 parameter2.parameterKind = ParameterKind.REQUIRED; |
| 5252 methodM2.parameters = <ParameterElement>[parameter2]; |
| 5253 classI2.methods = <MethodElement>[methodM2]; |
| 5254 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5255 MethodElementImpl methodM3 = |
| 5256 ElementFactory.methodElement(methodName, _typeProvider.dynamicType); |
| 5257 ParameterElementImpl parameter3 = |
| 5258 new ParameterElementImpl.forNode(AstFactory.identifier3("a0")); |
| 5259 parameter3.type = classC.type; |
| 5260 parameter3.parameterKind = ParameterKind.REQUIRED; |
| 5261 methodM3.parameters = <ParameterElement>[parameter3]; |
| 5262 classI3.methods = <MethodElement>[methodM3]; |
| 5263 ClassElementImpl classD = ElementFactory.classElement2("D"); |
| 5264 classD.interfaces = <InterfaceType>[ |
| 5265 classI1.type, |
| 5266 classI2.type, |
| 5267 classI3.type |
| 5268 ]; |
| 5269 MemberMap mapD = |
| 5270 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); |
| 5271 expect(mapD.size, _numOfMembersInObject + 1); |
| 5272 MethodElement syntheticMethod = ElementFactory.methodElement( |
| 5273 methodName, _typeProvider.dynamicType, [_typeProvider.dynamicType]); |
| 5274 expect(mapD.get(methodName).type, syntheticMethod.type); |
| 5275 _assertNoErrors(classD); |
| 5276 } |
| 5277 |
| 5278 void test_getMapOfMembersInheritedFromInterfaces_union_multipleSubtypes_3_sett
ers() { |
| 5279 // class A {} |
| 5280 // class B extends A {} |
| 5281 // class C extends B {} |
| 5282 // class I1 { set s(A); } |
| 5283 // class I2 { set s(B); } |
| 5284 // class I3 { set s(C); } |
| 5285 // class D implements I1, I2, I3 {} |
| 5286 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5287 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5288 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); |
| 5289 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5290 String accessorName = "s"; |
| 5291 PropertyAccessorElement setter1 = |
| 5292 ElementFactory.setterElement(accessorName, false, classA.type); |
| 5293 classI1.accessors = <PropertyAccessorElement>[setter1]; |
| 5294 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5295 PropertyAccessorElement setter2 = |
| 5296 ElementFactory.setterElement(accessorName, false, classB.type); |
| 5297 classI2.accessors = <PropertyAccessorElement>[setter2]; |
| 5298 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5299 PropertyAccessorElement setter3 = |
| 5300 ElementFactory.setterElement(accessorName, false, classC.type); |
| 5301 classI3.accessors = <PropertyAccessorElement>[setter3]; |
| 5302 ClassElementImpl classD = ElementFactory.classElement2("D"); |
| 5303 classD.interfaces = <InterfaceType>[ |
| 5304 classI1.type, |
| 5305 classI2.type, |
| 5306 classI3.type |
| 5307 ]; |
| 5308 MemberMap mapD = |
| 5309 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classD); |
| 5310 expect(mapD.size, _numOfMembersInObject + 1); |
| 5311 PropertyAccessorElementImpl syntheticAccessor = ElementFactory |
| 5312 .setterElement(accessorName, false, _typeProvider.dynamicType); |
| 5313 syntheticAccessor.returnType = _typeProvider.dynamicType; |
| 5314 expect(mapD.get("$accessorName=").type, syntheticAccessor.type); |
| 5315 _assertNoErrors(classD); |
| 5316 } |
| 5317 |
| 5318 void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_2_methods()
{ |
| 5319 // class I1 { int m(); } |
| 5320 // class I2 { int m([int]); } |
| 5321 // class A implements I1, I2 {} |
| 5322 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5323 String methodName = "m"; |
| 5324 MethodElement methodM1 = |
| 5325 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5326 classI1.methods = <MethodElement>[methodM1]; |
| 5327 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5328 MethodElementImpl methodM2 = |
| 5329 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5330 ParameterElementImpl parameter1 = |
| 5331 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); |
| 5332 parameter1.type = _typeProvider.intType; |
| 5333 parameter1.parameterKind = ParameterKind.POSITIONAL; |
| 5334 methodM2.parameters = <ParameterElement>[parameter1]; |
| 5335 classI2.methods = <MethodElement>[methodM2]; |
| 5336 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5337 classA.interfaces = <InterfaceType>[classI1.type, classI2.type]; |
| 5338 MemberMap mapA = |
| 5339 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5340 expect(mapA.size, _numOfMembersInObject + 1); |
| 5341 expect(mapA.get(methodName), same(methodM2)); |
| 5342 _assertNoErrors(classA); |
| 5343 } |
| 5344 |
| 5345 void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_3_methods()
{ |
| 5346 // class I1 { int m(); } |
| 5347 // class I2 { int m([int]); } |
| 5348 // class I3 { int m([int, int]); } |
| 5349 // class A implements I1, I2, I3 {} |
| 5350 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5351 String methodName = "m"; |
| 5352 MethodElementImpl methodM1 = |
| 5353 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5354 classI1.methods = <MethodElement>[methodM1]; |
| 5355 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5356 MethodElementImpl methodM2 = |
| 5357 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5358 ParameterElementImpl parameter1 = |
| 5359 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); |
| 5360 parameter1.type = _typeProvider.intType; |
| 5361 parameter1.parameterKind = ParameterKind.POSITIONAL; |
| 5362 methodM1.parameters = <ParameterElement>[parameter1]; |
| 5363 classI2.methods = <MethodElement>[methodM2]; |
| 5364 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5365 MethodElementImpl methodM3 = |
| 5366 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5367 ParameterElementImpl parameter2 = |
| 5368 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); |
| 5369 parameter2.type = _typeProvider.intType; |
| 5370 parameter2.parameterKind = ParameterKind.POSITIONAL; |
| 5371 ParameterElementImpl parameter3 = |
| 5372 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); |
| 5373 parameter3.type = _typeProvider.intType; |
| 5374 parameter3.parameterKind = ParameterKind.POSITIONAL; |
| 5375 methodM3.parameters = <ParameterElement>[parameter2, parameter3]; |
| 5376 classI3.methods = <MethodElement>[methodM3]; |
| 5377 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5378 classA.interfaces = <InterfaceType>[ |
| 5379 classI1.type, |
| 5380 classI2.type, |
| 5381 classI3.type |
| 5382 ]; |
| 5383 MemberMap mapA = |
| 5384 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5385 expect(mapA.size, _numOfMembersInObject + 1); |
| 5386 expect(mapA.get(methodName), same(methodM3)); |
| 5387 _assertNoErrors(classA); |
| 5388 } |
| 5389 |
| 5390 void test_getMapOfMembersInheritedFromInterfaces_union_oneSubtype_4_methods()
{ |
| 5391 // class I1 { int m(); } |
| 5392 // class I2 { int m(); } |
| 5393 // class I3 { int m([int]); } |
| 5394 // class I4 { int m([int, int]); } |
| 5395 // class A implements I1, I2, I3, I4 {} |
| 5396 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5397 String methodName = "m"; |
| 5398 MethodElement methodM1 = |
| 5399 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5400 classI1.methods = <MethodElement>[methodM1]; |
| 5401 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5402 MethodElement methodM2 = |
| 5403 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5404 classI2.methods = <MethodElement>[methodM2]; |
| 5405 ClassElementImpl classI3 = ElementFactory.classElement2("I3"); |
| 5406 MethodElementImpl methodM3 = |
| 5407 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5408 ParameterElementImpl parameter1 = |
| 5409 new ParameterElementImpl.forNode(AstFactory.identifier3("a1")); |
| 5410 parameter1.type = _typeProvider.intType; |
| 5411 parameter1.parameterKind = ParameterKind.POSITIONAL; |
| 5412 methodM3.parameters = <ParameterElement>[parameter1]; |
| 5413 classI3.methods = <MethodElement>[methodM3]; |
| 5414 ClassElementImpl classI4 = ElementFactory.classElement2("I4"); |
| 5415 MethodElementImpl methodM4 = |
| 5416 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5417 ParameterElementImpl parameter2 = |
| 5418 new ParameterElementImpl.forNode(AstFactory.identifier3("a2")); |
| 5419 parameter2.type = _typeProvider.intType; |
| 5420 parameter2.parameterKind = ParameterKind.POSITIONAL; |
| 5421 ParameterElementImpl parameter3 = |
| 5422 new ParameterElementImpl.forNode(AstFactory.identifier3("a3")); |
| 5423 parameter3.type = _typeProvider.intType; |
| 5424 parameter3.parameterKind = ParameterKind.POSITIONAL; |
| 5425 methodM4.parameters = <ParameterElement>[parameter2, parameter3]; |
| 5426 classI4.methods = <MethodElement>[methodM4]; |
| 5427 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5428 classA.interfaces = <InterfaceType>[ |
| 5429 classI1.type, |
| 5430 classI2.type, |
| 5431 classI3.type, |
| 5432 classI4.type |
| 5433 ]; |
| 5434 MemberMap mapA = |
| 5435 _inheritanceManager.getMapOfMembersInheritedFromInterfaces(classA); |
| 5436 expect(mapA.size, _numOfMembersInObject + 1); |
| 5437 expect(mapA.get(methodName), same(methodM4)); |
| 5438 _assertNoErrors(classA); |
| 5439 } |
| 5440 |
| 5441 void test_lookupInheritance_interface_getter() { |
| 5442 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5443 String getterName = "g"; |
| 5444 PropertyAccessorElement getterG = |
| 5445 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 5446 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5447 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5448 classB.interfaces = <InterfaceType>[classA.type]; |
| 5449 expect(_inheritanceManager.lookupInheritance(classB, getterName), |
| 5450 same(getterG)); |
| 5451 _assertNoErrors(classA); |
| 5452 _assertNoErrors(classB); |
| 5453 } |
| 5454 |
| 5455 void test_lookupInheritance_interface_method() { |
| 5456 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5457 String methodName = "m"; |
| 5458 MethodElement methodM = |
| 5459 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5460 classA.methods = <MethodElement>[methodM]; |
| 5461 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5462 classB.interfaces = <InterfaceType>[classA.type]; |
| 5463 expect(_inheritanceManager.lookupInheritance(classB, methodName), |
| 5464 same(methodM)); |
| 5465 _assertNoErrors(classA); |
| 5466 _assertNoErrors(classB); |
| 5467 } |
| 5468 |
| 5469 void test_lookupInheritance_interface_setter() { |
| 5470 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5471 String setterName = "s"; |
| 5472 PropertyAccessorElement setterS = |
| 5473 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 5474 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5475 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5476 classB.interfaces = <InterfaceType>[classA.type]; |
| 5477 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), |
| 5478 same(setterS)); |
| 5479 _assertNoErrors(classA); |
| 5480 _assertNoErrors(classB); |
| 5481 } |
| 5482 |
| 5483 void test_lookupInheritance_interface_staticMember() { |
| 5484 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5485 String methodName = "m"; |
| 5486 MethodElement methodM = |
| 5487 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5488 (methodM as MethodElementImpl).static = true; |
| 5489 classA.methods = <MethodElement>[methodM]; |
| 5490 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5491 classB.interfaces = <InterfaceType>[classA.type]; |
| 5492 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); |
| 5493 _assertNoErrors(classA); |
| 5494 _assertNoErrors(classB); |
| 5495 } |
| 5496 |
| 5497 void test_lookupInheritance_interfaces_infiniteLoop() { |
| 5498 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5499 classA.interfaces = <InterfaceType>[classA.type]; |
| 5500 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); |
| 5501 _assertNoErrors(classA); |
| 5502 } |
| 5503 |
| 5504 void test_lookupInheritance_interfaces_infiniteLoop2() { |
| 5505 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5506 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5507 classA.interfaces = <InterfaceType>[classB.type]; |
| 5508 classB.interfaces = <InterfaceType>[classA.type]; |
| 5509 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); |
| 5510 _assertNoErrors(classA); |
| 5511 _assertNoErrors(classB); |
| 5512 } |
| 5513 |
| 5514 void test_lookupInheritance_interfaces_union2() { |
| 5515 ClassElementImpl classI1 = ElementFactory.classElement2("I1"); |
| 5516 String methodName1 = "m1"; |
| 5517 MethodElement methodM1 = |
| 5518 ElementFactory.methodElement(methodName1, _typeProvider.intType); |
| 5519 classI1.methods = <MethodElement>[methodM1]; |
| 5520 ClassElementImpl classI2 = ElementFactory.classElement2("I2"); |
| 5521 String methodName2 = "m2"; |
| 5522 MethodElement methodM2 = |
| 5523 ElementFactory.methodElement(methodName2, _typeProvider.intType); |
| 5524 classI2.methods = <MethodElement>[methodM2]; |
| 5525 classI2.interfaces = <InterfaceType>[classI1.type]; |
| 5526 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5527 classA.interfaces = <InterfaceType>[classI2.type]; |
| 5528 expect(_inheritanceManager.lookupInheritance(classA, methodName1), |
| 5529 same(methodM1)); |
| 5530 expect(_inheritanceManager.lookupInheritance(classA, methodName2), |
| 5531 same(methodM2)); |
| 5532 _assertNoErrors(classI1); |
| 5533 _assertNoErrors(classI2); |
| 5534 _assertNoErrors(classA); |
| 5535 } |
| 5536 |
| 5537 void test_lookupInheritance_mixin_getter() { |
| 5538 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5539 String getterName = "g"; |
| 5540 PropertyAccessorElement getterG = |
| 5541 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 5542 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5543 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5544 classB.mixins = <InterfaceType>[classA.type]; |
| 5545 expect(_inheritanceManager.lookupInheritance(classB, getterName), |
| 5546 same(getterG)); |
| 5547 _assertNoErrors(classA); |
| 5548 _assertNoErrors(classB); |
| 5549 } |
| 5550 |
| 5551 void test_lookupInheritance_mixin_method() { |
| 5552 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5553 String methodName = "m"; |
| 5554 MethodElement methodM = |
| 5555 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5556 classA.methods = <MethodElement>[methodM]; |
| 5557 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5558 classB.mixins = <InterfaceType>[classA.type]; |
| 5559 expect(_inheritanceManager.lookupInheritance(classB, methodName), |
| 5560 same(methodM)); |
| 5561 _assertNoErrors(classA); |
| 5562 _assertNoErrors(classB); |
| 5563 } |
| 5564 |
| 5565 void test_lookupInheritance_mixin_setter() { |
| 5566 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5567 String setterName = "s"; |
| 5568 PropertyAccessorElement setterS = |
| 5569 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 5570 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5571 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5572 classB.mixins = <InterfaceType>[classA.type]; |
| 5573 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), |
| 5574 same(setterS)); |
| 5575 _assertNoErrors(classA); |
| 5576 _assertNoErrors(classB); |
| 5577 } |
| 5578 |
| 5579 void test_lookupInheritance_mixin_staticMember() { |
| 5580 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5581 String methodName = "m"; |
| 5582 MethodElement methodM = |
| 5583 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5584 (methodM as MethodElementImpl).static = true; |
| 5585 classA.methods = <MethodElement>[methodM]; |
| 5586 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5587 classB.mixins = <InterfaceType>[classA.type]; |
| 5588 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); |
| 5589 _assertNoErrors(classA); |
| 5590 _assertNoErrors(classB); |
| 5591 } |
| 5592 |
| 5593 void test_lookupInheritance_noMember() { |
| 5594 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5595 expect(_inheritanceManager.lookupInheritance(classA, "a"), isNull); |
| 5596 _assertNoErrors(classA); |
| 5597 } |
| 5598 |
| 5599 void test_lookupInheritance_superclass_getter() { |
| 5600 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5601 String getterName = "g"; |
| 5602 PropertyAccessorElement getterG = |
| 5603 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 5604 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5605 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5606 expect(_inheritanceManager.lookupInheritance(classB, getterName), |
| 5607 same(getterG)); |
| 5608 _assertNoErrors(classA); |
| 5609 _assertNoErrors(classB); |
| 5610 } |
| 5611 |
| 5612 void test_lookupInheritance_superclass_infiniteLoop() { |
| 5613 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5614 classA.supertype = classA.type; |
| 5615 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); |
| 5616 _assertNoErrors(classA); |
| 5617 } |
| 5618 |
| 5619 void test_lookupInheritance_superclass_infiniteLoop2() { |
| 5620 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5621 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5622 classA.supertype = classB.type; |
| 5623 classB.supertype = classA.type; |
| 5624 expect(_inheritanceManager.lookupInheritance(classA, "name"), isNull); |
| 5625 _assertNoErrors(classA); |
| 5626 _assertNoErrors(classB); |
| 5627 } |
| 5628 |
| 5629 void test_lookupInheritance_superclass_method() { |
| 5630 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5631 String methodName = "m"; |
| 5632 MethodElement methodM = |
| 5633 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5634 classA.methods = <MethodElement>[methodM]; |
| 5635 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5636 expect(_inheritanceManager.lookupInheritance(classB, methodName), |
| 5637 same(methodM)); |
| 5638 _assertNoErrors(classA); |
| 5639 _assertNoErrors(classB); |
| 5640 } |
| 5641 |
| 5642 void test_lookupInheritance_superclass_setter() { |
| 5643 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5644 String setterName = "s"; |
| 5645 PropertyAccessorElement setterS = |
| 5646 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 5647 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5648 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5649 expect(_inheritanceManager.lookupInheritance(classB, "$setterName="), |
| 5650 same(setterS)); |
| 5651 _assertNoErrors(classA); |
| 5652 _assertNoErrors(classB); |
| 5653 } |
| 5654 |
| 5655 void test_lookupInheritance_superclass_staticMember() { |
| 5656 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5657 String methodName = "m"; |
| 5658 MethodElement methodM = |
| 5659 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5660 (methodM as MethodElementImpl).static = true; |
| 5661 classA.methods = <MethodElement>[methodM]; |
| 5662 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5663 expect(_inheritanceManager.lookupInheritance(classB, methodName), isNull); |
| 5664 _assertNoErrors(classA); |
| 5665 _assertNoErrors(classB); |
| 5666 } |
| 5667 |
| 5668 void test_lookupMember_getter() { |
| 5669 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5670 String getterName = "g"; |
| 5671 PropertyAccessorElement getterG = |
| 5672 ElementFactory.getterElement(getterName, false, _typeProvider.intType); |
| 5673 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5674 expect(_inheritanceManager.lookupMember(classA, getterName), same(getterG)); |
| 5675 _assertNoErrors(classA); |
| 5676 } |
| 5677 |
| 5678 void test_lookupMember_getter_static() { |
| 5679 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5680 String getterName = "g"; |
| 5681 PropertyAccessorElement getterG = |
| 5682 ElementFactory.getterElement(getterName, true, _typeProvider.intType); |
| 5683 classA.accessors = <PropertyAccessorElement>[getterG]; |
| 5684 expect(_inheritanceManager.lookupMember(classA, getterName), isNull); |
| 5685 _assertNoErrors(classA); |
| 5686 } |
| 5687 |
| 5688 void test_lookupMember_method() { |
| 5689 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5690 String methodName = "m"; |
| 5691 MethodElement methodM = |
| 5692 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5693 classA.methods = <MethodElement>[methodM]; |
| 5694 expect(_inheritanceManager.lookupMember(classA, methodName), same(methodM)); |
| 5695 _assertNoErrors(classA); |
| 5696 } |
| 5697 |
| 5698 void test_lookupMember_method_static() { |
| 5699 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5700 String methodName = "m"; |
| 5701 MethodElement methodM = |
| 5702 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5703 (methodM as MethodElementImpl).static = true; |
| 5704 classA.methods = <MethodElement>[methodM]; |
| 5705 expect(_inheritanceManager.lookupMember(classA, methodName), isNull); |
| 5706 _assertNoErrors(classA); |
| 5707 } |
| 5708 |
| 5709 void test_lookupMember_noMember() { |
| 5710 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5711 expect(_inheritanceManager.lookupMember(classA, "a"), isNull); |
| 5712 _assertNoErrors(classA); |
| 5713 } |
| 5714 |
| 5715 void test_lookupMember_setter() { |
| 5716 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5717 String setterName = "s"; |
| 5718 PropertyAccessorElement setterS = |
| 5719 ElementFactory.setterElement(setterName, false, _typeProvider.intType); |
| 5720 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5721 expect(_inheritanceManager.lookupMember(classA, "$setterName="), |
| 5722 same(setterS)); |
| 5723 _assertNoErrors(classA); |
| 5724 } |
| 5725 |
| 5726 void test_lookupMember_setter_static() { |
| 5727 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5728 String setterName = "s"; |
| 5729 PropertyAccessorElement setterS = |
| 5730 ElementFactory.setterElement(setterName, true, _typeProvider.intType); |
| 5731 classA.accessors = <PropertyAccessorElement>[setterS]; |
| 5732 expect(_inheritanceManager.lookupMember(classA, setterName), isNull); |
| 5733 _assertNoErrors(classA); |
| 5734 } |
| 5735 |
| 5736 void test_lookupOverrides_noParentClasses() { |
| 5737 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5738 String methodName = "m"; |
| 5739 MethodElementImpl methodM = |
| 5740 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5741 classA.methods = <MethodElement>[methodM]; |
| 5742 expect( |
| 5743 _inheritanceManager.lookupOverrides(classA, methodName), hasLength(0)); |
| 5744 _assertNoErrors(classA); |
| 5745 } |
| 5746 |
| 5747 void test_lookupOverrides_overrideBaseClass() { |
| 5748 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5749 String methodName = "m"; |
| 5750 MethodElementImpl methodMinA = |
| 5751 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5752 classA.methods = <MethodElement>[methodMinA]; |
| 5753 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 5754 MethodElementImpl methodMinB = |
| 5755 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5756 classB.methods = <MethodElement>[methodMinB]; |
| 5757 List<ExecutableElement> overrides = |
| 5758 _inheritanceManager.lookupOverrides(classB, methodName); |
| 5759 expect(overrides, unorderedEquals([methodMinA])); |
| 5760 _assertNoErrors(classA); |
| 5761 _assertNoErrors(classB); |
| 5762 } |
| 5763 |
| 5764 void test_lookupOverrides_overrideInterface() { |
| 5765 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5766 String methodName = "m"; |
| 5767 MethodElementImpl methodMinA = |
| 5768 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5769 classA.methods = <MethodElement>[methodMinA]; |
| 5770 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5771 classB.interfaces = <InterfaceType>[classA.type]; |
| 5772 MethodElementImpl methodMinB = |
| 5773 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5774 classB.methods = <MethodElement>[methodMinB]; |
| 5775 List<ExecutableElement> overrides = |
| 5776 _inheritanceManager.lookupOverrides(classB, methodName); |
| 5777 expect(overrides, unorderedEquals([methodMinA])); |
| 5778 _assertNoErrors(classA); |
| 5779 _assertNoErrors(classB); |
| 5780 } |
| 5781 |
| 5782 void test_lookupOverrides_overrideTwoInterfaces() { |
| 5783 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 5784 String methodName = "m"; |
| 5785 MethodElementImpl methodMinA = |
| 5786 ElementFactory.methodElement(methodName, _typeProvider.intType); |
| 5787 classA.methods = <MethodElement>[methodMinA]; |
| 5788 ClassElementImpl classB = ElementFactory.classElement2("B"); |
| 5789 MethodElementImpl methodMinB = |
| 5790 ElementFactory.methodElement(methodName, _typeProvider.doubleType); |
| 5791 classB.methods = <MethodElement>[methodMinB]; |
| 5792 ClassElementImpl classC = ElementFactory.classElement2("C"); |
| 5793 classC.interfaces = <InterfaceType>[classA.type, classB.type]; |
| 5794 MethodElementImpl methodMinC = |
| 5795 ElementFactory.methodElement(methodName, _typeProvider.numType); |
| 5796 classC.methods = <MethodElement>[methodMinC]; |
| 5797 List<ExecutableElement> overrides = |
| 5798 _inheritanceManager.lookupOverrides(classC, methodName); |
| 5799 expect(overrides, unorderedEquals([methodMinA, methodMinB])); |
| 5800 _assertNoErrors(classA); |
| 5801 _assertNoErrors(classB); |
| 5802 _assertNoErrors(classC); |
| 5803 } |
| 5804 |
| 5805 void _assertErrors(ClassElement classElt, |
| 5806 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { |
| 5807 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 5808 HashSet<AnalysisError> actualErrors = |
| 5809 _inheritanceManager.getErrors(classElt); |
| 5810 if (actualErrors != null) { |
| 5811 for (AnalysisError error in actualErrors) { |
| 5812 errorListener.onError(error); |
| 5813 } |
| 5814 } |
| 5815 errorListener.assertErrorsWithCodes(expectedErrorCodes); |
| 5816 } |
| 5817 |
| 5818 void _assertNoErrors(ClassElement classElt) { |
| 5819 _assertErrors(classElt); |
| 5820 } |
| 5821 |
| 5822 /** |
| 5823 * Create the inheritance manager used by the tests. |
| 5824 * |
| 5825 * @return the inheritance manager that was created |
| 5826 */ |
| 5827 InheritanceManager _createInheritanceManager() { |
| 5828 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 5829 FileBasedSource source = |
| 5830 new FileBasedSource(FileUtilities2.createFile("/test.dart")); |
| 5831 CompilationUnitElementImpl definingCompilationUnit = |
| 5832 new CompilationUnitElementImpl("test.dart"); |
| 5833 definingCompilationUnit.librarySource = |
| 5834 definingCompilationUnit.source = source; |
| 5835 _definingLibrary = ElementFactory.library(context, "test"); |
| 5836 _definingLibrary.definingCompilationUnit = definingCompilationUnit; |
| 5837 return new InheritanceManager(_definingLibrary); |
| 5838 } |
| 5839 } |
| 5840 |
| 5841 @reflectiveTest |
| 5842 class LibraryElementBuilderTest extends EngineTestCase { |
| 5843 /** |
| 5844 * The analysis context used to analyze sources. |
| 5845 */ |
| 5846 InternalAnalysisContext _context; |
| 5847 |
| 5848 /** |
| 5849 * Add a source file to the content provider. The file path should be absolute
. |
| 5850 * |
| 5851 * @param filePath the path of the file being added |
| 5852 * @param contents the contents to be returned by the content provider for the
specified file |
| 5853 * @return the source object representing the added file |
| 5854 */ |
| 5855 Source addSource(String filePath, String contents) { |
| 5856 Source source = new FileBasedSource(FileUtilities2.createFile(filePath)); |
| 5857 _context.setContents(source, contents); |
| 5858 return source; |
| 5859 } |
| 5860 |
| 5861 @override |
| 5862 void setUp() { |
| 5863 _context = AnalysisContextFactory.contextWithCore(); |
| 5864 } |
| 5865 |
| 5866 @override |
| 5867 void tearDown() { |
| 5868 _context = null; |
| 5869 super.tearDown(); |
| 5870 } |
| 5871 |
| 5872 void test_accessorsAcrossFiles() { |
| 5873 Source librarySource = addSource( |
| 5874 "/lib.dart", |
| 5875 r''' |
| 5876 library lib; |
| 5877 part 'first.dart'; |
| 5878 part 'second.dart';'''); |
| 5879 addSource( |
| 5880 "/first.dart", |
| 5881 r''' |
| 5882 part of lib; |
| 5883 int get V => 0;'''); |
| 5884 addSource( |
| 5885 "/second.dart", |
| 5886 r''' |
| 5887 part of lib; |
| 5888 void set V(int v) {}'''); |
| 5889 LibraryElement element = _buildLibrary(librarySource); |
| 5890 expect(element, isNotNull); |
| 5891 List<CompilationUnitElement> sourcedUnits = element.parts; |
| 5892 expect(sourcedUnits, hasLength(2)); |
| 5893 List<PropertyAccessorElement> firstAccessors = sourcedUnits[0].accessors; |
| 5894 expect(firstAccessors, hasLength(1)); |
| 5895 List<PropertyAccessorElement> secondAccessors = sourcedUnits[1].accessors; |
| 5896 expect(secondAccessors, hasLength(1)); |
| 5897 expect(secondAccessors[0].variable, same(firstAccessors[0].variable)); |
| 5898 } |
| 5899 |
| 5900 void test_empty() { |
| 5901 Source librarySource = addSource("/lib.dart", "library lib;"); |
| 5902 LibraryElement element = _buildLibrary(librarySource); |
| 5903 expect(element, isNotNull); |
| 5904 expect(element.name, "lib"); |
| 5905 expect(element.entryPoint, isNull); |
| 5906 expect(element.importedLibraries, hasLength(0)); |
| 5907 expect(element.imports, hasLength(0)); |
| 5908 expect(element.library, same(element)); |
| 5909 expect(element.prefixes, hasLength(0)); |
| 5910 expect(element.parts, hasLength(0)); |
| 5911 CompilationUnitElement unit = element.definingCompilationUnit; |
| 5912 expect(unit, isNotNull); |
| 5913 expect(unit.name, "lib.dart"); |
| 5914 expect(unit.library, element); |
| 5915 expect(unit.accessors, hasLength(0)); |
| 5916 expect(unit.functions, hasLength(0)); |
| 5917 expect(unit.functionTypeAliases, hasLength(0)); |
| 5918 expect(unit.types, hasLength(0)); |
| 5919 expect(unit.topLevelVariables, hasLength(0)); |
| 5920 } |
| 5921 |
| 5922 void test_missingLibraryDirectiveWithPart() { |
| 5923 addSource("/a.dart", "part of lib;"); |
| 5924 Source librarySource = addSource("/lib.dart", "part 'a.dart';"); |
| 5925 LibraryElement element = _buildLibrary( |
| 5926 librarySource, [ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART]); |
| 5927 expect(element, isNotNull); |
| 5928 } |
| 5929 |
| 5930 void test_missingPartOfDirective() { |
| 5931 addSource("/a.dart", "class A {}"); |
| 5932 Source librarySource = addSource( |
| 5933 "/lib.dart", |
| 5934 r''' |
| 5935 library lib; |
| 5936 |
| 5937 part 'a.dart';'''); |
| 5938 LibraryElement element = |
| 5939 _buildLibrary(librarySource, [CompileTimeErrorCode.PART_OF_NON_PART]); |
| 5940 expect(element, isNotNull); |
| 5941 } |
| 5942 |
| 5943 void test_multipleFiles() { |
| 5944 Source librarySource = addSource( |
| 5945 "/lib.dart", |
| 5946 r''' |
| 5947 library lib; |
| 5948 part 'first.dart'; |
| 5949 part 'second.dart'; |
| 5950 |
| 5951 class A {}'''); |
| 5952 addSource( |
| 5953 "/first.dart", |
| 5954 r''' |
| 5955 part of lib; |
| 5956 class B {}'''); |
| 5957 addSource( |
| 5958 "/second.dart", |
| 5959 r''' |
| 5960 part of lib; |
| 5961 class C {}'''); |
| 5962 LibraryElement element = _buildLibrary(librarySource); |
| 5963 expect(element, isNotNull); |
| 5964 List<CompilationUnitElement> sourcedUnits = element.parts; |
| 5965 expect(sourcedUnits, hasLength(2)); |
| 5966 _assertTypes(element.definingCompilationUnit, ["A"]); |
| 5967 if (sourcedUnits[0].name == "first.dart") { |
| 5968 _assertTypes(sourcedUnits[0], ["B"]); |
| 5969 _assertTypes(sourcedUnits[1], ["C"]); |
| 5970 } else { |
| 5971 _assertTypes(sourcedUnits[0], ["C"]); |
| 5972 _assertTypes(sourcedUnits[1], ["B"]); |
| 5973 } |
| 5974 } |
| 5975 |
| 5976 void test_singleFile() { |
| 5977 Source librarySource = addSource( |
| 5978 "/lib.dart", |
| 5979 r''' |
| 5980 library lib; |
| 5981 |
| 5982 class A {}'''); |
| 5983 LibraryElement element = _buildLibrary(librarySource); |
| 5984 expect(element, isNotNull); |
| 5985 _assertTypes(element.definingCompilationUnit, ["A"]); |
| 5986 } |
| 5987 |
| 5988 /** |
| 5989 * Ensure that there are elements representing all of the types in the given a
rray of type names. |
| 5990 * |
| 5991 * @param unit the compilation unit containing the types |
| 5992 * @param typeNames the names of the types that should be found |
| 5993 */ |
| 5994 void _assertTypes(CompilationUnitElement unit, List<String> typeNames) { |
| 5995 expect(unit, isNotNull); |
| 5996 List<ClassElement> types = unit.types; |
| 5997 expect(types, hasLength(typeNames.length)); |
| 5998 for (ClassElement type in types) { |
| 5999 expect(type, isNotNull); |
| 6000 String actualTypeName = type.displayName; |
| 6001 bool wasExpected = false; |
| 6002 for (String expectedTypeName in typeNames) { |
| 6003 if (expectedTypeName == actualTypeName) { |
| 6004 wasExpected = true; |
| 6005 } |
| 6006 } |
| 6007 if (!wasExpected) { |
| 6008 fail("Found unexpected type $actualTypeName"); |
| 6009 } |
| 6010 } |
| 6011 } |
| 6012 |
| 6013 /** |
| 6014 * Build the element model for the library whose defining compilation unit has
the given source. |
| 6015 * |
| 6016 * @param librarySource the source of the defining compilation unit for the li
brary |
| 6017 * @param expectedErrorCodes the errors that are expected to be found while bu
ilding the element |
| 6018 * model |
| 6019 * @return the element model that was built for the library |
| 6020 * @throws Exception if the element model could not be built |
| 6021 */ |
| 6022 LibraryElement _buildLibrary(Source librarySource, |
| 6023 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { |
| 6024 LibraryResolver resolver = new LibraryResolver(_context); |
| 6025 LibraryElementBuilder builder = new LibraryElementBuilder( |
| 6026 resolver.analysisContext, resolver.errorListener); |
| 6027 Library library = resolver.createLibrary(librarySource); |
| 6028 LibraryElement element = builder.buildLibrary(library); |
| 6029 GatheringErrorListener listener = new GatheringErrorListener(); |
| 6030 listener.addAll2(resolver.errorListener); |
| 6031 listener.assertErrorsWithCodes(expectedErrorCodes); |
| 6032 return element; |
| 6033 } |
| 6034 } |
| 6035 |
| 6036 @reflectiveTest |
| 6037 class LibraryImportScopeTest extends ResolverTestCase { |
| 6038 void test_conflictingImports() { |
| 6039 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6040 String typeNameA = "A"; |
| 6041 String typeNameB = "B"; |
| 6042 String typeNameC = "C"; |
| 6043 ClassElement typeA = ElementFactory.classElement2(typeNameA); |
| 6044 ClassElement typeB1 = ElementFactory.classElement2(typeNameB); |
| 6045 ClassElement typeB2 = ElementFactory.classElement2(typeNameB); |
| 6046 ClassElement typeC = ElementFactory.classElement2(typeNameC); |
| 6047 LibraryElement importedLibrary1 = createTestLibrary(context, "imported1"); |
| 6048 (importedLibrary1.definingCompilationUnit as CompilationUnitElementImpl) |
| 6049 .types = <ClassElement>[typeA, typeB1]; |
| 6050 ImportElementImpl import1 = |
| 6051 ElementFactory.importFor(importedLibrary1, null); |
| 6052 LibraryElement importedLibrary2 = createTestLibrary(context, "imported2"); |
| 6053 (importedLibrary2.definingCompilationUnit as CompilationUnitElementImpl) |
| 6054 .types = <ClassElement>[typeB2, typeC]; |
| 6055 ImportElementImpl import2 = |
| 6056 ElementFactory.importFor(importedLibrary2, null); |
| 6057 LibraryElementImpl importingLibrary = |
| 6058 createTestLibrary(context, "importing"); |
| 6059 importingLibrary.imports = <ImportElement>[import1, import2]; |
| 6060 { |
| 6061 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6062 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6063 expect(scope.lookup(AstFactory.identifier3(typeNameA), importingLibrary), |
| 6064 typeA); |
| 6065 errorListener.assertNoErrors(); |
| 6066 expect(scope.lookup(AstFactory.identifier3(typeNameC), importingLibrary), |
| 6067 typeC); |
| 6068 errorListener.assertNoErrors(); |
| 6069 Element element = |
| 6070 scope.lookup(AstFactory.identifier3(typeNameB), importingLibrary); |
| 6071 errorListener.assertErrorsWithCodes([StaticWarningCode.AMBIGUOUS_IMPORT]); |
| 6072 EngineTestCase.assertInstanceOf((obj) => obj is MultiplyDefinedElement, |
| 6073 MultiplyDefinedElement, element); |
| 6074 List<Element> conflictingElements = |
| 6075 (element as MultiplyDefinedElement).conflictingElements; |
| 6076 expect(conflictingElements, hasLength(2)); |
| 6077 if (identical(conflictingElements[0], typeB1)) { |
| 6078 expect(conflictingElements[1], same(typeB2)); |
| 6079 } else if (identical(conflictingElements[0], typeB2)) { |
| 6080 expect(conflictingElements[1], same(typeB1)); |
| 6081 } else { |
| 6082 expect(conflictingElements[0], same(typeB1)); |
| 6083 } |
| 6084 } |
| 6085 { |
| 6086 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6087 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6088 Identifier identifier = AstFactory.identifier3(typeNameB); |
| 6089 AstFactory.methodDeclaration(null, AstFactory.typeName3(identifier), null, |
| 6090 null, AstFactory.identifier3("foo"), null); |
| 6091 Element element = scope.lookup(identifier, importingLibrary); |
| 6092 errorListener.assertErrorsWithCodes([StaticWarningCode.AMBIGUOUS_IMPORT]); |
| 6093 EngineTestCase.assertInstanceOf((obj) => obj is MultiplyDefinedElement, |
| 6094 MultiplyDefinedElement, element); |
| 6095 } |
| 6096 } |
| 6097 |
| 6098 void test_creation_empty() { |
| 6099 LibraryElement definingLibrary = createDefaultTestLibrary(); |
| 6100 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6101 new LibraryImportScope(definingLibrary, errorListener); |
| 6102 } |
| 6103 |
| 6104 void test_creation_nonEmpty() { |
| 6105 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6106 String importedTypeName = "A"; |
| 6107 ClassElement importedType = |
| 6108 new ClassElementImpl.forNode(AstFactory.identifier3(importedTypeName)); |
| 6109 LibraryElement importedLibrary = createTestLibrary(context, "imported"); |
| 6110 (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6111 .types = <ClassElement>[importedType]; |
| 6112 LibraryElementImpl definingLibrary = |
| 6113 createTestLibrary(context, "importing"); |
| 6114 ImportElementImpl importElement = new ImportElementImpl(0); |
| 6115 importElement.importedLibrary = importedLibrary; |
| 6116 definingLibrary.imports = <ImportElement>[importElement]; |
| 6117 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6118 Scope scope = new LibraryImportScope(definingLibrary, errorListener); |
| 6119 expect( |
| 6120 scope.lookup(AstFactory.identifier3(importedTypeName), definingLibrary), |
| 6121 importedType); |
| 6122 } |
| 6123 |
| 6124 void test_getErrorListener() { |
| 6125 LibraryElement definingLibrary = createDefaultTestLibrary(); |
| 6126 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6127 LibraryImportScope scope = |
| 6128 new LibraryImportScope(definingLibrary, errorListener); |
| 6129 expect(scope.errorListener, errorListener); |
| 6130 } |
| 6131 |
| 6132 void test_nonConflictingImports_fromSdk() { |
| 6133 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6134 String typeName = "List"; |
| 6135 ClassElement type = ElementFactory.classElement2(typeName); |
| 6136 LibraryElement importedLibrary = createTestLibrary(context, "lib"); |
| 6137 (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6138 .types = <ClassElement>[type]; |
| 6139 ImportElementImpl importCore = ElementFactory.importFor( |
| 6140 context.getLibraryElement(context.sourceFactory.forUri("dart:core")), |
| 6141 null); |
| 6142 ImportElementImpl importLib = |
| 6143 ElementFactory.importFor(importedLibrary, null); |
| 6144 LibraryElementImpl importingLibrary = |
| 6145 createTestLibrary(context, "importing"); |
| 6146 importingLibrary.imports = <ImportElement>[importCore, importLib]; |
| 6147 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6148 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6149 expect( |
| 6150 scope.lookup(AstFactory.identifier3(typeName), importingLibrary), type); |
| 6151 errorListener |
| 6152 .assertErrorsWithCodes([StaticWarningCode.CONFLICTING_DART_IMPORT]); |
| 6153 } |
| 6154 |
| 6155 void test_nonConflictingImports_sameElement() { |
| 6156 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6157 String typeNameA = "A"; |
| 6158 String typeNameB = "B"; |
| 6159 ClassElement typeA = ElementFactory.classElement2(typeNameA); |
| 6160 ClassElement typeB = ElementFactory.classElement2(typeNameB); |
| 6161 LibraryElement importedLibrary = createTestLibrary(context, "imported"); |
| 6162 (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6163 .types = <ClassElement>[typeA, typeB]; |
| 6164 ImportElementImpl import1 = ElementFactory.importFor(importedLibrary, null); |
| 6165 ImportElementImpl import2 = ElementFactory.importFor(importedLibrary, null); |
| 6166 LibraryElementImpl importingLibrary = |
| 6167 createTestLibrary(context, "importing"); |
| 6168 importingLibrary.imports = <ImportElement>[import1, import2]; |
| 6169 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6170 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6171 expect(scope.lookup(AstFactory.identifier3(typeNameA), importingLibrary), |
| 6172 typeA); |
| 6173 errorListener.assertNoErrors(); |
| 6174 expect(scope.lookup(AstFactory.identifier3(typeNameB), importingLibrary), |
| 6175 typeB); |
| 6176 errorListener.assertNoErrors(); |
| 6177 } |
| 6178 |
| 6179 void test_prefixedAndNonPrefixed() { |
| 6180 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6181 String typeName = "C"; |
| 6182 String prefixName = "p"; |
| 6183 ClassElement prefixedType = ElementFactory.classElement2(typeName); |
| 6184 ClassElement nonPrefixedType = ElementFactory.classElement2(typeName); |
| 6185 LibraryElement prefixedLibrary = |
| 6186 createTestLibrary(context, "import.prefixed"); |
| 6187 (prefixedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6188 .types = <ClassElement>[prefixedType]; |
| 6189 ImportElementImpl prefixedImport = ElementFactory.importFor( |
| 6190 prefixedLibrary, ElementFactory.prefix(prefixName)); |
| 6191 LibraryElement nonPrefixedLibrary = |
| 6192 createTestLibrary(context, "import.nonPrefixed"); |
| 6193 (nonPrefixedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6194 .types = <ClassElement>[nonPrefixedType]; |
| 6195 ImportElementImpl nonPrefixedImport = |
| 6196 ElementFactory.importFor(nonPrefixedLibrary, null); |
| 6197 LibraryElementImpl importingLibrary = |
| 6198 createTestLibrary(context, "importing"); |
| 6199 importingLibrary.imports = <ImportElement>[ |
| 6200 prefixedImport, |
| 6201 nonPrefixedImport |
| 6202 ]; |
| 6203 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6204 Scope scope = new LibraryImportScope(importingLibrary, errorListener); |
| 6205 Element prefixedElement = scope.lookup( |
| 6206 AstFactory.identifier5(prefixName, typeName), importingLibrary); |
| 6207 errorListener.assertNoErrors(); |
| 6208 expect(prefixedElement, same(prefixedType)); |
| 6209 Element nonPrefixedElement = |
| 6210 scope.lookup(AstFactory.identifier3(typeName), importingLibrary); |
| 6211 errorListener.assertNoErrors(); |
| 6212 expect(nonPrefixedElement, same(nonPrefixedType)); |
| 6213 } |
| 6214 } |
| 6215 |
| 6216 @reflectiveTest |
| 6217 class LibraryResolver2Test extends ResolverTestCase { |
| 6218 LibraryResolver2 _resolver; |
| 6219 |
| 6220 Source _coreLibrarySource; |
| 6221 |
| 6222 Source _asyncLibrarySource; |
| 6223 |
| 6224 @override |
| 6225 void setUp() { |
| 6226 super.setUp(); |
| 6227 _resolver = new LibraryResolver2(analysisContext2); |
| 6228 _coreLibrarySource = |
| 6229 analysisContext2.sourceFactory.forUri(DartSdk.DART_CORE); |
| 6230 _asyncLibrarySource = |
| 6231 analysisContext2.sourceFactory.forUri(DartSdk.DART_ASYNC); |
| 6232 } |
| 6233 |
| 6234 void test_imports_relative() { |
| 6235 Source sourceA = addSource(r''' |
| 6236 library libA; |
| 6237 import 'libB.dart'; |
| 6238 class A {}'''); |
| 6239 Source sourceB = addNamedSource( |
| 6240 "/libB.dart", |
| 6241 r''' |
| 6242 library libB; |
| 6243 import 'test.dart |
| 6244 class B {}'''); |
| 6245 List<ResolvableLibrary> cycle = new List<ResolvableLibrary>(); |
| 6246 ResolvableLibrary coreLib = _createResolvableLibrary(_coreLibrarySource); |
| 6247 coreLib.libraryElement = analysisContext2 |
| 6248 .computeLibraryElement(_coreLibrarySource) as LibraryElementImpl; |
| 6249 ResolvableLibrary asyncLib = _createResolvableLibrary(_asyncLibrarySource); |
| 6250 asyncLib.libraryElement = analysisContext2 |
| 6251 .computeLibraryElement(_asyncLibrarySource) as LibraryElementImpl; |
| 6252 ResolvableLibrary libA = _createResolvableLibrary(sourceA); |
| 6253 ResolvableLibrary libB = _createResolvableLibrary(sourceB); |
| 6254 libA.importedLibraries = <ResolvableLibrary>[coreLib, asyncLib, libB]; |
| 6255 libB.importedLibraries = <ResolvableLibrary>[coreLib, asyncLib, libA]; |
| 6256 cycle.add(libA); |
| 6257 cycle.add(libB); |
| 6258 LibraryElement library = _resolver.resolveLibrary(sourceA, cycle); |
| 6259 List<LibraryElement> importedLibraries = library.importedLibraries; |
| 6260 assertNamedElements(importedLibraries, ["dart.core", "libB"]); |
| 6261 } |
| 6262 |
| 6263 ResolvableLibrary _createResolvableLibrary(Source source) { |
| 6264 CompilationUnit unit = analysisContext2.parseCompilationUnit(source); |
| 6265 ResolvableLibrary resolvableLibrary = new ResolvableLibrary(source); |
| 6266 resolvableLibrary.resolvableCompilationUnits = <ResolvableCompilationUnit>[ |
| 6267 new ResolvableCompilationUnit(source, unit) |
| 6268 ]; |
| 6269 return resolvableLibrary; |
| 6270 } |
| 6271 } |
| 6272 |
| 6273 @reflectiveTest |
| 6274 class LibraryResolverTest extends ResolverTestCase { |
| 6275 LibraryResolver _resolver; |
| 6276 |
| 6277 @override |
| 6278 void setUp() { |
| 6279 super.setUp(); |
| 6280 _resolver = new LibraryResolver(analysisContext2); |
| 6281 } |
| 6282 |
| 6283 void test_imports_dart_html() { |
| 6284 Source source = addSource(r''' |
| 6285 library libA; |
| 6286 import 'dart:html'; |
| 6287 class A {}'''); |
| 6288 LibraryElement library = _resolver.resolveLibrary(source, true); |
| 6289 List<LibraryElement> importedLibraries = library.importedLibraries; |
| 6290 assertNamedElements(importedLibraries, ["dart.core", "dart.dom.html"]); |
| 6291 } |
| 6292 |
| 6293 void test_imports_none() { |
| 6294 Source source = addSource(r''' |
| 6295 library libA; |
| 6296 class A {}'''); |
| 6297 LibraryElement library = _resolver.resolveLibrary(source, true); |
| 6298 List<LibraryElement> importedLibraries = library.importedLibraries; |
| 6299 assertNamedElements(importedLibraries, ["dart.core"]); |
| 6300 } |
| 6301 |
| 6302 void test_imports_relative() { |
| 6303 addNamedSource("/libB.dart", "library libB;"); |
| 6304 Source source = addSource(r''' |
| 6305 library libA; |
| 6306 import 'libB.dart'; |
| 6307 class A {}'''); |
| 6308 LibraryElement library = _resolver.resolveLibrary(source, true); |
| 6309 List<LibraryElement> importedLibraries = library.importedLibraries; |
| 6310 assertNamedElements(importedLibraries, ["dart.core", "libB"]); |
| 6311 } |
| 6312 } |
| 6313 |
| 6314 @reflectiveTest |
| 6315 class LibraryScopeTest extends ResolverTestCase { |
| 6316 void test_creation_empty() { |
| 6317 LibraryElement definingLibrary = createDefaultTestLibrary(); |
| 6318 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6319 new LibraryScope(definingLibrary, errorListener); |
| 6320 } |
| 6321 |
| 6322 void test_creation_nonEmpty() { |
| 6323 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 6324 String importedTypeName = "A"; |
| 6325 ClassElement importedType = |
| 6326 new ClassElementImpl.forNode(AstFactory.identifier3(importedTypeName)); |
| 6327 LibraryElement importedLibrary = createTestLibrary(context, "imported"); |
| 6328 (importedLibrary.definingCompilationUnit as CompilationUnitElementImpl) |
| 6329 .types = <ClassElement>[importedType]; |
| 6330 LibraryElementImpl definingLibrary = |
| 6331 createTestLibrary(context, "importing"); |
| 6332 ImportElementImpl importElement = new ImportElementImpl(0); |
| 6333 importElement.importedLibrary = importedLibrary; |
| 6334 definingLibrary.imports = <ImportElement>[importElement]; |
| 6335 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6336 Scope scope = new LibraryScope(definingLibrary, errorListener); |
| 6337 expect( |
| 6338 scope.lookup(AstFactory.identifier3(importedTypeName), definingLibrary), |
| 6339 importedType); |
| 6340 } |
| 6341 |
| 6342 void test_getErrorListener() { |
| 6343 LibraryElement definingLibrary = createDefaultTestLibrary(); |
| 6344 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 6345 LibraryScope scope = new LibraryScope(definingLibrary, errorListener); |
| 6346 expect(scope.errorListener, errorListener); |
| 6347 } |
| 6348 } |
| 6349 |
| 6350 @reflectiveTest |
| 6351 class LibraryTest extends EngineTestCase { |
| 6352 /** |
| 6353 * The error listener to which all errors will be reported. |
| 6354 */ |
| 6355 GatheringErrorListener _errorListener; |
| 6356 |
| 6357 /** |
| 6358 * The analysis context to pass in to all libraries created by the tests. |
| 6359 */ |
| 6360 InternalAnalysisContext _analysisContext; |
| 6361 |
| 6362 /** |
| 6363 * The library used by the tests. |
| 6364 */ |
| 6365 Library _library; |
| 6366 |
| 6367 @override |
| 6368 void setUp() { |
| 6369 _analysisContext = AnalysisContextFactory.contextWithCore(); |
| 6370 _errorListener = new GatheringErrorListener(); |
| 6371 _library = _createLibrary("/lib.dart"); |
| 6372 } |
| 6373 |
| 6374 @override |
| 6375 void tearDown() { |
| 6376 _errorListener = null; |
| 6377 _analysisContext = null; |
| 6378 _library = null; |
| 6379 super.tearDown(); |
| 6380 } |
| 6381 |
| 6382 void test_getExplicitlyImportsCore() { |
| 6383 expect(_library.explicitlyImportsCore, isFalse); |
| 6384 _errorListener.assertNoErrors(); |
| 6385 } |
| 6386 |
| 6387 void test_getExports() { |
| 6388 expect(_library.exports, hasLength(0)); |
| 6389 _errorListener.assertNoErrors(); |
| 6390 } |
| 6391 |
| 6392 void test_getImports() { |
| 6393 expect(_library.imports, hasLength(0)); |
| 6394 _errorListener.assertNoErrors(); |
| 6395 } |
| 6396 |
| 6397 void test_getImportsAndExports() { |
| 6398 _library.importedLibraries = <Library>[_createLibrary("/imported.dart")]; |
| 6399 _library.exportedLibraries = <Library>[_createLibrary("/exported.dart")]; |
| 6400 expect(_library.importsAndExports, hasLength(2)); |
| 6401 _errorListener.assertNoErrors(); |
| 6402 } |
| 6403 |
| 6404 void test_getLibraryScope() { |
| 6405 LibraryElementImpl element = new LibraryElementImpl.forNode( |
| 6406 _analysisContext, AstFactory.libraryIdentifier2(["lib"])); |
| 6407 element.definingCompilationUnit = |
| 6408 new CompilationUnitElementImpl("lib.dart"); |
| 6409 _library.libraryElement = element; |
| 6410 expect(_library.libraryScope, isNotNull); |
| 6411 _errorListener.assertNoErrors(); |
| 6412 } |
| 6413 |
| 6414 void test_getLibrarySource() { |
| 6415 expect(_library.librarySource, isNotNull); |
| 6416 } |
| 6417 |
| 6418 void test_setExplicitlyImportsCore() { |
| 6419 _library.explicitlyImportsCore = true; |
| 6420 expect(_library.explicitlyImportsCore, isTrue); |
| 6421 _errorListener.assertNoErrors(); |
| 6422 } |
| 6423 |
| 6424 void test_setExportedLibraries() { |
| 6425 Library exportLibrary = _createLibrary("/exported.dart"); |
| 6426 _library.exportedLibraries = <Library>[exportLibrary]; |
| 6427 List<Library> exports = _library.exports; |
| 6428 expect(exports, hasLength(1)); |
| 6429 expect(exports[0], same(exportLibrary)); |
| 6430 _errorListener.assertNoErrors(); |
| 6431 } |
| 6432 |
| 6433 void test_setImportedLibraries() { |
| 6434 Library importLibrary = _createLibrary("/imported.dart"); |
| 6435 _library.importedLibraries = <Library>[importLibrary]; |
| 6436 List<Library> imports = _library.imports; |
| 6437 expect(imports, hasLength(1)); |
| 6438 expect(imports[0], same(importLibrary)); |
| 6439 _errorListener.assertNoErrors(); |
| 6440 } |
| 6441 |
| 6442 void test_setLibraryElement() { |
| 6443 LibraryElementImpl element = new LibraryElementImpl.forNode( |
| 6444 _analysisContext, AstFactory.libraryIdentifier2(["lib"])); |
| 6445 _library.libraryElement = element; |
| 6446 expect(_library.libraryElement, same(element)); |
| 6447 } |
| 6448 |
| 6449 Library _createLibrary(String definingCompilationUnitPath) => new Library( |
| 6450 _analysisContext, |
| 6451 _errorListener, |
| 6452 new FileBasedSource( |
| 6453 FileUtilities2.createFile(definingCompilationUnitPath))); |
| 6454 } |
| 6455 |
| 6456 @reflectiveTest |
| 6457 class MemberMapTest { |
| 6458 /** |
| 6459 * The null type. |
| 6460 */ |
| 6461 InterfaceType _nullType; |
| 6462 |
| 6463 void setUp() { |
| 6464 _nullType = new TestTypeProvider().nullType; |
| 6465 } |
| 6466 |
| 6467 void test_MemberMap_copyConstructor() { |
| 6468 MethodElement m1 = ElementFactory.methodElement("m1", _nullType); |
| 6469 MethodElement m2 = ElementFactory.methodElement("m2", _nullType); |
| 6470 MethodElement m3 = ElementFactory.methodElement("m3", _nullType); |
| 6471 MemberMap map = new MemberMap(); |
| 6472 map.put(m1.name, m1); |
| 6473 map.put(m2.name, m2); |
| 6474 map.put(m3.name, m3); |
| 6475 MemberMap copy = new MemberMap.from(map); |
| 6476 expect(copy.size, map.size); |
| 6477 expect(copy.get(m1.name), m1); |
| 6478 expect(copy.get(m2.name), m2); |
| 6479 expect(copy.get(m3.name), m3); |
| 6480 } |
| 6481 |
| 6482 void test_MemberMap_override() { |
| 6483 MethodElement m1 = ElementFactory.methodElement("m", _nullType); |
| 6484 MethodElement m2 = ElementFactory.methodElement("m", _nullType); |
| 6485 MemberMap map = new MemberMap(); |
| 6486 map.put(m1.name, m1); |
| 6487 map.put(m2.name, m2); |
| 6488 expect(map.size, 1); |
| 6489 expect(map.get("m"), m2); |
| 6490 } |
| 6491 |
| 6492 void test_MemberMap_put() { |
| 6493 MethodElement m1 = ElementFactory.methodElement("m1", _nullType); |
| 6494 MemberMap map = new MemberMap(); |
| 6495 expect(map.size, 0); |
| 6496 map.put(m1.name, m1); |
| 6497 expect(map.size, 1); |
| 6498 expect(map.get("m1"), m1); |
| 6499 } |
| 6500 } |
| 6501 |
| 6502 /** |
| 6503 * An analysis context that has a fake SDK that is much smaller and faster for |
| 6504 * testing purposes. |
| 6505 */ |
| 6506 class NewAnalysisContextForTests extends newContext.AnalysisContextImpl { |
| 6507 @override |
| 6508 void set analysisOptions(AnalysisOptions options) { |
| 6509 AnalysisOptions currentOptions = analysisOptions; |
| 6510 bool needsRecompute = currentOptions.analyzeFunctionBodiesPredicate != |
| 6511 options.analyzeFunctionBodiesPredicate || |
| 6512 currentOptions.generateImplicitErrors != |
| 6513 options.generateImplicitErrors || |
| 6514 currentOptions.generateSdkErrors != options.generateSdkErrors || |
| 6515 currentOptions.dart2jsHint != options.dart2jsHint || |
| 6516 (currentOptions.hint && !options.hint) || |
| 6517 currentOptions.preserveComments != options.preserveComments || |
| 6518 currentOptions.enableStrictCallChecks != options.enableStrictCallChecks; |
| 6519 if (needsRecompute) { |
| 6520 fail( |
| 6521 "Cannot set options that cause the sources to be reanalyzed in a test
context"); |
| 6522 } |
| 6523 super.analysisOptions = options; |
| 6524 } |
| 6525 |
| 6526 @override |
| 6527 bool exists(Source source) => |
| 6528 super.exists(source) || sourceFactory.dartSdk.context.exists(source); |
| 6529 |
| 6530 @override |
| 6531 TimestampedData<String> getContents(Source source) { |
| 6532 if (source.isInSystemLibrary) { |
| 6533 return sourceFactory.dartSdk.context.getContents(source); |
| 6534 } |
| 6535 return super.getContents(source); |
| 6536 } |
| 6537 |
| 6538 @override |
| 6539 int getModificationStamp(Source source) { |
| 6540 if (source.isInSystemLibrary) { |
| 6541 return sourceFactory.dartSdk.context.getModificationStamp(source); |
| 6542 } |
| 6543 return super.getModificationStamp(source); |
| 6544 } |
| 6545 |
| 6546 /** |
| 6547 * Set the analysis options, even if they would force re-analysis. This method
should only be |
| 6548 * invoked before the fake SDK is initialized. |
| 6549 * |
| 6550 * @param options the analysis options to be set |
| 6551 */ |
| 6552 void _internalSetAnalysisOptions(AnalysisOptions options) { |
| 6553 super.analysisOptions = options; |
| 6554 } |
| 6555 } |
| 6556 |
| 6557 @reflectiveTest |
| 6558 class NonHintCodeTest extends ResolverTestCase { |
| 6559 void test_deadCode_deadBlock_conditionalElse_debugConst() { |
| 6560 Source source = addSource(r''' |
| 6561 const bool DEBUG = true; |
| 6562 f() { |
| 6563 DEBUG ? 1 : 2; |
| 6564 }'''); |
| 6565 computeLibrarySourceErrors(source); |
| 6566 assertNoErrors(source); |
| 6567 verify([source]); |
| 6568 } |
| 6569 |
| 6570 void test_deadCode_deadBlock_conditionalIf_debugConst() { |
| 6571 Source source = addSource(r''' |
| 6572 const bool DEBUG = false; |
| 6573 f() { |
| 6574 DEBUG ? 1 : 2; |
| 6575 }'''); |
| 6576 computeLibrarySourceErrors(source); |
| 6577 assertNoErrors(source); |
| 6578 verify([source]); |
| 6579 } |
| 6580 |
| 6581 void test_deadCode_deadBlock_else() { |
| 6582 Source source = addSource(r''' |
| 6583 const bool DEBUG = true; |
| 6584 f() { |
| 6585 if(DEBUG) {} else {} |
| 6586 }'''); |
| 6587 computeLibrarySourceErrors(source); |
| 6588 assertNoErrors(source); |
| 6589 verify([source]); |
| 6590 } |
| 6591 |
| 6592 void test_deadCode_deadBlock_if_debugConst_prefixedIdentifier() { |
| 6593 Source source = addSource(r''' |
| 6594 class A { |
| 6595 static const bool DEBUG = false; |
| 6596 } |
| 6597 f() { |
| 6598 if(A.DEBUG) {} |
| 6599 }'''); |
| 6600 computeLibrarySourceErrors(source); |
| 6601 assertNoErrors(source); |
| 6602 verify([source]); |
| 6603 } |
| 6604 |
| 6605 void test_deadCode_deadBlock_if_debugConst_prefixedIdentifier2() { |
| 6606 Source source = addSource(r''' |
| 6607 library L; |
| 6608 import 'lib2.dart'; |
| 6609 f() { |
| 6610 if(A.DEBUG) {} |
| 6611 }'''); |
| 6612 addNamedSource( |
| 6613 "/lib2.dart", |
| 6614 r''' |
| 6615 library lib2; |
| 6616 class A { |
| 6617 static const bool DEBUG = false; |
| 6618 }'''); |
| 6619 computeLibrarySourceErrors(source); |
| 6620 assertNoErrors(source); |
| 6621 verify([source]); |
| 6622 } |
| 6623 |
| 6624 void test_deadCode_deadBlock_if_debugConst_propertyAccessor() { |
| 6625 Source source = addSource(r''' |
| 6626 library L; |
| 6627 import 'lib2.dart' as LIB; |
| 6628 f() { |
| 6629 if(LIB.A.DEBUG) {} |
| 6630 }'''); |
| 6631 addNamedSource( |
| 6632 "/lib2.dart", |
| 6633 r''' |
| 6634 library lib2; |
| 6635 class A { |
| 6636 static const bool DEBUG = false; |
| 6637 }'''); |
| 6638 computeLibrarySourceErrors(source); |
| 6639 assertNoErrors(source); |
| 6640 verify([source]); |
| 6641 } |
| 6642 |
| 6643 void test_deadCode_deadBlock_if_debugConst_simpleIdentifier() { |
| 6644 Source source = addSource(r''' |
| 6645 const bool DEBUG = false; |
| 6646 f() { |
| 6647 if(DEBUG) {} |
| 6648 }'''); |
| 6649 computeLibrarySourceErrors(source); |
| 6650 assertNoErrors(source); |
| 6651 verify([source]); |
| 6652 } |
| 6653 |
| 6654 void test_deadCode_deadBlock_while_debugConst() { |
| 6655 Source source = addSource(r''' |
| 6656 const bool DEBUG = false; |
| 6657 f() { |
| 6658 while(DEBUG) {} |
| 6659 }'''); |
| 6660 computeLibrarySourceErrors(source); |
| 6661 assertNoErrors(source); |
| 6662 verify([source]); |
| 6663 } |
| 6664 |
| 6665 void test_deadCode_deadCatch_onCatchSubtype() { |
| 6666 Source source = addSource(r''' |
| 6667 class A {} |
| 6668 class B extends A {} |
| 6669 f() { |
| 6670 try {} on B catch (e) {} on A catch (e) {} catch (e) {} |
| 6671 }'''); |
| 6672 computeLibrarySourceErrors(source); |
| 6673 assertNoErrors(source); |
| 6674 verify([source]); |
| 6675 } |
| 6676 |
| 6677 void test_deadCode_deadOperandLHS_and_debugConst() { |
| 6678 Source source = addSource(r''' |
| 6679 const bool DEBUG = false; |
| 6680 f() { |
| 6681 bool b = DEBUG && false; |
| 6682 }'''); |
| 6683 computeLibrarySourceErrors(source); |
| 6684 assertNoErrors(source); |
| 6685 verify([source]); |
| 6686 } |
| 6687 |
| 6688 void test_deadCode_deadOperandLHS_or_debugConst() { |
| 6689 Source source = addSource(r''' |
| 6690 const bool DEBUG = true; |
| 6691 f() { |
| 6692 bool b = DEBUG || true; |
| 6693 }'''); |
| 6694 computeLibrarySourceErrors(source); |
| 6695 assertNoErrors(source); |
| 6696 verify([source]); |
| 6697 } |
| 6698 |
| 6699 void test_divisionOptimization() { |
| 6700 Source source = addSource(r''' |
| 6701 f(int x, int y) { |
| 6702 var v = x / y.toInt(); |
| 6703 }'''); |
| 6704 computeLibrarySourceErrors(source); |
| 6705 assertNoErrors(source); |
| 6706 verify([source]); |
| 6707 } |
| 6708 |
| 6709 void test_divisionOptimization_supressIfDivisionNotDefinedInCore() { |
| 6710 Source source = addSource(r''' |
| 6711 f(x, y) { |
| 6712 var v = (x / y).toInt(); |
| 6713 }'''); |
| 6714 computeLibrarySourceErrors(source); |
| 6715 assertNoErrors(source); |
| 6716 verify([source]); |
| 6717 } |
| 6718 |
| 6719 void test_divisionOptimization_supressIfDivisionOverridden() { |
| 6720 Source source = addSource(r''' |
| 6721 class A { |
| 6722 num operator /(x) { return x; } |
| 6723 } |
| 6724 f(A x, A y) { |
| 6725 var v = (x / y).toInt(); |
| 6726 }'''); |
| 6727 computeLibrarySourceErrors(source); |
| 6728 assertNoErrors(source); |
| 6729 verify([source]); |
| 6730 } |
| 6731 |
| 6732 void test_duplicateImport_as() { |
| 6733 Source source = addSource(r''' |
| 6734 library L; |
| 6735 import 'lib1.dart'; |
| 6736 import 'lib1.dart' as one; |
| 6737 A a; |
| 6738 one.A a2;'''); |
| 6739 addNamedSource( |
| 6740 "/lib1.dart", |
| 6741 r''' |
| 6742 library lib1; |
| 6743 class A {}'''); |
| 6744 computeLibrarySourceErrors(source); |
| 6745 assertNoErrors(source); |
| 6746 verify([source]); |
| 6747 } |
| 6748 |
| 6749 void test_duplicateImport_hide() { |
| 6750 Source source = addSource(r''' |
| 6751 library L; |
| 6752 import 'lib1.dart'; |
| 6753 import 'lib1.dart' hide A; |
| 6754 A a; |
| 6755 B b;'''); |
| 6756 addNamedSource( |
| 6757 "/lib1.dart", |
| 6758 r''' |
| 6759 library lib1; |
| 6760 class A {} |
| 6761 class B {}'''); |
| 6762 computeLibrarySourceErrors(source); |
| 6763 assertNoErrors(source); |
| 6764 verify([source]); |
| 6765 } |
| 6766 |
| 6767 void test_duplicateImport_show() { |
| 6768 Source source = addSource(r''' |
| 6769 library L; |
| 6770 import 'lib1.dart'; |
| 6771 import 'lib1.dart' show A; |
| 6772 A a; |
| 6773 B b;'''); |
| 6774 addNamedSource( |
| 6775 "/lib1.dart", |
| 6776 r''' |
| 6777 library lib1; |
| 6778 class A {} |
| 6779 class B {}'''); |
| 6780 computeLibrarySourceErrors(source); |
| 6781 assertNoErrors(source); |
| 6782 verify([source]); |
| 6783 } |
| 6784 |
| 6785 void test_importDeferredLibraryWithLoadFunction() { |
| 6786 resolveWithErrors(<String>[ |
| 6787 r''' |
| 6788 library lib1; |
| 6789 f() {}''', |
| 6790 r''' |
| 6791 library root; |
| 6792 import 'lib1.dart' deferred as lib1; |
| 6793 main() { lib1.f(); }''' |
| 6794 ], ErrorCode.EMPTY_LIST); |
| 6795 } |
| 6796 |
| 6797 void test_issue20904BuggyTypePromotionAtIfJoin_1() { |
| 6798 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 6799 Source source = addSource(r''' |
| 6800 f(var message, var dynamic_) { |
| 6801 if (message is Function) { |
| 6802 message = dynamic_; |
| 6803 } |
| 6804 int s = message; |
| 6805 }'''); |
| 6806 computeLibrarySourceErrors(source); |
| 6807 assertNoErrors(source); |
| 6808 verify([source]); |
| 6809 } |
| 6810 |
| 6811 void test_issue20904BuggyTypePromotionAtIfJoin_3() { |
| 6812 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 6813 Source source = addSource(r''' |
| 6814 f(var message) { |
| 6815 var dynamic_; |
| 6816 if (message is Function) { |
| 6817 message = dynamic_; |
| 6818 } else { |
| 6819 return; |
| 6820 } |
| 6821 int s = message; |
| 6822 }'''); |
| 6823 computeLibrarySourceErrors(source); |
| 6824 assertNoErrors(source); |
| 6825 verify([source]); |
| 6826 } |
| 6827 |
| 6828 void test_issue20904BuggyTypePromotionAtIfJoin_4() { |
| 6829 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 6830 Source source = addSource(r''' |
| 6831 f(var message) { |
| 6832 if (message is Function) { |
| 6833 message = ''; |
| 6834 } else { |
| 6835 return; |
| 6836 } |
| 6837 String s = message; |
| 6838 }'''); |
| 6839 computeLibrarySourceErrors(source); |
| 6840 assertNoErrors(source); |
| 6841 verify([source]); |
| 6842 } |
| 6843 |
| 6844 void test_missingReturn_emptyFunctionBody() { |
| 6845 Source source = addSource(r''' |
| 6846 abstract class A { |
| 6847 int m(); |
| 6848 }'''); |
| 6849 computeLibrarySourceErrors(source); |
| 6850 assertNoErrors(source); |
| 6851 verify([source]); |
| 6852 } |
| 6853 |
| 6854 void test_missingReturn_expressionFunctionBody() { |
| 6855 Source source = addSource("int f() => 0;"); |
| 6856 computeLibrarySourceErrors(source); |
| 6857 assertNoErrors(source); |
| 6858 verify([source]); |
| 6859 } |
| 6860 |
| 6861 void test_missingReturn_noReturnType() { |
| 6862 Source source = addSource("f() {}"); |
| 6863 computeLibrarySourceErrors(source); |
| 6864 assertNoErrors(source); |
| 6865 verify([source]); |
| 6866 } |
| 6867 |
| 6868 void test_missingReturn_voidReturnType() { |
| 6869 Source source = addSource("void f() {}"); |
| 6870 computeLibrarySourceErrors(source); |
| 6871 assertNoErrors(source); |
| 6872 verify([source]); |
| 6873 } |
| 6874 |
| 6875 void test_overrideEqualsButNotHashCode() { |
| 6876 Source source = addSource(r''' |
| 6877 class A { |
| 6878 bool operator ==(x) { return x; } |
| 6879 get hashCode => 0; |
| 6880 }'''); |
| 6881 computeLibrarySourceErrors(source); |
| 6882 assertNoErrors(source); |
| 6883 verify([source]); |
| 6884 } |
| 6885 |
| 6886 void test_overrideOnNonOverridingGetter_inInterface() { |
| 6887 Source source = addSource(r''' |
| 6888 library dart.core; |
| 6889 const override = null; |
| 6890 class A { |
| 6891 int get m => 0; |
| 6892 } |
| 6893 class B implements A { |
| 6894 @override |
| 6895 int get m => 1; |
| 6896 }'''); |
| 6897 computeLibrarySourceErrors(source); |
| 6898 assertNoErrors(source); |
| 6899 verify([source]); |
| 6900 } |
| 6901 |
| 6902 void test_overrideOnNonOverridingGetter_inSuperclass() { |
| 6903 Source source = addSource(r''' |
| 6904 library dart.core; |
| 6905 const override = null; |
| 6906 class A { |
| 6907 int get m => 0; |
| 6908 } |
| 6909 class B extends A { |
| 6910 @override |
| 6911 int get m => 1; |
| 6912 }'''); |
| 6913 computeLibrarySourceErrors(source); |
| 6914 assertNoErrors(source); |
| 6915 verify([source]); |
| 6916 } |
| 6917 |
| 6918 void test_overrideOnNonOverridingMethod_inInterface() { |
| 6919 Source source = addSource(r''' |
| 6920 library dart.core; |
| 6921 const override = null; |
| 6922 class A { |
| 6923 int m() => 0; |
| 6924 } |
| 6925 class B implements A { |
| 6926 @override |
| 6927 int m() => 1; |
| 6928 }'''); |
| 6929 computeLibrarySourceErrors(source); |
| 6930 assertNoErrors(source); |
| 6931 verify([source]); |
| 6932 } |
| 6933 |
| 6934 void test_overrideOnNonOverridingMethod_inSuperclass() { |
| 6935 Source source = addSource(r''' |
| 6936 library dart.core; |
| 6937 const override = null; |
| 6938 class A { |
| 6939 int m() => 0; |
| 6940 } |
| 6941 class B extends A { |
| 6942 @override |
| 6943 int m() => 1; |
| 6944 }'''); |
| 6945 computeLibrarySourceErrors(source); |
| 6946 assertNoErrors(source); |
| 6947 verify([source]); |
| 6948 } |
| 6949 |
| 6950 void test_overrideOnNonOverridingSetter_inInterface() { |
| 6951 Source source = addSource(r''' |
| 6952 library dart.core; |
| 6953 const override = null; |
| 6954 class A { |
| 6955 set m(int x) {} |
| 6956 } |
| 6957 class B implements A { |
| 6958 @override |
| 6959 set m(int x) {} |
| 6960 }'''); |
| 6961 computeLibrarySourceErrors(source); |
| 6962 assertNoErrors(source); |
| 6963 verify([source]); |
| 6964 } |
| 6965 |
| 6966 void test_overrideOnNonOverridingSetter_inSuperclass() { |
| 6967 Source source = addSource(r''' |
| 6968 library dart.core; |
| 6969 const override = null; |
| 6970 class A { |
| 6971 set m(int x) {} |
| 6972 } |
| 6973 class B extends A { |
| 6974 @override |
| 6975 set m(int x) {} |
| 6976 }'''); |
| 6977 computeLibrarySourceErrors(source); |
| 6978 assertNoErrors(source); |
| 6979 verify([source]); |
| 6980 } |
| 6981 |
| 6982 void test_propagatedFieldType() { |
| 6983 Source source = addSource(r''' |
| 6984 class A { } |
| 6985 class X<T> { |
| 6986 final x = new List<T>(); |
| 6987 } |
| 6988 class Z { |
| 6989 final X<A> y = new X<A>(); |
| 6990 foo() { |
| 6991 y.x.add(new A()); |
| 6992 } |
| 6993 }'''); |
| 6994 computeLibrarySourceErrors(source); |
| 6995 assertNoErrors(source); |
| 6996 verify([source]); |
| 6997 } |
| 6998 |
| 6999 void test_proxy_annotation_prefixed() { |
| 7000 Source source = addSource(r''' |
| 7001 library L; |
| 7002 @proxy |
| 7003 class A {} |
| 7004 f(var a) { |
| 7005 a = new A(); |
| 7006 a.m(); |
| 7007 var x = a.g; |
| 7008 a.s = 1; |
| 7009 var y = a + a; |
| 7010 a++; |
| 7011 ++a; |
| 7012 }'''); |
| 7013 computeLibrarySourceErrors(source); |
| 7014 assertNoErrors(source); |
| 7015 } |
| 7016 |
| 7017 void test_proxy_annotation_prefixed2() { |
| 7018 Source source = addSource(r''' |
| 7019 library L; |
| 7020 @proxy |
| 7021 class A {} |
| 7022 class B { |
| 7023 f(var a) { |
| 7024 a = new A(); |
| 7025 a.m(); |
| 7026 var x = a.g; |
| 7027 a.s = 1; |
| 7028 var y = a + a; |
| 7029 a++; |
| 7030 ++a; |
| 7031 } |
| 7032 }'''); |
| 7033 computeLibrarySourceErrors(source); |
| 7034 assertNoErrors(source); |
| 7035 } |
| 7036 |
| 7037 void test_proxy_annotation_prefixed3() { |
| 7038 Source source = addSource(r''' |
| 7039 library L; |
| 7040 class B { |
| 7041 f(var a) { |
| 7042 a = new A(); |
| 7043 a.m(); |
| 7044 var x = a.g; |
| 7045 a.s = 1; |
| 7046 var y = a + a; |
| 7047 a++; |
| 7048 ++a; |
| 7049 } |
| 7050 } |
| 7051 @proxy |
| 7052 class A {}'''); |
| 7053 computeLibrarySourceErrors(source); |
| 7054 assertNoErrors(source); |
| 7055 } |
| 7056 |
| 7057 void test_undefinedGetter_inSubtype() { |
| 7058 Source source = addSource(r''' |
| 7059 class A {} |
| 7060 class B extends A { |
| 7061 get b => 0; |
| 7062 } |
| 7063 f(var a) { |
| 7064 if(a is A) { |
| 7065 return a.b; |
| 7066 } |
| 7067 }'''); |
| 7068 computeLibrarySourceErrors(source); |
| 7069 assertNoErrors(source); |
| 7070 } |
| 7071 |
| 7072 void test_undefinedMethod_assignmentExpression_inSubtype() { |
| 7073 Source source = addSource(r''' |
| 7074 class A {} |
| 7075 class B extends A { |
| 7076 operator +(B b) {return new B();} |
| 7077 } |
| 7078 f(var a, var a2) { |
| 7079 a = new A(); |
| 7080 a2 = new A(); |
| 7081 a += a2; |
| 7082 }'''); |
| 7083 computeLibrarySourceErrors(source); |
| 7084 assertNoErrors(source); |
| 7085 } |
| 7086 |
| 7087 void test_undefinedMethod_dynamic() { |
| 7088 Source source = addSource(r''' |
| 7089 class D<T extends dynamic> { |
| 7090 fieldAccess(T t) => t.abc; |
| 7091 methodAccess(T t) => t.xyz(1, 2, 'three'); |
| 7092 }'''); |
| 7093 computeLibrarySourceErrors(source); |
| 7094 assertNoErrors(source); |
| 7095 } |
| 7096 |
| 7097 void test_undefinedMethod_inSubtype() { |
| 7098 Source source = addSource(r''' |
| 7099 class A {} |
| 7100 class B extends A { |
| 7101 b() {} |
| 7102 } |
| 7103 f() { |
| 7104 var a = new A(); |
| 7105 a.b(); |
| 7106 }'''); |
| 7107 computeLibrarySourceErrors(source); |
| 7108 assertNoErrors(source); |
| 7109 } |
| 7110 |
| 7111 void test_undefinedMethod_unionType_all() { |
| 7112 Source source = addSource(r''' |
| 7113 class A { |
| 7114 int m(int x) => 0; |
| 7115 } |
| 7116 class B { |
| 7117 String m() => '0'; |
| 7118 } |
| 7119 f(A a, B b) { |
| 7120 var ab; |
| 7121 if (0 < 1) { |
| 7122 ab = a; |
| 7123 } else { |
| 7124 ab = b; |
| 7125 } |
| 7126 ab.m(); |
| 7127 }'''); |
| 7128 computeLibrarySourceErrors(source); |
| 7129 assertNoErrors(source); |
| 7130 } |
| 7131 |
| 7132 void test_undefinedMethod_unionType_some() { |
| 7133 Source source = addSource(r''' |
| 7134 class A { |
| 7135 int m(int x) => 0; |
| 7136 } |
| 7137 class B {} |
| 7138 f(A a, B b) { |
| 7139 var ab; |
| 7140 if (0 < 1) { |
| 7141 ab = a; |
| 7142 } else { |
| 7143 ab = b; |
| 7144 } |
| 7145 ab.m(0); |
| 7146 }'''); |
| 7147 computeLibrarySourceErrors(source); |
| 7148 assertNoErrors(source); |
| 7149 } |
| 7150 |
| 7151 void test_undefinedOperator_binaryExpression_inSubtype() { |
| 7152 Source source = addSource(r''' |
| 7153 class A {} |
| 7154 class B extends A { |
| 7155 operator +(B b) {} |
| 7156 } |
| 7157 f(var a) { |
| 7158 if(a is A) { |
| 7159 a + 1; |
| 7160 } |
| 7161 }'''); |
| 7162 computeLibrarySourceErrors(source); |
| 7163 assertNoErrors(source); |
| 7164 } |
| 7165 |
| 7166 void test_undefinedOperator_indexBoth_inSubtype() { |
| 7167 Source source = addSource(r''' |
| 7168 class A {} |
| 7169 class B extends A { |
| 7170 operator [](int index) {} |
| 7171 } |
| 7172 f(var a) { |
| 7173 if(a is A) { |
| 7174 a[0]++; |
| 7175 } |
| 7176 }'''); |
| 7177 computeLibrarySourceErrors(source); |
| 7178 assertNoErrors(source); |
| 7179 } |
| 7180 |
| 7181 void test_undefinedOperator_indexGetter_inSubtype() { |
| 7182 Source source = addSource(r''' |
| 7183 class A {} |
| 7184 class B extends A { |
| 7185 operator [](int index) {} |
| 7186 } |
| 7187 f(var a) { |
| 7188 if(a is A) { |
| 7189 a[0]; |
| 7190 } |
| 7191 }'''); |
| 7192 computeLibrarySourceErrors(source); |
| 7193 assertNoErrors(source); |
| 7194 } |
| 7195 |
| 7196 void test_undefinedOperator_indexSetter_inSubtype() { |
| 7197 Source source = addSource(r''' |
| 7198 class A {} |
| 7199 class B extends A { |
| 7200 operator []=(i, v) {} |
| 7201 } |
| 7202 f(var a) { |
| 7203 if(a is A) { |
| 7204 a[0] = 1; |
| 7205 } |
| 7206 }'''); |
| 7207 computeLibrarySourceErrors(source); |
| 7208 assertNoErrors(source); |
| 7209 } |
| 7210 |
| 7211 void test_undefinedOperator_postfixExpression() { |
| 7212 Source source = addSource(r''' |
| 7213 class A {} |
| 7214 class B extends A { |
| 7215 operator +(B b) {return new B();} |
| 7216 } |
| 7217 f(var a) { |
| 7218 if(a is A) { |
| 7219 a++; |
| 7220 } |
| 7221 }'''); |
| 7222 computeLibrarySourceErrors(source); |
| 7223 assertNoErrors(source); |
| 7224 } |
| 7225 |
| 7226 void test_undefinedOperator_prefixExpression() { |
| 7227 Source source = addSource(r''' |
| 7228 class A {} |
| 7229 class B extends A { |
| 7230 operator +(B b) {return new B();} |
| 7231 } |
| 7232 f(var a) { |
| 7233 if(a is A) { |
| 7234 ++a; |
| 7235 } |
| 7236 }'''); |
| 7237 computeLibrarySourceErrors(source); |
| 7238 assertNoErrors(source); |
| 7239 } |
| 7240 |
| 7241 void test_undefinedSetter_inSubtype() { |
| 7242 Source source = addSource(r''' |
| 7243 class A {} |
| 7244 class B extends A { |
| 7245 set b(x) {} |
| 7246 } |
| 7247 f(var a) { |
| 7248 if(a is A) { |
| 7249 a.b = 0; |
| 7250 } |
| 7251 }'''); |
| 7252 computeLibrarySourceErrors(source); |
| 7253 assertNoErrors(source); |
| 7254 } |
| 7255 |
| 7256 void test_unnecessaryCast_13855_parameter_A() { |
| 7257 // dartbug.com/13855, dartbug.com/13732 |
| 7258 Source source = addSource(r''' |
| 7259 class A{ |
| 7260 a() {} |
| 7261 } |
| 7262 class B<E> { |
| 7263 E e; |
| 7264 m() { |
| 7265 (e as A).a(); |
| 7266 } |
| 7267 }'''); |
| 7268 computeLibrarySourceErrors(source); |
| 7269 assertNoErrors(source); |
| 7270 verify([source]); |
| 7271 } |
| 7272 |
| 7273 void test_unnecessaryCast_conditionalExpression() { |
| 7274 Source source = addSource(r''' |
| 7275 abstract class I {} |
| 7276 class A implements I {} |
| 7277 class B implements I {} |
| 7278 I m(A a, B b) { |
| 7279 return a == null ? b as I : a as I; |
| 7280 }'''); |
| 7281 computeLibrarySourceErrors(source); |
| 7282 assertNoErrors(source); |
| 7283 verify([source]); |
| 7284 } |
| 7285 |
| 7286 void test_unnecessaryCast_dynamic_type() { |
| 7287 Source source = addSource(r''' |
| 7288 m(v) { |
| 7289 var b = v as Object; |
| 7290 }'''); |
| 7291 computeLibrarySourceErrors(source); |
| 7292 assertNoErrors(source); |
| 7293 verify([source]); |
| 7294 } |
| 7295 |
| 7296 void test_unnecessaryCast_generics() { |
| 7297 // dartbug.com/18953 |
| 7298 Source source = addSource(r''' |
| 7299 import 'dart:async'; |
| 7300 Future<int> f() => new Future.value(0); |
| 7301 void g(bool c) { |
| 7302 (c ? f(): new Future.value(0) as Future<int>).then((int value) {}); |
| 7303 }'''); |
| 7304 computeLibrarySourceErrors(source); |
| 7305 assertNoErrors(source); |
| 7306 verify([source]); |
| 7307 } |
| 7308 |
| 7309 void test_unnecessaryCast_type_dynamic() { |
| 7310 Source source = addSource(r''' |
| 7311 m(v) { |
| 7312 var b = Object as dynamic; |
| 7313 }'''); |
| 7314 computeLibrarySourceErrors(source); |
| 7315 assertNoErrors(source); |
| 7316 verify([source]); |
| 7317 } |
| 7318 |
| 7319 void test_unusedImport_annotationOnDirective() { |
| 7320 Source source = addSource(r''' |
| 7321 library L; |
| 7322 @A() |
| 7323 import 'lib1.dart';'''); |
| 7324 Source source2 = addNamedSource( |
| 7325 "/lib1.dart", |
| 7326 r''' |
| 7327 library lib1; |
| 7328 class A { |
| 7329 const A() {} |
| 7330 }'''); |
| 7331 computeLibrarySourceErrors(source); |
| 7332 assertErrors(source); |
| 7333 verify([source, source2]); |
| 7334 } |
| 7335 |
| 7336 void test_unusedImport_as_equalPrefixes() { |
| 7337 // 18818 |
| 7338 Source source = addSource(r''' |
| 7339 library L; |
| 7340 import 'lib1.dart' as one; |
| 7341 import 'lib2.dart' as one; |
| 7342 one.A a; |
| 7343 one.B b;'''); |
| 7344 Source source2 = addNamedSource( |
| 7345 "/lib1.dart", |
| 7346 r''' |
| 7347 library lib1; |
| 7348 class A {}'''); |
| 7349 Source source3 = addNamedSource( |
| 7350 "/lib2.dart", |
| 7351 r''' |
| 7352 library lib2; |
| 7353 class B {}'''); |
| 7354 computeLibrarySourceErrors(source); |
| 7355 assertErrors(source); |
| 7356 assertNoErrors(source2); |
| 7357 assertNoErrors(source3); |
| 7358 verify([source, source2, source3]); |
| 7359 } |
| 7360 |
| 7361 void test_unusedImport_core_library() { |
| 7362 Source source = addSource(r''' |
| 7363 library L; |
| 7364 import 'dart:core';'''); |
| 7365 computeLibrarySourceErrors(source); |
| 7366 assertNoErrors(source); |
| 7367 verify([source]); |
| 7368 } |
| 7369 |
| 7370 void test_unusedImport_export() { |
| 7371 Source source = addSource(r''' |
| 7372 library L; |
| 7373 import 'lib1.dart'; |
| 7374 Two two;'''); |
| 7375 addNamedSource( |
| 7376 "/lib1.dart", |
| 7377 r''' |
| 7378 library lib1; |
| 7379 export 'lib2.dart'; |
| 7380 class One {}'''); |
| 7381 addNamedSource( |
| 7382 "/lib2.dart", |
| 7383 r''' |
| 7384 library lib2; |
| 7385 class Two {}'''); |
| 7386 computeLibrarySourceErrors(source); |
| 7387 assertNoErrors(source); |
| 7388 verify([source]); |
| 7389 } |
| 7390 |
| 7391 void test_unusedImport_export2() { |
| 7392 Source source = addSource(r''' |
| 7393 library L; |
| 7394 import 'lib1.dart'; |
| 7395 Three three;'''); |
| 7396 addNamedSource( |
| 7397 "/lib1.dart", |
| 7398 r''' |
| 7399 library lib1; |
| 7400 export 'lib2.dart'; |
| 7401 class One {}'''); |
| 7402 addNamedSource( |
| 7403 "/lib2.dart", |
| 7404 r''' |
| 7405 library lib2; |
| 7406 export 'lib3.dart'; |
| 7407 class Two {}'''); |
| 7408 addNamedSource( |
| 7409 "/lib3.dart", |
| 7410 r''' |
| 7411 library lib3; |
| 7412 class Three {}'''); |
| 7413 computeLibrarySourceErrors(source); |
| 7414 assertNoErrors(source); |
| 7415 verify([source]); |
| 7416 } |
| 7417 |
| 7418 void test_unusedImport_export_infiniteLoop() { |
| 7419 Source source = addSource(r''' |
| 7420 library L; |
| 7421 import 'lib1.dart'; |
| 7422 Two two;'''); |
| 7423 addNamedSource( |
| 7424 "/lib1.dart", |
| 7425 r''' |
| 7426 library lib1; |
| 7427 export 'lib2.dart'; |
| 7428 class One {}'''); |
| 7429 addNamedSource( |
| 7430 "/lib2.dart", |
| 7431 r''' |
| 7432 library lib2; |
| 7433 export 'lib3.dart'; |
| 7434 class Two {}'''); |
| 7435 addNamedSource( |
| 7436 "/lib3.dart", |
| 7437 r''' |
| 7438 library lib3; |
| 7439 export 'lib2.dart'; |
| 7440 class Three {}'''); |
| 7441 computeLibrarySourceErrors(source); |
| 7442 assertNoErrors(source); |
| 7443 verify([source]); |
| 7444 } |
| 7445 |
| 7446 void test_unusedImport_metadata() { |
| 7447 Source source = addSource(r''' |
| 7448 library L; |
| 7449 @A(x) |
| 7450 import 'lib1.dart'; |
| 7451 class A { |
| 7452 final int value; |
| 7453 const A(this.value); |
| 7454 }'''); |
| 7455 addNamedSource( |
| 7456 "/lib1.dart", |
| 7457 r''' |
| 7458 library lib1; |
| 7459 const x = 0;'''); |
| 7460 computeLibrarySourceErrors(source); |
| 7461 assertNoErrors(source); |
| 7462 verify([source]); |
| 7463 } |
| 7464 |
| 7465 void test_unusedImport_prefix_topLevelFunction() { |
| 7466 Source source = addSource(r''' |
| 7467 library L; |
| 7468 import 'lib1.dart' hide topLevelFunction; |
| 7469 import 'lib1.dart' as one show topLevelFunction; |
| 7470 class A { |
| 7471 static void x() { |
| 7472 One o; |
| 7473 one.topLevelFunction(); |
| 7474 } |
| 7475 }'''); |
| 7476 addNamedSource( |
| 7477 "/lib1.dart", |
| 7478 r''' |
| 7479 library lib1; |
| 7480 class One {} |
| 7481 topLevelFunction() {}'''); |
| 7482 computeLibrarySourceErrors(source); |
| 7483 assertNoErrors(source); |
| 7484 verify([source]); |
| 7485 } |
| 7486 |
| 7487 void test_useOfVoidResult_implicitReturnValue() { |
| 7488 Source source = addSource(r''' |
| 7489 f() {} |
| 7490 class A { |
| 7491 n() { |
| 7492 var a = f(); |
| 7493 } |
| 7494 }'''); |
| 7495 computeLibrarySourceErrors(source); |
| 7496 assertNoErrors(source); |
| 7497 verify([source]); |
| 7498 } |
| 7499 |
| 7500 void test_useOfVoidResult_nonVoidReturnValue() { |
| 7501 Source source = addSource(r''' |
| 7502 int f() => 1; |
| 7503 g() { |
| 7504 var a = f(); |
| 7505 }'''); |
| 7506 computeLibrarySourceErrors(source); |
| 7507 assertNoErrors(source); |
| 7508 verify([source]); |
| 7509 } |
| 7510 } |
| 7511 |
| 7512 class PubSuggestionCodeTest extends ResolverTestCase { |
| 7513 void test_import_package() { |
| 7514 Source source = addSource("import 'package:somepackage/other.dart';"); |
| 7515 computeLibrarySourceErrors(source); |
| 7516 assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]); |
| 7517 } |
| 7518 |
| 7519 void test_import_packageWithDotDot() { |
| 7520 Source source = addSource("import 'package:somepackage/../other.dart';"); |
| 7521 computeLibrarySourceErrors(source); |
| 7522 assertErrors(source, [ |
| 7523 CompileTimeErrorCode.URI_DOES_NOT_EXIST, |
| 7524 HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT |
| 7525 ]); |
| 7526 } |
| 7527 |
| 7528 void test_import_packageWithLeadingDotDot() { |
| 7529 Source source = addSource("import 'package:../other.dart';"); |
| 7530 computeLibrarySourceErrors(source); |
| 7531 assertErrors(source, [ |
| 7532 CompileTimeErrorCode.URI_DOES_NOT_EXIST, |
| 7533 HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT |
| 7534 ]); |
| 7535 } |
| 7536 |
| 7537 void test_import_referenceIntoLibDirectory() { |
| 7538 cacheSource("/myproj/pubspec.yaml", ""); |
| 7539 cacheSource("/myproj/lib/other.dart", ""); |
| 7540 Source source = |
| 7541 addNamedSource("/myproj/web/test.dart", "import '../lib/other.dart';"); |
| 7542 computeLibrarySourceErrors(source); |
| 7543 assertErrors( |
| 7544 source, [HintCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE]); |
| 7545 } |
| 7546 |
| 7547 void test_import_referenceIntoLibDirectory_no_pubspec() { |
| 7548 cacheSource("/myproj/lib/other.dart", ""); |
| 7549 Source source = |
| 7550 addNamedSource("/myproj/web/test.dart", "import '../lib/other.dart';"); |
| 7551 computeLibrarySourceErrors(source); |
| 7552 assertNoErrors(source); |
| 7553 } |
| 7554 |
| 7555 void test_import_referenceOutOfLibDirectory() { |
| 7556 cacheSource("/myproj/pubspec.yaml", ""); |
| 7557 cacheSource("/myproj/web/other.dart", ""); |
| 7558 Source source = |
| 7559 addNamedSource("/myproj/lib/test.dart", "import '../web/other.dart';"); |
| 7560 computeLibrarySourceErrors(source); |
| 7561 assertErrors( |
| 7562 source, [HintCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE]); |
| 7563 } |
| 7564 |
| 7565 void test_import_referenceOutOfLibDirectory_no_pubspec() { |
| 7566 cacheSource("/myproj/web/other.dart", ""); |
| 7567 Source source = |
| 7568 addNamedSource("/myproj/lib/test.dart", "import '../web/other.dart';"); |
| 7569 computeLibrarySourceErrors(source); |
| 7570 assertNoErrors(source); |
| 7571 } |
| 7572 |
| 7573 void test_import_valid_inside_lib1() { |
| 7574 cacheSource("/myproj/pubspec.yaml", ""); |
| 7575 cacheSource("/myproj/lib/other.dart", ""); |
| 7576 Source source = |
| 7577 addNamedSource("/myproj/lib/test.dart", "import 'other.dart';"); |
| 7578 computeLibrarySourceErrors(source); |
| 7579 assertNoErrors(source); |
| 7580 } |
| 7581 |
| 7582 void test_import_valid_inside_lib2() { |
| 7583 cacheSource("/myproj/pubspec.yaml", ""); |
| 7584 cacheSource("/myproj/lib/bar/other.dart", ""); |
| 7585 Source source = addNamedSource( |
| 7586 "/myproj/lib/foo/test.dart", "import '../bar/other.dart';"); |
| 7587 computeLibrarySourceErrors(source); |
| 7588 assertNoErrors(source); |
| 7589 } |
| 7590 |
| 7591 void test_import_valid_outside_lib() { |
| 7592 cacheSource("/myproj/pubspec.yaml", ""); |
| 7593 cacheSource("/myproj/web/other.dart", ""); |
| 7594 Source source = |
| 7595 addNamedSource("/myproj/lib2/test.dart", "import '../web/other.dart';"); |
| 7596 computeLibrarySourceErrors(source); |
| 7597 assertNoErrors(source); |
| 7598 } |
| 7599 } |
| 7600 |
| 7601 /** |
| 7602 * An AST visitor used to verify that all of the nodes in an AST structure that |
| 7603 * should have been resolved were resolved. |
| 7604 */ |
| 7605 class ResolutionVerifier extends RecursiveAstVisitor<Object> { |
| 7606 /** |
| 7607 * A set containing nodes that are known to not be resolvable and should |
| 7608 * therefore not cause the test to fail. |
| 7609 */ |
| 7610 final Set<AstNode> _knownExceptions; |
| 7611 |
| 7612 /** |
| 7613 * A list containing all of the AST nodes that were not resolved. |
| 7614 */ |
| 7615 List<AstNode> _unresolvedNodes = new List<AstNode>(); |
| 7616 |
| 7617 /** |
| 7618 * A list containing all of the AST nodes that were resolved to an element of |
| 7619 * the wrong type. |
| 7620 */ |
| 7621 List<AstNode> _wrongTypedNodes = new List<AstNode>(); |
| 7622 |
| 7623 /** |
| 7624 * Initialize a newly created verifier to verify that all of the identifiers |
| 7625 * in the visited AST structures that are expected to have been resolved have |
| 7626 * an element associated with them. Nodes in the set of [_knownExceptions] are |
| 7627 * not expected to have been resolved, even if they normally would have been |
| 7628 * expected to have been resolved. |
| 7629 */ |
| 7630 ResolutionVerifier([this._knownExceptions]); |
| 7631 |
| 7632 /** |
| 7633 * Assert that all of the visited identifiers were resolved. |
| 7634 */ |
| 7635 void assertResolved() { |
| 7636 if (!_unresolvedNodes.isEmpty || !_wrongTypedNodes.isEmpty) { |
| 7637 StringBuffer buffer = new StringBuffer(); |
| 7638 if (!_unresolvedNodes.isEmpty) { |
| 7639 buffer.write("Failed to resolve "); |
| 7640 buffer.write(_unresolvedNodes.length); |
| 7641 buffer.writeln(" nodes:"); |
| 7642 _printNodes(buffer, _unresolvedNodes); |
| 7643 } |
| 7644 if (!_wrongTypedNodes.isEmpty) { |
| 7645 buffer.write("Resolved "); |
| 7646 buffer.write(_wrongTypedNodes.length); |
| 7647 buffer.writeln(" to the wrong type of element:"); |
| 7648 _printNodes(buffer, _wrongTypedNodes); |
| 7649 } |
| 7650 fail(buffer.toString()); |
| 7651 } |
| 7652 } |
| 7653 |
| 7654 @override |
| 7655 Object visitAnnotation(Annotation node) { |
| 7656 node.visitChildren(this); |
| 7657 ElementAnnotation elementAnnotation = node.elementAnnotation; |
| 7658 if (elementAnnotation == null) { |
| 7659 if (_knownExceptions == null || !_knownExceptions.contains(node)) { |
| 7660 _unresolvedNodes.add(node); |
| 7661 } |
| 7662 } else if (elementAnnotation is! ElementAnnotation) { |
| 7663 _wrongTypedNodes.add(node); |
| 7664 } |
| 7665 return null; |
| 7666 } |
| 7667 |
| 7668 @override |
| 7669 Object visitBinaryExpression(BinaryExpression node) { |
| 7670 node.visitChildren(this); |
| 7671 if (!node.operator.isUserDefinableOperator) { |
| 7672 return null; |
| 7673 } |
| 7674 DartType operandType = node.leftOperand.staticType; |
| 7675 if (operandType == null || operandType.isDynamic) { |
| 7676 return null; |
| 7677 } |
| 7678 return _checkResolved( |
| 7679 node, node.staticElement, (node) => node is MethodElement); |
| 7680 } |
| 7681 |
| 7682 @override |
| 7683 Object visitCommentReference(CommentReference node) => null; |
| 7684 |
| 7685 @override |
| 7686 Object visitCompilationUnit(CompilationUnit node) { |
| 7687 node.visitChildren(this); |
| 7688 return _checkResolved( |
| 7689 node, node.element, (node) => node is CompilationUnitElement); |
| 7690 } |
| 7691 |
| 7692 @override |
| 7693 Object visitExportDirective(ExportDirective node) => |
| 7694 _checkResolved(node, node.element, (node) => node is ExportElement); |
| 7695 |
| 7696 @override |
| 7697 Object visitFunctionDeclaration(FunctionDeclaration node) { |
| 7698 node.visitChildren(this); |
| 7699 if (node.element is LibraryElement) { |
| 7700 _wrongTypedNodes.add(node); |
| 7701 } |
| 7702 return null; |
| 7703 } |
| 7704 |
| 7705 @override |
| 7706 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
| 7707 node.visitChildren(this); |
| 7708 // TODO(brianwilkerson) If we start resolving function expressions, then |
| 7709 // conditionally check to see whether the node was resolved correctly. |
| 7710 return null; |
| 7711 //checkResolved(node, node.getElement(), FunctionElement.class); |
| 7712 } |
| 7713 |
| 7714 @override |
| 7715 Object visitImportDirective(ImportDirective node) { |
| 7716 // Not sure how to test the combinators given that it isn't an error if the |
| 7717 // names are not defined. |
| 7718 _checkResolved(node, node.element, (node) => node is ImportElement); |
| 7719 SimpleIdentifier prefix = node.prefix; |
| 7720 if (prefix == null) { |
| 7721 return null; |
| 7722 } |
| 7723 return _checkResolved( |
| 7724 prefix, prefix.staticElement, (node) => node is PrefixElement); |
| 7725 } |
| 7726 |
| 7727 @override |
| 7728 Object visitIndexExpression(IndexExpression node) { |
| 7729 node.visitChildren(this); |
| 7730 DartType targetType = node.realTarget.staticType; |
| 7731 if (targetType == null || targetType.isDynamic) { |
| 7732 return null; |
| 7733 } |
| 7734 return _checkResolved( |
| 7735 node, node.staticElement, (node) => node is MethodElement); |
| 7736 } |
| 7737 |
| 7738 @override |
| 7739 Object visitLibraryDirective(LibraryDirective node) => |
| 7740 _checkResolved(node, node.element, (node) => node is LibraryElement); |
| 7741 |
| 7742 @override |
| 7743 Object visitNamedExpression(NamedExpression node) => |
| 7744 node.expression.accept(this); |
| 7745 |
| 7746 @override |
| 7747 Object visitPartDirective(PartDirective node) => _checkResolved( |
| 7748 node, node.element, (node) => node is CompilationUnitElement); |
| 7749 |
| 7750 @override |
| 7751 Object visitPartOfDirective(PartOfDirective node) => |
| 7752 _checkResolved(node, node.element, (node) => node is LibraryElement); |
| 7753 |
| 7754 @override |
| 7755 Object visitPostfixExpression(PostfixExpression node) { |
| 7756 node.visitChildren(this); |
| 7757 if (!node.operator.isUserDefinableOperator) { |
| 7758 return null; |
| 7759 } |
| 7760 DartType operandType = node.operand.staticType; |
| 7761 if (operandType == null || operandType.isDynamic) { |
| 7762 return null; |
| 7763 } |
| 7764 return _checkResolved( |
| 7765 node, node.staticElement, (node) => node is MethodElement); |
| 7766 } |
| 7767 |
| 7768 @override |
| 7769 Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 7770 SimpleIdentifier prefix = node.prefix; |
| 7771 prefix.accept(this); |
| 7772 DartType prefixType = prefix.staticType; |
| 7773 if (prefixType == null || prefixType.isDynamic) { |
| 7774 return null; |
| 7775 } |
| 7776 return _checkResolved(node, node.staticElement, null); |
| 7777 } |
| 7778 |
| 7779 @override |
| 7780 Object visitPrefixExpression(PrefixExpression node) { |
| 7781 node.visitChildren(this); |
| 7782 if (!node.operator.isUserDefinableOperator) { |
| 7783 return null; |
| 7784 } |
| 7785 DartType operandType = node.operand.staticType; |
| 7786 if (operandType == null || operandType.isDynamic) { |
| 7787 return null; |
| 7788 } |
| 7789 return _checkResolved( |
| 7790 node, node.staticElement, (node) => node is MethodElement); |
| 7791 } |
| 7792 |
| 7793 @override |
| 7794 Object visitPropertyAccess(PropertyAccess node) { |
| 7795 Expression target = node.realTarget; |
| 7796 target.accept(this); |
| 7797 DartType targetType = target.staticType; |
| 7798 if (targetType == null || targetType.isDynamic) { |
| 7799 return null; |
| 7800 } |
| 7801 return node.propertyName.accept(this); |
| 7802 } |
| 7803 |
| 7804 @override |
| 7805 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 7806 if (node.name == "void") { |
| 7807 return null; |
| 7808 } |
| 7809 AstNode parent = node.parent; |
| 7810 if (parent is MethodInvocation) { |
| 7811 MethodInvocation invocation = parent; |
| 7812 if (identical(invocation.methodName, node)) { |
| 7813 Expression target = invocation.realTarget; |
| 7814 DartType targetType = target == null ? null : target.staticType; |
| 7815 if (targetType == null || targetType.isDynamic) { |
| 7816 return null; |
| 7817 } |
| 7818 } |
| 7819 } |
| 7820 return _checkResolved(node, node.staticElement, null); |
| 7821 } |
| 7822 |
| 7823 Object _checkResolved( |
| 7824 AstNode node, Element element, Predicate<Element> predicate) { |
| 7825 if (element == null) { |
| 7826 if (_knownExceptions == null || !_knownExceptions.contains(node)) { |
| 7827 _unresolvedNodes.add(node); |
| 7828 } |
| 7829 } else if (predicate != null) { |
| 7830 if (!predicate(element)) { |
| 7831 _wrongTypedNodes.add(node); |
| 7832 } |
| 7833 } |
| 7834 return null; |
| 7835 } |
| 7836 |
| 7837 String _getFileName(AstNode node) { |
| 7838 // TODO (jwren) there are two copies of this method, one here and one in |
| 7839 // StaticTypeVerifier, they should be resolved into a single method |
| 7840 if (node != null) { |
| 7841 AstNode root = node.root; |
| 7842 if (root is CompilationUnit) { |
| 7843 CompilationUnit rootCU = root; |
| 7844 if (rootCU.element != null) { |
| 7845 return rootCU.element.source.fullName; |
| 7846 } else { |
| 7847 return "<unknown file- CompilationUnit.getElement() returned null>"; |
| 7848 } |
| 7849 } else { |
| 7850 return "<unknown file- CompilationUnit.getRoot() is not a CompilationUni
t>"; |
| 7851 } |
| 7852 } |
| 7853 return "<unknown file- ASTNode is null>"; |
| 7854 } |
| 7855 |
| 7856 void _printNodes(StringBuffer buffer, List<AstNode> nodes) { |
| 7857 for (AstNode identifier in nodes) { |
| 7858 buffer.write(" "); |
| 7859 buffer.write(identifier.toString()); |
| 7860 buffer.write(" ("); |
| 7861 buffer.write(_getFileName(identifier)); |
| 7862 buffer.write(" : "); |
| 7863 buffer.write(identifier.offset); |
| 7864 buffer.writeln(")"); |
| 7865 } |
| 7866 } |
| 7867 } |
| 7868 |
| 7869 class ResolverTestCase extends EngineTestCase { |
| 7870 /** |
| 7871 * The analysis context used to parse the compilation units being resolved. |
| 7872 */ |
| 7873 InternalAnalysisContext analysisContext2; |
| 7874 |
| 7875 /** |
| 7876 * Specifies if [assertErrors] should check for [HintCode.UNUSED_ELEMENT] and |
| 7877 * [HintCode.UNUSED_FIELD]. |
| 7878 */ |
| 7879 bool enableUnusedElement = false; |
| 7880 |
| 7881 /** |
| 7882 * Specifies if [assertErrors] should check for [HintCode.UNUSED_LOCAL_VARIABL
E]. |
| 7883 */ |
| 7884 bool enableUnusedLocalVariable = false; |
| 7885 |
| 7886 AnalysisContext get analysisContext => analysisContext2; |
| 7887 |
| 7888 /** |
| 7889 * Return a type provider that can be used to test the results of resolution. |
| 7890 * |
| 7891 * @return a type provider |
| 7892 * @throws AnalysisException if dart:core cannot be resolved |
| 7893 */ |
| 7894 TypeProvider get typeProvider => analysisContext2.typeProvider; |
| 7895 |
| 7896 /** |
| 7897 * Add a source file to the content provider. The file path should be absolute
. |
| 7898 * |
| 7899 * @param filePath the path of the file being added |
| 7900 * @param contents the contents to be returned by the content provider for the
specified file |
| 7901 * @return the source object representing the added file |
| 7902 */ |
| 7903 Source addNamedSource(String filePath, String contents) { |
| 7904 Source source = cacheSource(filePath, contents); |
| 7905 ChangeSet changeSet = new ChangeSet(); |
| 7906 changeSet.addedSource(source); |
| 7907 analysisContext2.applyChanges(changeSet); |
| 7908 return source; |
| 7909 } |
| 7910 |
| 7911 /** |
| 7912 * Add a source file to the content provider. |
| 7913 * |
| 7914 * @param contents the contents to be returned by the content provider for the
specified file |
| 7915 * @return the source object representing the added file |
| 7916 */ |
| 7917 Source addSource(String contents) => addNamedSource("/test.dart", contents); |
| 7918 |
| 7919 /** |
| 7920 * Assert that the number of errors reported against the given source matches
the number of errors |
| 7921 * that are given and that they have the expected error codes. The order in wh
ich the errors were |
| 7922 * gathered is ignored. |
| 7923 * |
| 7924 * @param source the source against which the errors should have been reported |
| 7925 * @param expectedErrorCodes the error codes of the errors that should have be
en reported |
| 7926 * @throws AnalysisException if the reported errors could not be computed |
| 7927 * @throws AssertionFailedError if a different number of errors have been repo
rted than were |
| 7928 * expected |
| 7929 */ |
| 7930 void assertErrors(Source source, |
| 7931 [List<ErrorCode> expectedErrorCodes = ErrorCode.EMPTY_LIST]) { |
| 7932 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 7933 for (AnalysisError error in analysisContext2.computeErrors(source)) { |
| 7934 ErrorCode errorCode = error.errorCode; |
| 7935 if (!enableUnusedElement && |
| 7936 (errorCode == HintCode.UNUSED_ELEMENT || |
| 7937 errorCode == HintCode.UNUSED_FIELD)) { |
| 7938 continue; |
| 7939 } |
| 7940 if (!enableUnusedLocalVariable && |
| 7941 (errorCode == HintCode.UNUSED_CATCH_CLAUSE || |
| 7942 errorCode == HintCode.UNUSED_CATCH_STACK || |
| 7943 errorCode == HintCode.UNUSED_LOCAL_VARIABLE)) { |
| 7944 continue; |
| 7945 } |
| 7946 errorListener.onError(error); |
| 7947 } |
| 7948 errorListener.assertErrorsWithCodes(expectedErrorCodes); |
| 7949 } |
| 7950 |
| 7951 /** |
| 7952 * Assert that no errors have been reported against the given source. |
| 7953 * |
| 7954 * @param source the source against which no errors should have been reported |
| 7955 * @throws AnalysisException if the reported errors could not be computed |
| 7956 * @throws AssertionFailedError if any errors have been reported |
| 7957 */ |
| 7958 void assertNoErrors(Source source) { |
| 7959 assertErrors(source); |
| 7960 } |
| 7961 |
| 7962 /** |
| 7963 * Cache the source file content in the source factory but don't add the sourc
e to the analysis |
| 7964 * context. The file path should be absolute. |
| 7965 * |
| 7966 * @param filePath the path of the file being cached |
| 7967 * @param contents the contents to be returned by the content provider for the
specified file |
| 7968 * @return the source object representing the cached file |
| 7969 */ |
| 7970 Source cacheSource(String filePath, String contents) { |
| 7971 Source source = new FileBasedSource(FileUtilities2.createFile(filePath)); |
| 7972 analysisContext2.setContents(source, contents); |
| 7973 return source; |
| 7974 } |
| 7975 |
| 7976 /** |
| 7977 * Computes errors for the given [librarySource]. |
| 7978 * This assumes that the given [librarySource] and its parts have already |
| 7979 * been added to the content provider using the method [addNamedSource]. |
| 7980 */ |
| 7981 void computeLibrarySourceErrors(Source librarySource) { |
| 7982 analysisContext.computeErrors(librarySource); |
| 7983 } |
| 7984 |
| 7985 /** |
| 7986 * Create a library element that represents a library named `"test"` containin
g a single |
| 7987 * empty compilation unit. |
| 7988 * |
| 7989 * @return the library element that was created |
| 7990 */ |
| 7991 LibraryElementImpl createDefaultTestLibrary() => |
| 7992 createTestLibrary(AnalysisContextFactory.contextWithCore(), "test"); |
| 7993 |
| 7994 /** |
| 7995 * Create a library element that represents a library with the given name cont
aining a single |
| 7996 * empty compilation unit. |
| 7997 * |
| 7998 * @param libraryName the name of the library to be created |
| 7999 * @return the library element that was created |
| 8000 */ |
| 8001 LibraryElementImpl createTestLibrary( |
| 8002 AnalysisContext context, String libraryName, |
| 8003 [List<String> typeNames]) { |
| 8004 String fileName = "$libraryName.dart"; |
| 8005 FileBasedSource definingCompilationUnitSource = |
| 8006 _createNamedSource(fileName); |
| 8007 List<CompilationUnitElement> sourcedCompilationUnits; |
| 8008 if (typeNames == null) { |
| 8009 sourcedCompilationUnits = CompilationUnitElement.EMPTY_LIST; |
| 8010 } else { |
| 8011 int count = typeNames.length; |
| 8012 sourcedCompilationUnits = new List<CompilationUnitElement>(count); |
| 8013 for (int i = 0; i < count; i++) { |
| 8014 String typeName = typeNames[i]; |
| 8015 ClassElementImpl type = |
| 8016 new ClassElementImpl.forNode(AstFactory.identifier3(typeName)); |
| 8017 String fileName = "$typeName.dart"; |
| 8018 CompilationUnitElementImpl compilationUnit = |
| 8019 new CompilationUnitElementImpl(fileName); |
| 8020 compilationUnit.source = _createNamedSource(fileName); |
| 8021 compilationUnit.librarySource = definingCompilationUnitSource; |
| 8022 compilationUnit.types = <ClassElement>[type]; |
| 8023 sourcedCompilationUnits[i] = compilationUnit; |
| 8024 } |
| 8025 } |
| 8026 CompilationUnitElementImpl compilationUnit = |
| 8027 new CompilationUnitElementImpl(fileName); |
| 8028 compilationUnit.librarySource = |
| 8029 compilationUnit.source = definingCompilationUnitSource; |
| 8030 LibraryElementImpl library = new LibraryElementImpl.forNode( |
| 8031 context, AstFactory.libraryIdentifier2([libraryName])); |
| 8032 library.definingCompilationUnit = compilationUnit; |
| 8033 library.parts = sourcedCompilationUnits; |
| 8034 return library; |
| 8035 } |
| 8036 |
| 8037 Expression findTopLevelConstantExpression( |
| 8038 CompilationUnit compilationUnit, String name) => |
| 8039 findTopLevelDeclaration(compilationUnit, name).initializer; |
| 8040 |
| 8041 VariableDeclaration findTopLevelDeclaration( |
| 8042 CompilationUnit compilationUnit, String name) { |
| 8043 for (CompilationUnitMember member in compilationUnit.declarations) { |
| 8044 if (member is TopLevelVariableDeclaration) { |
| 8045 for (VariableDeclaration variable in member.variables.variables) { |
| 8046 if (variable.name.name == name) { |
| 8047 return variable; |
| 8048 } |
| 8049 } |
| 8050 } |
| 8051 } |
| 8052 return null; |
| 8053 // Not found |
| 8054 } |
| 8055 |
| 8056 /** |
| 8057 * @param code the code that assigns the value to the variable "v", no matter
how. We check that |
| 8058 * "v" has expected static and propagated type. |
| 8059 */ |
| 8060 void _assertPropagatedAssignedType(String code, DartType expectedStaticType, |
| 8061 DartType expectedPropagatedType) { |
| 8062 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = "); |
| 8063 expect(identifier.staticType, same(expectedStaticType)); |
| 8064 expect(identifier.propagatedType, same(expectedPropagatedType)); |
| 8065 } |
| 8066 |
| 8067 /** |
| 8068 * Check the static and propagated types of the expression marked with "; // m
arker" comment. |
| 8069 * |
| 8070 * @param code source code to analyze, with the expression to check marked wit
h "// marker". |
| 8071 * @param expectedStaticType if non-null, check actual static type is equal to
this. |
| 8072 * @param expectedPropagatedType if non-null, check actual static type is equa
l to this. |
| 8073 * @throws Exception |
| 8074 */ |
| 8075 void _assertTypeOfMarkedExpression(String code, DartType expectedStaticType, |
| 8076 DartType expectedPropagatedType) { |
| 8077 SimpleIdentifier identifier = _findMarkedIdentifier(code, "; // marker"); |
| 8078 if (expectedStaticType != null) { |
| 8079 expect(identifier.staticType, expectedStaticType); |
| 8080 } |
| 8081 expect(identifier.propagatedType, expectedPropagatedType); |
| 8082 } |
| 8083 |
| 8084 /** |
| 8085 * Return the `SimpleIdentifier` marked by `marker`. The source code must have
no |
| 8086 * errors and be verifiable. |
| 8087 * |
| 8088 * @param code source code to analyze. |
| 8089 * @param marker marker identifying sought after expression in source code. |
| 8090 * @return expression marked by the marker. |
| 8091 * @throws Exception |
| 8092 */ |
| 8093 SimpleIdentifier _findMarkedIdentifier(String code, String marker) { |
| 8094 try { |
| 8095 Source source = addSource(code); |
| 8096 LibraryElement library = resolve2(source); |
| 8097 assertNoErrors(source); |
| 8098 verify([source]); |
| 8099 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 8100 // Could generalize this further by making [SimpleIdentifier.class] a |
| 8101 // parameter. |
| 8102 return EngineTestCase.findNode( |
| 8103 unit, code, marker, (node) => node is SimpleIdentifier); |
| 8104 } catch (exception) { |
| 8105 // Is there a better exception to throw here? The point is that an |
| 8106 // assertion failure here should be a failure, in both "test_*" and |
| 8107 // "fail_*" tests. However, an assertion failure is success for the |
| 8108 // purpose of "fail_*" tests, so without catching them here "fail_*" tests |
| 8109 // can succeed by failing for the wrong reason. |
| 8110 throw new JavaException("Unexexpected assertion failure: $exception"); |
| 8111 } |
| 8112 } |
| 8113 |
| 8114 /** |
| 8115 * In the rare cases we want to group several tests into single "test_" method
, so need a way to |
| 8116 * reset test instance to reuse it. |
| 8117 */ |
| 8118 void reset() { |
| 8119 analysisContext2 = AnalysisContextFactory.contextWithCore(); |
| 8120 } |
| 8121 |
| 8122 /** |
| 8123 * Reset the analysis context to have the given options applied. |
| 8124 * |
| 8125 * @param options the analysis options to be applied to the context |
| 8126 */ |
| 8127 void resetWithOptions(AnalysisOptions options) { |
| 8128 analysisContext2 = |
| 8129 AnalysisContextFactory.contextWithCoreAndOptions(options); |
| 8130 } |
| 8131 |
| 8132 /** |
| 8133 * Given a library and all of its parts, resolve the contents of the library a
nd the contents of |
| 8134 * the parts. This assumes that the sources for the library and its parts have
already been added |
| 8135 * to the content provider using the method [addNamedSource]. |
| 8136 * |
| 8137 * @param librarySource the source for the compilation unit that defines the l
ibrary |
| 8138 * @return the element representing the resolved library |
| 8139 * @throws AnalysisException if the analysis could not be performed |
| 8140 */ |
| 8141 LibraryElement resolve2(Source librarySource) => |
| 8142 analysisContext2.computeLibraryElement(librarySource); |
| 8143 |
| 8144 /** |
| 8145 * Return the resolved compilation unit corresponding to the given source in t
he given library. |
| 8146 * |
| 8147 * @param source the source of the compilation unit to be returned |
| 8148 * @param library the library in which the compilation unit is to be resolved |
| 8149 * @return the resolved compilation unit |
| 8150 * @throws Exception if the compilation unit could not be resolved |
| 8151 */ |
| 8152 CompilationUnit resolveCompilationUnit( |
| 8153 Source source, LibraryElement library) => |
| 8154 analysisContext2.resolveCompilationUnit(source, library); |
| 8155 |
| 8156 CompilationUnit resolveSource(String sourceText) => |
| 8157 resolveSource2("/test.dart", sourceText); |
| 8158 |
| 8159 CompilationUnit resolveSource2(String fileName, String sourceText) { |
| 8160 Source source = addNamedSource(fileName, sourceText); |
| 8161 LibraryElement library = analysisContext.computeLibraryElement(source); |
| 8162 return analysisContext.resolveCompilationUnit(source, library); |
| 8163 } |
| 8164 |
| 8165 Source resolveSources(List<String> sourceTexts) { |
| 8166 for (int i = 0; i < sourceTexts.length; i++) { |
| 8167 CompilationUnit unit = |
| 8168 resolveSource2("/lib${i + 1}.dart", sourceTexts[i]); |
| 8169 // reference the source if this is the last source |
| 8170 if (i + 1 == sourceTexts.length) { |
| 8171 return unit.element.source; |
| 8172 } |
| 8173 } |
| 8174 return null; |
| 8175 } |
| 8176 |
| 8177 void resolveWithAndWithoutExperimental( |
| 8178 List<String> strSources, |
| 8179 List<ErrorCode> codesWithoutExperimental, |
| 8180 List<ErrorCode> codesWithExperimental) { |
| 8181 // Setup analysis context as non-experimental |
| 8182 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 8183 // options.enableDeferredLoading = false; |
| 8184 resetWithOptions(options); |
| 8185 // Analysis and assertions |
| 8186 Source source = resolveSources(strSources); |
| 8187 assertErrors(source, codesWithoutExperimental); |
| 8188 verify([source]); |
| 8189 // Setup analysis context as experimental |
| 8190 reset(); |
| 8191 // Analysis and assertions |
| 8192 source = resolveSources(strSources); |
| 8193 assertErrors(source, codesWithExperimental); |
| 8194 verify([source]); |
| 8195 } |
| 8196 |
| 8197 void resolveWithErrors(List<String> strSources, List<ErrorCode> codes) { |
| 8198 // Analysis and assertions |
| 8199 Source source = resolveSources(strSources); |
| 8200 assertErrors(source, codes); |
| 8201 verify([source]); |
| 8202 } |
| 8203 |
| 8204 @override |
| 8205 void setUp() { |
| 8206 reset(); |
| 8207 } |
| 8208 |
| 8209 @override |
| 8210 void tearDown() { |
| 8211 analysisContext2 = null; |
| 8212 super.tearDown(); |
| 8213 } |
| 8214 |
| 8215 /** |
| 8216 * Verify that all of the identifiers in the compilation units associated with |
| 8217 * the given [sources] have been resolved. |
| 8218 */ |
| 8219 void verify(List<Source> sources) { |
| 8220 ResolutionVerifier verifier = new ResolutionVerifier(); |
| 8221 for (Source source in sources) { |
| 8222 List<Source> libraries = analysisContext2.getLibrariesContaining(source); |
| 8223 for (Source library in libraries) { |
| 8224 analysisContext2 |
| 8225 .resolveCompilationUnit2(source, library) |
| 8226 .accept(verifier); |
| 8227 } |
| 8228 } |
| 8229 verifier.assertResolved(); |
| 8230 } |
| 8231 |
| 8232 /** |
| 8233 * Create a source object representing a file with the given [fileName] and |
| 8234 * give it an empty content. Return the source that was created. |
| 8235 */ |
| 8236 FileBasedSource _createNamedSource(String fileName) { |
| 8237 FileBasedSource source = |
| 8238 new FileBasedSource(FileUtilities2.createFile(fileName)); |
| 8239 analysisContext2.setContents(source, ""); |
| 8240 return source; |
| 8241 } |
| 8242 } |
| 8243 |
| 8244 class Scope_EnclosedScopeTest_test_define_duplicate extends Scope { |
| 8245 GatheringErrorListener listener; |
| 8246 |
| 8247 Scope_EnclosedScopeTest_test_define_duplicate(this.listener) : super(); |
| 8248 |
| 8249 @override |
| 8250 AnalysisErrorListener get errorListener => listener; |
| 8251 |
| 8252 @override |
| 8253 Element internalLookup(Identifier identifier, String name, |
| 8254 LibraryElement referencingLibrary) => |
| 8255 null; |
| 8256 } |
| 8257 |
| 8258 class Scope_EnclosedScopeTest_test_define_normal extends Scope { |
| 8259 GatheringErrorListener listener; |
| 8260 |
| 8261 Scope_EnclosedScopeTest_test_define_normal(this.listener) : super(); |
| 8262 |
| 8263 @override |
| 8264 AnalysisErrorListener get errorListener => listener; |
| 8265 |
| 8266 @override |
| 8267 Element internalLookup(Identifier identifier, String name, |
| 8268 LibraryElement referencingLibrary) => |
| 8269 null; |
| 8270 } |
| 8271 |
| 8272 @reflectiveTest |
| 8273 class ScopeTest extends ResolverTestCase { |
| 8274 void test_define_duplicate() { |
| 8275 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 8276 ScopeTest_TestScope scope = new ScopeTest_TestScope(errorListener); |
| 8277 VariableElement element1 = |
| 8278 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 8279 VariableElement element2 = |
| 8280 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 8281 scope.define(element1); |
| 8282 scope.define(element2); |
| 8283 errorListener.assertErrorsWithSeverities([ErrorSeverity.ERROR]); |
| 8284 } |
| 8285 |
| 8286 void test_define_normal() { |
| 8287 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 8288 ScopeTest_TestScope scope = new ScopeTest_TestScope(errorListener); |
| 8289 VariableElement element1 = |
| 8290 ElementFactory.localVariableElement(AstFactory.identifier3("v1")); |
| 8291 VariableElement element2 = |
| 8292 ElementFactory.localVariableElement(AstFactory.identifier3("v2")); |
| 8293 scope.define(element1); |
| 8294 scope.define(element2); |
| 8295 errorListener.assertNoErrors(); |
| 8296 } |
| 8297 |
| 8298 void test_getErrorListener() { |
| 8299 GatheringErrorListener errorListener = new GatheringErrorListener(); |
| 8300 ScopeTest_TestScope scope = new ScopeTest_TestScope(errorListener); |
| 8301 expect(scope.errorListener, errorListener); |
| 8302 } |
| 8303 |
| 8304 void test_isPrivateName_nonPrivate() { |
| 8305 expect(Scope.isPrivateName("Public"), isFalse); |
| 8306 } |
| 8307 |
| 8308 void test_isPrivateName_private() { |
| 8309 expect(Scope.isPrivateName("_Private"), isTrue); |
| 8310 } |
| 8311 } |
| 8312 |
| 8313 /** |
| 8314 * A non-abstract subclass that can be used for testing purposes. |
| 8315 */ |
| 8316 class ScopeTest_TestScope extends Scope { |
| 8317 /** |
| 8318 * The listener that is to be informed when an error is encountered. |
| 8319 */ |
| 8320 final AnalysisErrorListener errorListener; |
| 8321 |
| 8322 ScopeTest_TestScope(this.errorListener); |
| 8323 |
| 8324 @override |
| 8325 Element internalLookup(Identifier identifier, String name, |
| 8326 LibraryElement referencingLibrary) => |
| 8327 localLookup(name, referencingLibrary); |
| 8328 } |
| 8329 |
| 8330 @reflectiveTest |
| 8331 class SimpleResolverTest extends ResolverTestCase { |
| 8332 void fail_getter_and_setter_fromMixins_property_access() { |
| 8333 // TODO(paulberry): it appears that auxiliaryElements isn't properly set on |
| 8334 // a SimpleIdentifier that's inside a property access. This bug should be |
| 8335 // fixed. |
| 8336 Source source = addSource(''' |
| 8337 class B {} |
| 8338 class M1 { |
| 8339 get x => null; |
| 8340 set x(value) {} |
| 8341 } |
| 8342 class M2 { |
| 8343 get x => null; |
| 8344 set x(value) {} |
| 8345 } |
| 8346 class C extends B with M1, M2 {} |
| 8347 void main() { |
| 8348 new C().x += 1; |
| 8349 } |
| 8350 '''); |
| 8351 LibraryElement library = resolve2(source); |
| 8352 assertNoErrors(source); |
| 8353 verify([source]); |
| 8354 // Verify that both the getter and setter for "x" in "new C().x" refer to |
| 8355 // the accessors defined in M2. |
| 8356 FunctionDeclaration main = |
| 8357 library.definingCompilationUnit.functions[0].computeNode(); |
| 8358 BlockFunctionBody body = main.functionExpression.body; |
| 8359 ExpressionStatement stmt = body.block.statements[0]; |
| 8360 AssignmentExpression assignment = stmt.expression; |
| 8361 PropertyAccess propertyAccess = assignment.leftHandSide; |
| 8362 expect( |
| 8363 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 8364 expect( |
| 8365 propertyAccess |
| 8366 .propertyName.auxiliaryElements.staticElement.enclosingElement.name, |
| 8367 'M2'); |
| 8368 } |
| 8369 |
| 8370 void fail_staticInvocation() { |
| 8371 Source source = addSource(r''' |
| 8372 class A { |
| 8373 static int get g => (a,b) => 0; |
| 8374 } |
| 8375 class B { |
| 8376 f() { |
| 8377 A.g(1,0); |
| 8378 } |
| 8379 }'''); |
| 8380 computeLibrarySourceErrors(source); |
| 8381 assertNoErrors(source); |
| 8382 verify([source]); |
| 8383 } |
| 8384 |
| 8385 void test_argumentResolution_required_matching() { |
| 8386 Source source = addSource(r''' |
| 8387 class A { |
| 8388 void f() { |
| 8389 g(1, 2, 3); |
| 8390 } |
| 8391 void g(a, b, c) {} |
| 8392 }'''); |
| 8393 _validateArgumentResolution(source, [0, 1, 2]); |
| 8394 } |
| 8395 |
| 8396 void test_argumentResolution_required_tooFew() { |
| 8397 Source source = addSource(r''' |
| 8398 class A { |
| 8399 void f() { |
| 8400 g(1, 2); |
| 8401 } |
| 8402 void g(a, b, c) {} |
| 8403 }'''); |
| 8404 _validateArgumentResolution(source, [0, 1]); |
| 8405 } |
| 8406 |
| 8407 void test_argumentResolution_required_tooMany() { |
| 8408 Source source = addSource(r''' |
| 8409 class A { |
| 8410 void f() { |
| 8411 g(1, 2, 3); |
| 8412 } |
| 8413 void g(a, b) {} |
| 8414 }'''); |
| 8415 _validateArgumentResolution(source, [0, 1, -1]); |
| 8416 } |
| 8417 |
| 8418 void test_argumentResolution_requiredAndNamed_extra() { |
| 8419 Source source = addSource(r''' |
| 8420 class A { |
| 8421 void f() { |
| 8422 g(1, 2, c: 3, d: 4); |
| 8423 } |
| 8424 void g(a, b, {c}) {} |
| 8425 }'''); |
| 8426 _validateArgumentResolution(source, [0, 1, 2, -1]); |
| 8427 } |
| 8428 |
| 8429 void test_argumentResolution_requiredAndNamed_matching() { |
| 8430 Source source = addSource(r''' |
| 8431 class A { |
| 8432 void f() { |
| 8433 g(1, 2, c: 3); |
| 8434 } |
| 8435 void g(a, b, {c}) {} |
| 8436 }'''); |
| 8437 _validateArgumentResolution(source, [0, 1, 2]); |
| 8438 } |
| 8439 |
| 8440 void test_argumentResolution_requiredAndNamed_missing() { |
| 8441 Source source = addSource(r''' |
| 8442 class A { |
| 8443 void f() { |
| 8444 g(1, 2, d: 3); |
| 8445 } |
| 8446 void g(a, b, {c, d}) {} |
| 8447 }'''); |
| 8448 _validateArgumentResolution(source, [0, 1, 3]); |
| 8449 } |
| 8450 |
| 8451 void test_argumentResolution_requiredAndPositional_fewer() { |
| 8452 Source source = addSource(r''' |
| 8453 class A { |
| 8454 void f() { |
| 8455 g(1, 2, 3); |
| 8456 } |
| 8457 void g(a, b, [c, d]) {} |
| 8458 }'''); |
| 8459 _validateArgumentResolution(source, [0, 1, 2]); |
| 8460 } |
| 8461 |
| 8462 void test_argumentResolution_requiredAndPositional_matching() { |
| 8463 Source source = addSource(r''' |
| 8464 class A { |
| 8465 void f() { |
| 8466 g(1, 2, 3, 4); |
| 8467 } |
| 8468 void g(a, b, [c, d]) {} |
| 8469 }'''); |
| 8470 _validateArgumentResolution(source, [0, 1, 2, 3]); |
| 8471 } |
| 8472 |
| 8473 void test_argumentResolution_requiredAndPositional_more() { |
| 8474 Source source = addSource(r''' |
| 8475 class A { |
| 8476 void f() { |
| 8477 g(1, 2, 3, 4); |
| 8478 } |
| 8479 void g(a, b, [c]) {} |
| 8480 }'''); |
| 8481 _validateArgumentResolution(source, [0, 1, 2, -1]); |
| 8482 } |
| 8483 |
| 8484 void test_argumentResolution_setter_propagated() { |
| 8485 Source source = addSource(r''' |
| 8486 main() { |
| 8487 var a = new A(); |
| 8488 a.sss = 0; |
| 8489 } |
| 8490 class A { |
| 8491 set sss(x) {} |
| 8492 }'''); |
| 8493 LibraryElement library = resolve2(source); |
| 8494 CompilationUnitElement unit = library.definingCompilationUnit; |
| 8495 // find "a.sss = 0" |
| 8496 AssignmentExpression assignment; |
| 8497 { |
| 8498 FunctionElement mainElement = unit.functions[0]; |
| 8499 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 8500 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 8501 ExpressionStatement expressionStatement = |
| 8502 statement as ExpressionStatement; |
| 8503 assignment = expressionStatement.expression as AssignmentExpression; |
| 8504 } |
| 8505 // get parameter |
| 8506 Expression rhs = assignment.rightHandSide; |
| 8507 expect(rhs.staticParameterElement, isNull); |
| 8508 ParameterElement parameter = rhs.propagatedParameterElement; |
| 8509 expect(parameter, isNotNull); |
| 8510 expect(parameter.displayName, "x"); |
| 8511 // validate |
| 8512 ClassElement classA = unit.types[0]; |
| 8513 PropertyAccessorElement setter = classA.accessors[0]; |
| 8514 expect(setter.parameters[0], same(parameter)); |
| 8515 } |
| 8516 |
| 8517 void test_argumentResolution_setter_propagated_propertyAccess() { |
| 8518 Source source = addSource(r''' |
| 8519 main() { |
| 8520 var a = new A(); |
| 8521 a.b.sss = 0; |
| 8522 } |
| 8523 class A { |
| 8524 B b = new B(); |
| 8525 } |
| 8526 class B { |
| 8527 set sss(x) {} |
| 8528 }'''); |
| 8529 LibraryElement library = resolve2(source); |
| 8530 CompilationUnitElement unit = library.definingCompilationUnit; |
| 8531 // find "a.b.sss = 0" |
| 8532 AssignmentExpression assignment; |
| 8533 { |
| 8534 FunctionElement mainElement = unit.functions[0]; |
| 8535 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 8536 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 8537 ExpressionStatement expressionStatement = |
| 8538 statement as ExpressionStatement; |
| 8539 assignment = expressionStatement.expression as AssignmentExpression; |
| 8540 } |
| 8541 // get parameter |
| 8542 Expression rhs = assignment.rightHandSide; |
| 8543 expect(rhs.staticParameterElement, isNull); |
| 8544 ParameterElement parameter = rhs.propagatedParameterElement; |
| 8545 expect(parameter, isNotNull); |
| 8546 expect(parameter.displayName, "x"); |
| 8547 // validate |
| 8548 ClassElement classB = unit.types[1]; |
| 8549 PropertyAccessorElement setter = classB.accessors[0]; |
| 8550 expect(setter.parameters[0], same(parameter)); |
| 8551 } |
| 8552 |
| 8553 void test_argumentResolution_setter_static() { |
| 8554 Source source = addSource(r''' |
| 8555 main() { |
| 8556 A a = new A(); |
| 8557 a.sss = 0; |
| 8558 } |
| 8559 class A { |
| 8560 set sss(x) {} |
| 8561 }'''); |
| 8562 LibraryElement library = resolve2(source); |
| 8563 CompilationUnitElement unit = library.definingCompilationUnit; |
| 8564 // find "a.sss = 0" |
| 8565 AssignmentExpression assignment; |
| 8566 { |
| 8567 FunctionElement mainElement = unit.functions[0]; |
| 8568 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 8569 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 8570 ExpressionStatement expressionStatement = |
| 8571 statement as ExpressionStatement; |
| 8572 assignment = expressionStatement.expression as AssignmentExpression; |
| 8573 } |
| 8574 // get parameter |
| 8575 Expression rhs = assignment.rightHandSide; |
| 8576 ParameterElement parameter = rhs.staticParameterElement; |
| 8577 expect(parameter, isNotNull); |
| 8578 expect(parameter.displayName, "x"); |
| 8579 // validate |
| 8580 ClassElement classA = unit.types[0]; |
| 8581 PropertyAccessorElement setter = classA.accessors[0]; |
| 8582 expect(setter.parameters[0], same(parameter)); |
| 8583 } |
| 8584 |
| 8585 void test_argumentResolution_setter_static_propertyAccess() { |
| 8586 Source source = addSource(r''' |
| 8587 main() { |
| 8588 A a = new A(); |
| 8589 a.b.sss = 0; |
| 8590 } |
| 8591 class A { |
| 8592 B b = new B(); |
| 8593 } |
| 8594 class B { |
| 8595 set sss(x) {} |
| 8596 }'''); |
| 8597 LibraryElement library = resolve2(source); |
| 8598 CompilationUnitElement unit = library.definingCompilationUnit; |
| 8599 // find "a.b.sss = 0" |
| 8600 AssignmentExpression assignment; |
| 8601 { |
| 8602 FunctionElement mainElement = unit.functions[0]; |
| 8603 FunctionBody mainBody = mainElement.computeNode().functionExpression.body; |
| 8604 Statement statement = (mainBody as BlockFunctionBody).block.statements[1]; |
| 8605 ExpressionStatement expressionStatement = |
| 8606 statement as ExpressionStatement; |
| 8607 assignment = expressionStatement.expression as AssignmentExpression; |
| 8608 } |
| 8609 // get parameter |
| 8610 Expression rhs = assignment.rightHandSide; |
| 8611 ParameterElement parameter = rhs.staticParameterElement; |
| 8612 expect(parameter, isNotNull); |
| 8613 expect(parameter.displayName, "x"); |
| 8614 // validate |
| 8615 ClassElement classB = unit.types[1]; |
| 8616 PropertyAccessorElement setter = classB.accessors[0]; |
| 8617 expect(setter.parameters[0], same(parameter)); |
| 8618 } |
| 8619 |
| 8620 void test_breakTarget_labeled() { |
| 8621 // Verify that the target of the label is correctly found and is recorded |
| 8622 // as the unlabeled portion of the statement. |
| 8623 String text = r''' |
| 8624 void f() { |
| 8625 loop1: while (true) { |
| 8626 loop2: for (int i = 0; i < 10; i++) { |
| 8627 break loop1; |
| 8628 break loop2; |
| 8629 } |
| 8630 } |
| 8631 } |
| 8632 '''; |
| 8633 CompilationUnit unit = resolveSource(text); |
| 8634 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8635 unit, text, 'while (true)', (n) => n is WhileStatement); |
| 8636 ForStatement forStatement = |
| 8637 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 8638 BreakStatement break1 = EngineTestCase.findNode( |
| 8639 unit, text, 'break loop1', (n) => n is BreakStatement); |
| 8640 BreakStatement break2 = EngineTestCase.findNode( |
| 8641 unit, text, 'break loop2', (n) => n is BreakStatement); |
| 8642 expect(break1.target, same(whileStatement)); |
| 8643 expect(break2.target, same(forStatement)); |
| 8644 } |
| 8645 |
| 8646 void test_breakTarget_unlabeledBreakFromDo() { |
| 8647 String text = r''' |
| 8648 void f() { |
| 8649 do { |
| 8650 break; |
| 8651 } while (true); |
| 8652 } |
| 8653 '''; |
| 8654 CompilationUnit unit = resolveSource(text); |
| 8655 DoStatement doStatement = |
| 8656 EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement); |
| 8657 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8658 unit, text, 'break', (n) => n is BreakStatement); |
| 8659 expect(breakStatement.target, same(doStatement)); |
| 8660 } |
| 8661 |
| 8662 void test_breakTarget_unlabeledBreakFromFor() { |
| 8663 String text = r''' |
| 8664 void f() { |
| 8665 for (int i = 0; i < 10; i++) { |
| 8666 break; |
| 8667 } |
| 8668 } |
| 8669 '''; |
| 8670 CompilationUnit unit = resolveSource(text); |
| 8671 ForStatement forStatement = |
| 8672 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 8673 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8674 unit, text, 'break', (n) => n is BreakStatement); |
| 8675 expect(breakStatement.target, same(forStatement)); |
| 8676 } |
| 8677 |
| 8678 void test_breakTarget_unlabeledBreakFromForEach() { |
| 8679 String text = r''' |
| 8680 void f() { |
| 8681 for (x in []) { |
| 8682 break; |
| 8683 } |
| 8684 } |
| 8685 '''; |
| 8686 CompilationUnit unit = resolveSource(text); |
| 8687 ForEachStatement forStatement = EngineTestCase.findNode( |
| 8688 unit, text, 'for', (n) => n is ForEachStatement); |
| 8689 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8690 unit, text, 'break', (n) => n is BreakStatement); |
| 8691 expect(breakStatement.target, same(forStatement)); |
| 8692 } |
| 8693 |
| 8694 void test_breakTarget_unlabeledBreakFromSwitch() { |
| 8695 String text = r''' |
| 8696 void f() { |
| 8697 while (true) { |
| 8698 switch (0) { |
| 8699 case 0: |
| 8700 break; |
| 8701 } |
| 8702 } |
| 8703 } |
| 8704 '''; |
| 8705 CompilationUnit unit = resolveSource(text); |
| 8706 SwitchStatement switchStatement = EngineTestCase.findNode( |
| 8707 unit, text, 'switch', (n) => n is SwitchStatement); |
| 8708 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8709 unit, text, 'break', (n) => n is BreakStatement); |
| 8710 expect(breakStatement.target, same(switchStatement)); |
| 8711 } |
| 8712 |
| 8713 void test_breakTarget_unlabeledBreakFromWhile() { |
| 8714 String text = r''' |
| 8715 void f() { |
| 8716 while (true) { |
| 8717 break; |
| 8718 } |
| 8719 } |
| 8720 '''; |
| 8721 CompilationUnit unit = resolveSource(text); |
| 8722 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8723 unit, text, 'while', (n) => n is WhileStatement); |
| 8724 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8725 unit, text, 'break', (n) => n is BreakStatement); |
| 8726 expect(breakStatement.target, same(whileStatement)); |
| 8727 } |
| 8728 |
| 8729 void test_breakTarget_unlabeledBreakToOuterFunction() { |
| 8730 // Verify that unlabeled break statements can't resolve to loops in an |
| 8731 // outer function. |
| 8732 String text = r''' |
| 8733 void f() { |
| 8734 while (true) { |
| 8735 void g() { |
| 8736 break; |
| 8737 } |
| 8738 } |
| 8739 } |
| 8740 '''; |
| 8741 CompilationUnit unit = resolveSource(text); |
| 8742 BreakStatement breakStatement = EngineTestCase.findNode( |
| 8743 unit, text, 'break', (n) => n is BreakStatement); |
| 8744 expect(breakStatement.target, isNull); |
| 8745 } |
| 8746 |
| 8747 void test_class_definesCall() { |
| 8748 Source source = addSource(r''' |
| 8749 class A { |
| 8750 int call(int x) { return x; } |
| 8751 } |
| 8752 int f(A a) { |
| 8753 return a(0); |
| 8754 }'''); |
| 8755 computeLibrarySourceErrors(source); |
| 8756 assertNoErrors(source); |
| 8757 verify([source]); |
| 8758 } |
| 8759 |
| 8760 void test_class_extends_implements() { |
| 8761 Source source = addSource(r''' |
| 8762 class A extends B implements C {} |
| 8763 class B {} |
| 8764 class C {}'''); |
| 8765 computeLibrarySourceErrors(source); |
| 8766 assertNoErrors(source); |
| 8767 verify([source]); |
| 8768 } |
| 8769 |
| 8770 void test_commentReference_class() { |
| 8771 Source source = addSource(r''' |
| 8772 f() {} |
| 8773 /** [A] [new A] [A.n] [new A.n] [m] [f] */ |
| 8774 class A { |
| 8775 A() {} |
| 8776 A.n() {} |
| 8777 m() {} |
| 8778 }'''); |
| 8779 computeLibrarySourceErrors(source); |
| 8780 assertNoErrors(source); |
| 8781 verify([source]); |
| 8782 } |
| 8783 |
| 8784 void test_commentReference_parameter() { |
| 8785 Source source = addSource(r''' |
| 8786 class A { |
| 8787 A() {} |
| 8788 A.n() {} |
| 8789 /** [e] [f] */ |
| 8790 m(e, f()) {} |
| 8791 }'''); |
| 8792 computeLibrarySourceErrors(source); |
| 8793 assertNoErrors(source); |
| 8794 verify([source]); |
| 8795 } |
| 8796 |
| 8797 void test_commentReference_singleLine() { |
| 8798 Source source = addSource(r''' |
| 8799 /// [A] |
| 8800 class A {}'''); |
| 8801 computeLibrarySourceErrors(source); |
| 8802 assertNoErrors(source); |
| 8803 verify([source]); |
| 8804 } |
| 8805 |
| 8806 void test_continueTarget_labeled() { |
| 8807 // Verify that the target of the label is correctly found and is recorded |
| 8808 // as the unlabeled portion of the statement. |
| 8809 String text = r''' |
| 8810 void f() { |
| 8811 loop1: while (true) { |
| 8812 loop2: for (int i = 0; i < 10; i++) { |
| 8813 continue loop1; |
| 8814 continue loop2; |
| 8815 } |
| 8816 } |
| 8817 } |
| 8818 '''; |
| 8819 CompilationUnit unit = resolveSource(text); |
| 8820 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8821 unit, text, 'while (true)', (n) => n is WhileStatement); |
| 8822 ForStatement forStatement = |
| 8823 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 8824 ContinueStatement continue1 = EngineTestCase.findNode( |
| 8825 unit, text, 'continue loop1', (n) => n is ContinueStatement); |
| 8826 ContinueStatement continue2 = EngineTestCase.findNode( |
| 8827 unit, text, 'continue loop2', (n) => n is ContinueStatement); |
| 8828 expect(continue1.target, same(whileStatement)); |
| 8829 expect(continue2.target, same(forStatement)); |
| 8830 } |
| 8831 |
| 8832 void test_continueTarget_unlabeledContinueFromDo() { |
| 8833 String text = r''' |
| 8834 void f() { |
| 8835 do { |
| 8836 continue; |
| 8837 } while (true); |
| 8838 } |
| 8839 '''; |
| 8840 CompilationUnit unit = resolveSource(text); |
| 8841 DoStatement doStatement = |
| 8842 EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement); |
| 8843 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8844 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8845 expect(continueStatement.target, same(doStatement)); |
| 8846 } |
| 8847 |
| 8848 void test_continueTarget_unlabeledContinueFromFor() { |
| 8849 String text = r''' |
| 8850 void f() { |
| 8851 for (int i = 0; i < 10; i++) { |
| 8852 continue; |
| 8853 } |
| 8854 } |
| 8855 '''; |
| 8856 CompilationUnit unit = resolveSource(text); |
| 8857 ForStatement forStatement = |
| 8858 EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement); |
| 8859 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8860 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8861 expect(continueStatement.target, same(forStatement)); |
| 8862 } |
| 8863 |
| 8864 void test_continueTarget_unlabeledContinueFromForEach() { |
| 8865 String text = r''' |
| 8866 void f() { |
| 8867 for (x in []) { |
| 8868 continue; |
| 8869 } |
| 8870 } |
| 8871 '''; |
| 8872 CompilationUnit unit = resolveSource(text); |
| 8873 ForEachStatement forStatement = EngineTestCase.findNode( |
| 8874 unit, text, 'for', (n) => n is ForEachStatement); |
| 8875 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8876 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8877 expect(continueStatement.target, same(forStatement)); |
| 8878 } |
| 8879 |
| 8880 void test_continueTarget_unlabeledContinueFromWhile() { |
| 8881 String text = r''' |
| 8882 void f() { |
| 8883 while (true) { |
| 8884 continue; |
| 8885 } |
| 8886 } |
| 8887 '''; |
| 8888 CompilationUnit unit = resolveSource(text); |
| 8889 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8890 unit, text, 'while', (n) => n is WhileStatement); |
| 8891 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8892 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8893 expect(continueStatement.target, same(whileStatement)); |
| 8894 } |
| 8895 |
| 8896 void test_continueTarget_unlabeledContinueSkipsSwitch() { |
| 8897 String text = r''' |
| 8898 void f() { |
| 8899 while (true) { |
| 8900 switch (0) { |
| 8901 case 0: |
| 8902 continue; |
| 8903 } |
| 8904 } |
| 8905 } |
| 8906 '''; |
| 8907 CompilationUnit unit = resolveSource(text); |
| 8908 WhileStatement whileStatement = EngineTestCase.findNode( |
| 8909 unit, text, 'while', (n) => n is WhileStatement); |
| 8910 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8911 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8912 expect(continueStatement.target, same(whileStatement)); |
| 8913 } |
| 8914 |
| 8915 void test_continueTarget_unlabeledContinueToOuterFunction() { |
| 8916 // Verify that unlabeled continue statements can't resolve to loops in an |
| 8917 // outer function. |
| 8918 String text = r''' |
| 8919 void f() { |
| 8920 while (true) { |
| 8921 void g() { |
| 8922 continue; |
| 8923 } |
| 8924 } |
| 8925 } |
| 8926 '''; |
| 8927 CompilationUnit unit = resolveSource(text); |
| 8928 ContinueStatement continueStatement = EngineTestCase.findNode( |
| 8929 unit, text, 'continue', (n) => n is ContinueStatement); |
| 8930 expect(continueStatement.target, isNull); |
| 8931 } |
| 8932 |
| 8933 void test_empty() { |
| 8934 Source source = addSource(""); |
| 8935 computeLibrarySourceErrors(source); |
| 8936 assertNoErrors(source); |
| 8937 verify([source]); |
| 8938 } |
| 8939 |
| 8940 void test_entryPoint_exported() { |
| 8941 addNamedSource( |
| 8942 "/two.dart", |
| 8943 r''' |
| 8944 library two; |
| 8945 main() {}'''); |
| 8946 Source source = addNamedSource( |
| 8947 "/one.dart", |
| 8948 r''' |
| 8949 library one; |
| 8950 export 'two.dart';'''); |
| 8951 LibraryElement library = resolve2(source); |
| 8952 expect(library, isNotNull); |
| 8953 FunctionElement main = library.entryPoint; |
| 8954 expect(main, isNotNull); |
| 8955 expect(main.library, isNot(same(library))); |
| 8956 assertNoErrors(source); |
| 8957 verify([source]); |
| 8958 } |
| 8959 |
| 8960 void test_entryPoint_local() { |
| 8961 Source source = addNamedSource( |
| 8962 "/one.dart", |
| 8963 r''' |
| 8964 library one; |
| 8965 main() {}'''); |
| 8966 LibraryElement library = resolve2(source); |
| 8967 expect(library, isNotNull); |
| 8968 FunctionElement main = library.entryPoint; |
| 8969 expect(main, isNotNull); |
| 8970 expect(main.library, same(library)); |
| 8971 assertNoErrors(source); |
| 8972 verify([source]); |
| 8973 } |
| 8974 |
| 8975 void test_entryPoint_none() { |
| 8976 Source source = addNamedSource("/one.dart", "library one;"); |
| 8977 LibraryElement library = resolve2(source); |
| 8978 expect(library, isNotNull); |
| 8979 expect(library.entryPoint, isNull); |
| 8980 assertNoErrors(source); |
| 8981 verify([source]); |
| 8982 } |
| 8983 |
| 8984 void test_enum_externalLibrary() { |
| 8985 addNamedSource( |
| 8986 "/my_lib.dart", |
| 8987 r''' |
| 8988 library my_lib; |
| 8989 enum EEE {A, B, C}'''); |
| 8990 Source source = addSource(r''' |
| 8991 import 'my_lib.dart'; |
| 8992 main() { |
| 8993 EEE e = null; |
| 8994 }'''); |
| 8995 computeLibrarySourceErrors(source); |
| 8996 assertNoErrors(source); |
| 8997 verify([source]); |
| 8998 } |
| 8999 |
| 9000 void test_extractedMethodAsConstant() { |
| 9001 Source source = addSource(r''' |
| 9002 abstract class Comparable<T> { |
| 9003 int compareTo(T other); |
| 9004 static int compare(Comparable a, Comparable b) => a.compareTo(b); |
| 9005 } |
| 9006 class A { |
| 9007 void sort([compare = Comparable.compare]) {} |
| 9008 }'''); |
| 9009 computeLibrarySourceErrors(source); |
| 9010 assertNoErrors(source); |
| 9011 verify([source]); |
| 9012 } |
| 9013 |
| 9014 void test_fieldFormalParameter() { |
| 9015 Source source = addSource(r''' |
| 9016 class A { |
| 9017 int x; |
| 9018 A(this.x) {} |
| 9019 }'''); |
| 9020 computeLibrarySourceErrors(source); |
| 9021 assertNoErrors(source); |
| 9022 verify([source]); |
| 9023 } |
| 9024 |
| 9025 void test_forEachLoops_nonConflicting() { |
| 9026 Source source = addSource(r''' |
| 9027 f() { |
| 9028 List list = [1,2,3]; |
| 9029 for (int x in list) {} |
| 9030 for (int x in list) {} |
| 9031 }'''); |
| 9032 computeLibrarySourceErrors(source); |
| 9033 assertNoErrors(source); |
| 9034 verify([source]); |
| 9035 } |
| 9036 |
| 9037 void test_forLoops_nonConflicting() { |
| 9038 Source source = addSource(r''' |
| 9039 f() { |
| 9040 for (int i = 0; i < 3; i++) { |
| 9041 } |
| 9042 for (int i = 0; i < 3; i++) { |
| 9043 } |
| 9044 }'''); |
| 9045 computeLibrarySourceErrors(source); |
| 9046 assertNoErrors(source); |
| 9047 verify([source]); |
| 9048 } |
| 9049 |
| 9050 void test_functionTypeAlias() { |
| 9051 Source source = addSource(r''' |
| 9052 typedef bool P(e); |
| 9053 class A { |
| 9054 P p; |
| 9055 m(e) { |
| 9056 if (p(e)) {} |
| 9057 } |
| 9058 }'''); |
| 9059 computeLibrarySourceErrors(source); |
| 9060 assertNoErrors(source); |
| 9061 verify([source]); |
| 9062 } |
| 9063 |
| 9064 void test_getter_and_setter_fromMixins_bare_identifier() { |
| 9065 Source source = addSource(''' |
| 9066 class B {} |
| 9067 class M1 { |
| 9068 get x => null; |
| 9069 set x(value) {} |
| 9070 } |
| 9071 class M2 { |
| 9072 get x => null; |
| 9073 set x(value) {} |
| 9074 } |
| 9075 class C extends B with M1, M2 { |
| 9076 void f() { |
| 9077 x += 1; |
| 9078 } |
| 9079 } |
| 9080 '''); |
| 9081 LibraryElement library = resolve2(source); |
| 9082 assertNoErrors(source); |
| 9083 verify([source]); |
| 9084 // Verify that both the getter and setter for "x" in C.f() refer to the |
| 9085 // accessors defined in M2. |
| 9086 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 9087 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 9088 BlockFunctionBody body = f.body; |
| 9089 ExpressionStatement stmt = body.block.statements[0]; |
| 9090 AssignmentExpression assignment = stmt.expression; |
| 9091 SimpleIdentifier leftHandSide = assignment.leftHandSide; |
| 9092 expect(leftHandSide.staticElement.enclosingElement.name, 'M2'); |
| 9093 expect(leftHandSide.auxiliaryElements.staticElement.enclosingElement.name, |
| 9094 'M2'); |
| 9095 } |
| 9096 |
| 9097 void test_getter_fromMixins_bare_identifier() { |
| 9098 Source source = addSource(''' |
| 9099 class B {} |
| 9100 class M1 { |
| 9101 get x => null; |
| 9102 } |
| 9103 class M2 { |
| 9104 get x => null; |
| 9105 } |
| 9106 class C extends B with M1, M2 { |
| 9107 f() { |
| 9108 return x; |
| 9109 } |
| 9110 } |
| 9111 '''); |
| 9112 LibraryElement library = resolve2(source); |
| 9113 assertNoErrors(source); |
| 9114 verify([source]); |
| 9115 // Verify that the getter for "x" in C.f() refers to the getter defined in |
| 9116 // M2. |
| 9117 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 9118 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 9119 BlockFunctionBody body = f.body; |
| 9120 ReturnStatement stmt = body.block.statements[0]; |
| 9121 SimpleIdentifier x = stmt.expression; |
| 9122 expect(x.staticElement.enclosingElement.name, 'M2'); |
| 9123 } |
| 9124 |
| 9125 void test_getter_fromMixins_property_access() { |
| 9126 Source source = addSource(''' |
| 9127 class B {} |
| 9128 class M1 { |
| 9129 get x => null; |
| 9130 } |
| 9131 class M2 { |
| 9132 get x => null; |
| 9133 } |
| 9134 class C extends B with M1, M2 {} |
| 9135 void main() { |
| 9136 var y = new C().x; |
| 9137 } |
| 9138 '''); |
| 9139 LibraryElement library = resolve2(source); |
| 9140 assertNoErrors(source); |
| 9141 verify([source]); |
| 9142 // Verify that the getter for "x" in "new C().x" refers to the getter |
| 9143 // defined in M2. |
| 9144 FunctionDeclaration main = |
| 9145 library.definingCompilationUnit.functions[0].computeNode(); |
| 9146 BlockFunctionBody body = main.functionExpression.body; |
| 9147 VariableDeclarationStatement stmt = body.block.statements[0]; |
| 9148 PropertyAccess propertyAccess = stmt.variables.variables[0].initializer; |
| 9149 expect( |
| 9150 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 9151 } |
| 9152 |
| 9153 void test_getterAndSetterWithDifferentTypes() { |
| 9154 Source source = addSource(r''' |
| 9155 class A { |
| 9156 int get f => 0; |
| 9157 void set f(String s) {} |
| 9158 } |
| 9159 g (A a) { |
| 9160 a.f = a.f.toString(); |
| 9161 }'''); |
| 9162 computeLibrarySourceErrors(source); |
| 9163 assertErrors( |
| 9164 source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]); |
| 9165 verify([source]); |
| 9166 } |
| 9167 |
| 9168 void test_hasReferenceToSuper() { |
| 9169 Source source = addSource(r''' |
| 9170 class A {} |
| 9171 class B {toString() => super.toString();}'''); |
| 9172 LibraryElement library = resolve2(source); |
| 9173 expect(library, isNotNull); |
| 9174 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9175 expect(unit, isNotNull); |
| 9176 List<ClassElement> classes = unit.types; |
| 9177 expect(classes, hasLength(2)); |
| 9178 expect(classes[0].hasReferenceToSuper, isFalse); |
| 9179 expect(classes[1].hasReferenceToSuper, isTrue); |
| 9180 assertNoErrors(source); |
| 9181 verify([source]); |
| 9182 } |
| 9183 |
| 9184 void test_import_hide() { |
| 9185 addNamedSource( |
| 9186 "/lib1.dart", |
| 9187 r''' |
| 9188 library lib1; |
| 9189 set foo(value) {} |
| 9190 class A {}'''); |
| 9191 addNamedSource( |
| 9192 "/lib2.dart", |
| 9193 r''' |
| 9194 library lib2; |
| 9195 set foo(value) {}'''); |
| 9196 Source source = addNamedSource( |
| 9197 "/lib3.dart", |
| 9198 r''' |
| 9199 import 'lib1.dart' hide foo; |
| 9200 import 'lib2.dart'; |
| 9201 |
| 9202 main() { |
| 9203 foo = 0; |
| 9204 } |
| 9205 A a;'''); |
| 9206 computeLibrarySourceErrors(source); |
| 9207 assertNoErrors(source); |
| 9208 verify([source]); |
| 9209 } |
| 9210 |
| 9211 void test_import_prefix() { |
| 9212 addNamedSource( |
| 9213 "/two.dart", |
| 9214 r''' |
| 9215 library two; |
| 9216 f(int x) { |
| 9217 return x * x; |
| 9218 }'''); |
| 9219 Source source = addNamedSource( |
| 9220 "/one.dart", |
| 9221 r''' |
| 9222 library one; |
| 9223 import 'two.dart' as _two; |
| 9224 main() { |
| 9225 _two.f(0); |
| 9226 }'''); |
| 9227 computeLibrarySourceErrors(source); |
| 9228 assertNoErrors(source); |
| 9229 verify([source]); |
| 9230 } |
| 9231 |
| 9232 void test_import_spaceInUri() { |
| 9233 addNamedSource( |
| 9234 "/sub folder/lib.dart", |
| 9235 r''' |
| 9236 library lib; |
| 9237 foo() {}'''); |
| 9238 Source source = addNamedSource( |
| 9239 "/app.dart", |
| 9240 r''' |
| 9241 import 'sub folder/lib.dart'; |
| 9242 |
| 9243 main() { |
| 9244 foo(); |
| 9245 }'''); |
| 9246 computeLibrarySourceErrors(source); |
| 9247 assertNoErrors(source); |
| 9248 verify([source]); |
| 9249 } |
| 9250 |
| 9251 void test_indexExpression_typeParameters() { |
| 9252 Source source = addSource(r''' |
| 9253 f() { |
| 9254 List<int> a; |
| 9255 a[0]; |
| 9256 List<List<int>> b; |
| 9257 b[0][0]; |
| 9258 List<List<List<int>>> c; |
| 9259 c[0][0][0]; |
| 9260 }'''); |
| 9261 computeLibrarySourceErrors(source); |
| 9262 assertNoErrors(source); |
| 9263 verify([source]); |
| 9264 } |
| 9265 |
| 9266 void test_indexExpression_typeParameters_invalidAssignmentWarning() { |
| 9267 Source source = addSource(r''' |
| 9268 f() { |
| 9269 List<List<int>> b; |
| 9270 b[0][0] = 'hi'; |
| 9271 }'''); |
| 9272 computeLibrarySourceErrors(source); |
| 9273 assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]); |
| 9274 verify([source]); |
| 9275 } |
| 9276 |
| 9277 void test_indirectOperatorThroughCall() { |
| 9278 Source source = addSource(r''' |
| 9279 class A { |
| 9280 B call() { return new B(); } |
| 9281 } |
| 9282 |
| 9283 class B { |
| 9284 int operator [](int i) { return i; } |
| 9285 } |
| 9286 |
| 9287 A f = new A(); |
| 9288 |
| 9289 g(int x) {} |
| 9290 |
| 9291 main() { |
| 9292 g(f()[0]); |
| 9293 }'''); |
| 9294 computeLibrarySourceErrors(source); |
| 9295 assertNoErrors(source); |
| 9296 verify([source]); |
| 9297 } |
| 9298 |
| 9299 void test_invoke_dynamicThroughGetter() { |
| 9300 Source source = addSource(r''' |
| 9301 class A { |
| 9302 List get X => [() => 0]; |
| 9303 m(A a) { |
| 9304 X.last; |
| 9305 } |
| 9306 }'''); |
| 9307 computeLibrarySourceErrors(source); |
| 9308 assertNoErrors(source); |
| 9309 verify([source]); |
| 9310 } |
| 9311 |
| 9312 void test_isValidMixin_badSuperclass() { |
| 9313 Source source = addSource(r''' |
| 9314 class A extends B {} |
| 9315 class B {}'''); |
| 9316 LibraryElement library = resolve2(source); |
| 9317 expect(library, isNotNull); |
| 9318 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9319 expect(unit, isNotNull); |
| 9320 List<ClassElement> classes = unit.types; |
| 9321 expect(classes, hasLength(2)); |
| 9322 expect(classes[0].isValidMixin, isFalse); |
| 9323 assertNoErrors(source); |
| 9324 verify([source]); |
| 9325 } |
| 9326 |
| 9327 void test_isValidMixin_constructor() { |
| 9328 Source source = addSource(r''' |
| 9329 class A { |
| 9330 A() {} |
| 9331 }'''); |
| 9332 LibraryElement library = resolve2(source); |
| 9333 expect(library, isNotNull); |
| 9334 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9335 expect(unit, isNotNull); |
| 9336 List<ClassElement> classes = unit.types; |
| 9337 expect(classes, hasLength(1)); |
| 9338 expect(classes[0].isValidMixin, isFalse); |
| 9339 assertNoErrors(source); |
| 9340 verify([source]); |
| 9341 } |
| 9342 |
| 9343 void test_isValidMixin_super() { |
| 9344 Source source = addSource(r''' |
| 9345 class A { |
| 9346 toString() { |
| 9347 return super.toString(); |
| 9348 } |
| 9349 }'''); |
| 9350 LibraryElement library = resolve2(source); |
| 9351 expect(library, isNotNull); |
| 9352 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9353 expect(unit, isNotNull); |
| 9354 List<ClassElement> classes = unit.types; |
| 9355 expect(classes, hasLength(1)); |
| 9356 expect(classes[0].isValidMixin, isFalse); |
| 9357 assertNoErrors(source); |
| 9358 verify([source]); |
| 9359 } |
| 9360 |
| 9361 void test_isValidMixin_valid() { |
| 9362 Source source = addSource("class A {}"); |
| 9363 LibraryElement library = resolve2(source); |
| 9364 expect(library, isNotNull); |
| 9365 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9366 expect(unit, isNotNull); |
| 9367 List<ClassElement> classes = unit.types; |
| 9368 expect(classes, hasLength(1)); |
| 9369 expect(classes[0].isValidMixin, isTrue); |
| 9370 assertNoErrors(source); |
| 9371 verify([source]); |
| 9372 } |
| 9373 |
| 9374 void test_labels_switch() { |
| 9375 Source source = addSource(r''' |
| 9376 void doSwitch(int target) { |
| 9377 switch (target) { |
| 9378 l0: case 0: |
| 9379 continue l1; |
| 9380 l1: case 1: |
| 9381 continue l0; |
| 9382 default: |
| 9383 continue l1; |
| 9384 } |
| 9385 }'''); |
| 9386 LibraryElement library = resolve2(source); |
| 9387 expect(library, isNotNull); |
| 9388 assertNoErrors(source); |
| 9389 verify([source]); |
| 9390 } |
| 9391 |
| 9392 void test_localVariable_types_invoked() { |
| 9393 Source source = addSource(r''' |
| 9394 const A = null; |
| 9395 main() { |
| 9396 var myVar = (int p) => 'foo'; |
| 9397 myVar(42); |
| 9398 }'''); |
| 9399 LibraryElement library = resolve2(source); |
| 9400 expect(library, isNotNull); |
| 9401 CompilationUnit unit = |
| 9402 analysisContext.resolveCompilationUnit(source, library); |
| 9403 expect(unit, isNotNull); |
| 9404 List<bool> found = [false]; |
| 9405 List<CaughtException> thrownException = new List<CaughtException>(1); |
| 9406 unit.accept(new _SimpleResolverTest_localVariable_types_invoked( |
| 9407 this, found, thrownException)); |
| 9408 if (thrownException[0] != null) { |
| 9409 throw new AnalysisException( |
| 9410 "Exception", new CaughtException(thrownException[0], null)); |
| 9411 } |
| 9412 expect(found[0], isTrue); |
| 9413 } |
| 9414 |
| 9415 void test_metadata_class() { |
| 9416 Source source = addSource(r''' |
| 9417 const A = null; |
| 9418 @A class C<A> {}'''); |
| 9419 LibraryElement library = resolve2(source); |
| 9420 expect(library, isNotNull); |
| 9421 CompilationUnitElement unitElement = library.definingCompilationUnit; |
| 9422 expect(unitElement, isNotNull); |
| 9423 List<ClassElement> classes = unitElement.types; |
| 9424 expect(classes, hasLength(1)); |
| 9425 List<ElementAnnotation> annotations = classes[0].metadata; |
| 9426 expect(annotations, hasLength(1)); |
| 9427 assertNoErrors(source); |
| 9428 verify([source]); |
| 9429 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 9430 NodeList<CompilationUnitMember> declarations = unit.declarations; |
| 9431 expect(declarations, hasLength(2)); |
| 9432 Element expectedElement = (declarations[0] as TopLevelVariableDeclaration) |
| 9433 .variables |
| 9434 .variables[0].name.staticElement; |
| 9435 EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement, |
| 9436 PropertyInducingElement, expectedElement); |
| 9437 expectedElement = (expectedElement as PropertyInducingElement).getter; |
| 9438 Element actualElement = |
| 9439 (declarations[1] as ClassDeclaration).metadata[0].name.staticElement; |
| 9440 expect(actualElement, same(expectedElement)); |
| 9441 } |
| 9442 |
| 9443 void test_metadata_field() { |
| 9444 Source source = addSource(r''' |
| 9445 const A = null; |
| 9446 class C { |
| 9447 @A int f; |
| 9448 }'''); |
| 9449 LibraryElement library = resolve2(source); |
| 9450 expect(library, isNotNull); |
| 9451 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9452 expect(unit, isNotNull); |
| 9453 List<ClassElement> classes = unit.types; |
| 9454 expect(classes, hasLength(1)); |
| 9455 FieldElement field = classes[0].fields[0]; |
| 9456 List<ElementAnnotation> annotations = field.metadata; |
| 9457 expect(annotations, hasLength(1)); |
| 9458 assertNoErrors(source); |
| 9459 verify([source]); |
| 9460 } |
| 9461 |
| 9462 void test_metadata_fieldFormalParameter() { |
| 9463 Source source = addSource(r''' |
| 9464 const A = null; |
| 9465 class C { |
| 9466 int f; |
| 9467 C(@A this.f); |
| 9468 }'''); |
| 9469 LibraryElement library = resolve2(source); |
| 9470 expect(library, isNotNull); |
| 9471 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9472 expect(unit, isNotNull); |
| 9473 List<ClassElement> classes = unit.types; |
| 9474 expect(classes, hasLength(1)); |
| 9475 List<ConstructorElement> constructors = classes[0].constructors; |
| 9476 expect(constructors, hasLength(1)); |
| 9477 List<ParameterElement> parameters = constructors[0].parameters; |
| 9478 expect(parameters, hasLength(1)); |
| 9479 List<ElementAnnotation> annotations = parameters[0].metadata; |
| 9480 expect(annotations, hasLength(1)); |
| 9481 assertNoErrors(source); |
| 9482 verify([source]); |
| 9483 } |
| 9484 |
| 9485 void test_metadata_function() { |
| 9486 Source source = addSource(r''' |
| 9487 const A = null; |
| 9488 @A f() {}'''); |
| 9489 LibraryElement library = resolve2(source); |
| 9490 expect(library, isNotNull); |
| 9491 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9492 expect(unit, isNotNull); |
| 9493 List<FunctionElement> functions = unit.functions; |
| 9494 expect(functions, hasLength(1)); |
| 9495 List<ElementAnnotation> annotations = functions[0].metadata; |
| 9496 expect(annotations, hasLength(1)); |
| 9497 assertNoErrors(source); |
| 9498 verify([source]); |
| 9499 } |
| 9500 |
| 9501 void test_metadata_functionTypedParameter() { |
| 9502 Source source = addSource(r''' |
| 9503 const A = null; |
| 9504 f(@A int p(int x)) {}'''); |
| 9505 LibraryElement library = resolve2(source); |
| 9506 expect(library, isNotNull); |
| 9507 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9508 expect(unit, isNotNull); |
| 9509 List<FunctionElement> functions = unit.functions; |
| 9510 expect(functions, hasLength(1)); |
| 9511 List<ParameterElement> parameters = functions[0].parameters; |
| 9512 expect(parameters, hasLength(1)); |
| 9513 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 9514 expect(annotations1, hasLength(1)); |
| 9515 assertNoErrors(source); |
| 9516 verify([source]); |
| 9517 } |
| 9518 |
| 9519 void test_metadata_libraryDirective() { |
| 9520 Source source = addSource(r''' |
| 9521 @A library lib; |
| 9522 const A = null;'''); |
| 9523 LibraryElement library = resolve2(source); |
| 9524 expect(library, isNotNull); |
| 9525 List<ElementAnnotation> annotations = library.metadata; |
| 9526 expect(annotations, hasLength(1)); |
| 9527 assertNoErrors(source); |
| 9528 verify([source]); |
| 9529 } |
| 9530 |
| 9531 void test_metadata_method() { |
| 9532 Source source = addSource(r''' |
| 9533 const A = null; |
| 9534 class C { |
| 9535 @A void m() {} |
| 9536 }'''); |
| 9537 LibraryElement library = resolve2(source); |
| 9538 expect(library, isNotNull); |
| 9539 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9540 expect(unit, isNotNull); |
| 9541 List<ClassElement> classes = unit.types; |
| 9542 expect(classes, hasLength(1)); |
| 9543 MethodElement method = classes[0].methods[0]; |
| 9544 List<ElementAnnotation> annotations = method.metadata; |
| 9545 expect(annotations, hasLength(1)); |
| 9546 assertNoErrors(source); |
| 9547 verify([source]); |
| 9548 } |
| 9549 |
| 9550 void test_metadata_namedParameter() { |
| 9551 Source source = addSource(r''' |
| 9552 const A = null; |
| 9553 f({@A int p : 0}) {}'''); |
| 9554 LibraryElement library = resolve2(source); |
| 9555 expect(library, isNotNull); |
| 9556 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9557 expect(unit, isNotNull); |
| 9558 List<FunctionElement> functions = unit.functions; |
| 9559 expect(functions, hasLength(1)); |
| 9560 List<ParameterElement> parameters = functions[0].parameters; |
| 9561 expect(parameters, hasLength(1)); |
| 9562 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 9563 expect(annotations1, hasLength(1)); |
| 9564 assertNoErrors(source); |
| 9565 verify([source]); |
| 9566 } |
| 9567 |
| 9568 void test_metadata_positionalParameter() { |
| 9569 Source source = addSource(r''' |
| 9570 const A = null; |
| 9571 f([@A int p = 0]) {}'''); |
| 9572 LibraryElement library = resolve2(source); |
| 9573 expect(library, isNotNull); |
| 9574 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9575 expect(unit, isNotNull); |
| 9576 List<FunctionElement> functions = unit.functions; |
| 9577 expect(functions, hasLength(1)); |
| 9578 List<ParameterElement> parameters = functions[0].parameters; |
| 9579 expect(parameters, hasLength(1)); |
| 9580 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 9581 expect(annotations1, hasLength(1)); |
| 9582 assertNoErrors(source); |
| 9583 verify([source]); |
| 9584 } |
| 9585 |
| 9586 void test_metadata_simpleParameter() { |
| 9587 Source source = addSource(r''' |
| 9588 const A = null; |
| 9589 f(@A p1, @A int p2) {}'''); |
| 9590 LibraryElement library = resolve2(source); |
| 9591 expect(library, isNotNull); |
| 9592 CompilationUnitElement unit = library.definingCompilationUnit; |
| 9593 expect(unit, isNotNull); |
| 9594 List<FunctionElement> functions = unit.functions; |
| 9595 expect(functions, hasLength(1)); |
| 9596 List<ParameterElement> parameters = functions[0].parameters; |
| 9597 expect(parameters, hasLength(2)); |
| 9598 List<ElementAnnotation> annotations1 = parameters[0].metadata; |
| 9599 expect(annotations1, hasLength(1)); |
| 9600 List<ElementAnnotation> annotations2 = parameters[1].metadata; |
| 9601 expect(annotations2, hasLength(1)); |
| 9602 assertNoErrors(source); |
| 9603 verify([source]); |
| 9604 } |
| 9605 |
| 9606 void test_metadata_typedef() { |
| 9607 Source source = addSource(r''' |
| 9608 const A = null; |
| 9609 @A typedef F<A>();'''); |
| 9610 LibraryElement library = resolve2(source); |
| 9611 expect(library, isNotNull); |
| 9612 CompilationUnitElement unitElement = library.definingCompilationUnit; |
| 9613 expect(unitElement, isNotNull); |
| 9614 List<FunctionTypeAliasElement> aliases = unitElement.functionTypeAliases; |
| 9615 expect(aliases, hasLength(1)); |
| 9616 List<ElementAnnotation> annotations = aliases[0].metadata; |
| 9617 expect(annotations, hasLength(1)); |
| 9618 assertNoErrors(source); |
| 9619 verify([source]); |
| 9620 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 9621 NodeList<CompilationUnitMember> declarations = unit.declarations; |
| 9622 expect(declarations, hasLength(2)); |
| 9623 Element expectedElement = (declarations[0] as TopLevelVariableDeclaration) |
| 9624 .variables |
| 9625 .variables[0].name.staticElement; |
| 9626 EngineTestCase.assertInstanceOf((obj) => obj is PropertyInducingElement, |
| 9627 PropertyInducingElement, expectedElement); |
| 9628 expectedElement = (expectedElement as PropertyInducingElement).getter; |
| 9629 Element actualElement = |
| 9630 (declarations[1] as FunctionTypeAlias).metadata[0].name.staticElement; |
| 9631 expect(actualElement, same(expectedElement)); |
| 9632 } |
| 9633 |
| 9634 void test_method_fromMixin() { |
| 9635 Source source = addSource(r''' |
| 9636 class B { |
| 9637 bar() => 1; |
| 9638 } |
| 9639 class A { |
| 9640 foo() => 2; |
| 9641 } |
| 9642 |
| 9643 class C extends B with A { |
| 9644 bar() => super.bar(); |
| 9645 foo() => super.foo(); |
| 9646 }'''); |
| 9647 computeLibrarySourceErrors(source); |
| 9648 assertNoErrors(source); |
| 9649 verify([source]); |
| 9650 } |
| 9651 |
| 9652 void test_method_fromMixins() { |
| 9653 Source source = addSource(''' |
| 9654 class B {} |
| 9655 class M1 { |
| 9656 void f() {} |
| 9657 } |
| 9658 class M2 { |
| 9659 void f() {} |
| 9660 } |
| 9661 class C extends B with M1, M2 {} |
| 9662 void main() { |
| 9663 new C().f(); |
| 9664 } |
| 9665 '''); |
| 9666 LibraryElement library = resolve2(source); |
| 9667 assertNoErrors(source); |
| 9668 verify([source]); |
| 9669 // Verify that the "f" in "new C().f()" refers to the "f" defined in M2. |
| 9670 FunctionDeclaration main = |
| 9671 library.definingCompilationUnit.functions[0].computeNode(); |
| 9672 BlockFunctionBody body = main.functionExpression.body; |
| 9673 ExpressionStatement stmt = body.block.statements[0]; |
| 9674 MethodInvocation expr = stmt.expression; |
| 9675 expect(expr.methodName.staticElement.enclosingElement.name, 'M2'); |
| 9676 } |
| 9677 |
| 9678 void test_method_fromMixins_bare_identifier() { |
| 9679 Source source = addSource(''' |
| 9680 class B {} |
| 9681 class M1 { |
| 9682 void f() {} |
| 9683 } |
| 9684 class M2 { |
| 9685 void f() {} |
| 9686 } |
| 9687 class C extends B with M1, M2 { |
| 9688 void g() { |
| 9689 f(); |
| 9690 } |
| 9691 } |
| 9692 '''); |
| 9693 LibraryElement library = resolve2(source); |
| 9694 assertNoErrors(source); |
| 9695 verify([source]); |
| 9696 // Verify that the call to f() in C.g() refers to the method defined in M2. |
| 9697 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 9698 MethodDeclaration g = classC.getMethod('g').computeNode(); |
| 9699 BlockFunctionBody body = g.body; |
| 9700 ExpressionStatement stmt = body.block.statements[0]; |
| 9701 MethodInvocation invocation = stmt.expression; |
| 9702 SimpleIdentifier methodName = invocation.methodName; |
| 9703 expect(methodName.staticElement.enclosingElement.name, 'M2'); |
| 9704 } |
| 9705 |
| 9706 void test_method_fromMixins_invked_from_outside_class() { |
| 9707 Source source = addSource(''' |
| 9708 class B {} |
| 9709 class M1 { |
| 9710 void f() {} |
| 9711 } |
| 9712 class M2 { |
| 9713 void f() {} |
| 9714 } |
| 9715 class C extends B with M1, M2 {} |
| 9716 void main() { |
| 9717 new C().f(); |
| 9718 } |
| 9719 '''); |
| 9720 LibraryElement library = resolve2(source); |
| 9721 assertNoErrors(source); |
| 9722 verify([source]); |
| 9723 // Verify that the call to f() in "new C().f()" refers to the method |
| 9724 // defined in M2. |
| 9725 FunctionDeclaration main = |
| 9726 library.definingCompilationUnit.functions[0].computeNode(); |
| 9727 BlockFunctionBody body = main.functionExpression.body; |
| 9728 ExpressionStatement stmt = body.block.statements[0]; |
| 9729 MethodInvocation invocation = stmt.expression; |
| 9730 expect(invocation.methodName.staticElement.enclosingElement.name, 'M2'); |
| 9731 } |
| 9732 |
| 9733 void test_method_fromSuperclassMixin() { |
| 9734 Source source = addSource(r''' |
| 9735 class A { |
| 9736 void m1() {} |
| 9737 } |
| 9738 class B extends Object with A { |
| 9739 } |
| 9740 class C extends B { |
| 9741 } |
| 9742 f(C c) { |
| 9743 c.m1(); |
| 9744 }'''); |
| 9745 computeLibrarySourceErrors(source); |
| 9746 assertNoErrors(source); |
| 9747 verify([source]); |
| 9748 } |
| 9749 |
| 9750 void test_methodCascades() { |
| 9751 Source source = addSource(r''' |
| 9752 class A { |
| 9753 void m1() {} |
| 9754 void m2() {} |
| 9755 void m() { |
| 9756 A a = new A(); |
| 9757 a..m1() |
| 9758 ..m2(); |
| 9759 } |
| 9760 }'''); |
| 9761 computeLibrarySourceErrors(source); |
| 9762 assertNoErrors(source); |
| 9763 verify([source]); |
| 9764 } |
| 9765 |
| 9766 void test_methodCascades_withSetter() { |
| 9767 Source source = addSource(r''' |
| 9768 class A { |
| 9769 String name; |
| 9770 void m1() {} |
| 9771 void m2() {} |
| 9772 void m() { |
| 9773 A a = new A(); |
| 9774 a..m1() |
| 9775 ..name = 'name' |
| 9776 ..m2(); |
| 9777 } |
| 9778 }'''); |
| 9779 computeLibrarySourceErrors(source); |
| 9780 // failing with error code: INVOCATION_OF_NON_FUNCTION |
| 9781 assertNoErrors(source); |
| 9782 verify([source]); |
| 9783 } |
| 9784 |
| 9785 void test_resolveAgainstNull() { |
| 9786 Source source = addSource(r''' |
| 9787 f(var p) { |
| 9788 return null == p; |
| 9789 }'''); |
| 9790 computeLibrarySourceErrors(source); |
| 9791 assertNoErrors(source); |
| 9792 } |
| 9793 |
| 9794 void test_setter_fromMixins_bare_identifier() { |
| 9795 Source source = addSource(''' |
| 9796 class B {} |
| 9797 class M1 { |
| 9798 set x(value) {} |
| 9799 } |
| 9800 class M2 { |
| 9801 set x(value) {} |
| 9802 } |
| 9803 class C extends B with M1, M2 { |
| 9804 void f() { |
| 9805 x = 1; |
| 9806 } |
| 9807 } |
| 9808 '''); |
| 9809 LibraryElement library = resolve2(source); |
| 9810 assertNoErrors(source); |
| 9811 verify([source]); |
| 9812 // Verify that the setter for "x" in C.f() refers to the setter defined in |
| 9813 // M2. |
| 9814 ClassElement classC = library.definingCompilationUnit.types[3]; |
| 9815 MethodDeclaration f = classC.getMethod('f').computeNode(); |
| 9816 BlockFunctionBody body = f.body; |
| 9817 ExpressionStatement stmt = body.block.statements[0]; |
| 9818 AssignmentExpression assignment = stmt.expression; |
| 9819 SimpleIdentifier leftHandSide = assignment.leftHandSide; |
| 9820 expect(leftHandSide.staticElement.enclosingElement.name, 'M2'); |
| 9821 } |
| 9822 |
| 9823 void test_setter_fromMixins_property_access() { |
| 9824 Source source = addSource(''' |
| 9825 class B {} |
| 9826 class M1 { |
| 9827 set x(value) {} |
| 9828 } |
| 9829 class M2 { |
| 9830 set x(value) {} |
| 9831 } |
| 9832 class C extends B with M1, M2 {} |
| 9833 void main() { |
| 9834 new C().x = 1; |
| 9835 } |
| 9836 '''); |
| 9837 LibraryElement library = resolve2(source); |
| 9838 assertNoErrors(source); |
| 9839 verify([source]); |
| 9840 // Verify that the setter for "x" in "new C().x" refers to the setter |
| 9841 // defined in M2. |
| 9842 FunctionDeclaration main = |
| 9843 library.definingCompilationUnit.functions[0].computeNode(); |
| 9844 BlockFunctionBody body = main.functionExpression.body; |
| 9845 ExpressionStatement stmt = body.block.statements[0]; |
| 9846 AssignmentExpression assignment = stmt.expression; |
| 9847 PropertyAccess propertyAccess = assignment.leftHandSide; |
| 9848 expect( |
| 9849 propertyAccess.propertyName.staticElement.enclosingElement.name, 'M2'); |
| 9850 } |
| 9851 |
| 9852 void test_setter_inherited() { |
| 9853 Source source = addSource(r''' |
| 9854 class A { |
| 9855 int get x => 0; |
| 9856 set x(int p) {} |
| 9857 } |
| 9858 class B extends A { |
| 9859 int get x => super.x == null ? 0 : super.x; |
| 9860 int f() => x = 1; |
| 9861 }'''); |
| 9862 computeLibrarySourceErrors(source); |
| 9863 assertNoErrors(source); |
| 9864 verify([source]); |
| 9865 } |
| 9866 |
| 9867 void test_setter_static() { |
| 9868 Source source = addSource(r''' |
| 9869 set s(x) { |
| 9870 } |
| 9871 |
| 9872 main() { |
| 9873 s = 123; |
| 9874 }'''); |
| 9875 computeLibrarySourceErrors(source); |
| 9876 assertNoErrors(source); |
| 9877 verify([source]); |
| 9878 } |
| 9879 |
| 9880 /** |
| 9881 * Resolve the given source and verify that the arguments in a specific method
invocation were |
| 9882 * correctly resolved. |
| 9883 * |
| 9884 * The source is expected to be source for a compilation unit, the first decla
ration is expected |
| 9885 * to be a class, the first member of which is expected to be a method with a
block body, and the |
| 9886 * first statement in the body is expected to be an expression statement whose
expression is a |
| 9887 * method invocation. It is the arguments to that method invocation that are t
ested. The method |
| 9888 * invocation can contain errors. |
| 9889 * |
| 9890 * The arguments were resolved correctly if the number of expressions in the l
ist matches the |
| 9891 * length of the array of indices and if, for each index in the array of indic
es, the parameter to |
| 9892 * which the argument expression was resolved is the parameter in the invoked
method's list of |
| 9893 * parameters at that index. Arguments that should not be resolved to a parame
ter because of an |
| 9894 * error can be denoted by including a negative index in the array of indices. |
| 9895 * |
| 9896 * @param source the source to be resolved |
| 9897 * @param indices the array of indices used to associate arguments with parame
ters |
| 9898 * @throws Exception if the source could not be resolved or if the structure o
f the source is not |
| 9899 * valid |
| 9900 */ |
| 9901 void _validateArgumentResolution(Source source, List<int> indices) { |
| 9902 LibraryElement library = resolve2(source); |
| 9903 expect(library, isNotNull); |
| 9904 ClassElement classElement = library.definingCompilationUnit.types[0]; |
| 9905 List<ParameterElement> parameters = classElement.methods[1].parameters; |
| 9906 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 9907 expect(unit, isNotNull); |
| 9908 ClassDeclaration classDeclaration = |
| 9909 unit.declarations[0] as ClassDeclaration; |
| 9910 MethodDeclaration methodDeclaration = |
| 9911 classDeclaration.members[0] as MethodDeclaration; |
| 9912 Block block = (methodDeclaration.body as BlockFunctionBody).block; |
| 9913 ExpressionStatement statement = block.statements[0] as ExpressionStatement; |
| 9914 MethodInvocation invocation = statement.expression as MethodInvocation; |
| 9915 NodeList<Expression> arguments = invocation.argumentList.arguments; |
| 9916 int argumentCount = arguments.length; |
| 9917 expect(argumentCount, indices.length); |
| 9918 for (int i = 0; i < argumentCount; i++) { |
| 9919 Expression argument = arguments[i]; |
| 9920 ParameterElement element = argument.staticParameterElement; |
| 9921 int index = indices[i]; |
| 9922 if (index < 0) { |
| 9923 expect(element, isNull); |
| 9924 } else { |
| 9925 expect(element, same(parameters[index])); |
| 9926 } |
| 9927 } |
| 9928 } |
| 9929 } |
| 9930 |
| 9931 class SourceContainer_ChangeSetTest_test_toString implements SourceContainer { |
| 9932 @override |
| 9933 bool contains(Source source) => false; |
| 9934 } |
| 9935 |
| 9936 /** |
| 9937 * Like [StaticTypeAnalyzerTest], but as end-to-end tests. |
| 9938 */ |
| 9939 @reflectiveTest |
| 9940 class StaticTypeAnalyzer2Test extends ResolverTestCase { |
| 9941 String testCode; |
| 9942 Source testSource; |
| 9943 CompilationUnit testUnit; |
| 9944 |
| 9945 void test_FunctionExpressionInvocation_block() { |
| 9946 String code = r''' |
| 9947 main() { |
| 9948 var foo = (() { return 1; })(); |
| 9949 } |
| 9950 '''; |
| 9951 _resolveTestUnit(code); |
| 9952 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 9953 VariableDeclaration declaration = |
| 9954 identifier.getAncestor((node) => node is VariableDeclaration); |
| 9955 expect(declaration.initializer.staticType.isDynamic, isTrue); |
| 9956 expect(declaration.initializer.propagatedType, isNull); |
| 9957 } |
| 9958 |
| 9959 void test_FunctionExpressionInvocation_curried() { |
| 9960 String code = r''' |
| 9961 typedef int F(); |
| 9962 F f() => null; |
| 9963 main() { |
| 9964 var foo = f()(); |
| 9965 } |
| 9966 '''; |
| 9967 _resolveTestUnit(code); |
| 9968 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 9969 VariableDeclaration declaration = |
| 9970 identifier.getAncestor((node) => node is VariableDeclaration); |
| 9971 expect(declaration.initializer.staticType.name, 'int'); |
| 9972 expect(declaration.initializer.propagatedType, isNull); |
| 9973 } |
| 9974 |
| 9975 void test_FunctionExpressionInvocation_expression() { |
| 9976 String code = r''' |
| 9977 main() { |
| 9978 var foo = (() => 1)(); |
| 9979 } |
| 9980 '''; |
| 9981 _resolveTestUnit(code); |
| 9982 SimpleIdentifier identifier = _findIdentifier('foo'); |
| 9983 VariableDeclaration declaration = |
| 9984 identifier.getAncestor((node) => node is VariableDeclaration); |
| 9985 expect(declaration.initializer.staticType.name, 'int'); |
| 9986 expect(declaration.initializer.propagatedType, isNull); |
| 9987 } |
| 9988 |
| 9989 void test_MethodInvocation_nameType_localVariable() { |
| 9990 String code = r""" |
| 9991 typedef Foo(); |
| 9992 main() { |
| 9993 Foo foo; |
| 9994 foo(); |
| 9995 } |
| 9996 """; |
| 9997 _resolveTestUnit(code); |
| 9998 // "foo" should be resolved to the "Foo" type |
| 9999 SimpleIdentifier identifier = _findIdentifier("foo();"); |
| 10000 DartType type = identifier.staticType; |
| 10001 expect(type, new isInstanceOf<FunctionType>()); |
| 10002 } |
| 10003 |
| 10004 void test_MethodInvocation_nameType_parameter_FunctionTypeAlias() { |
| 10005 String code = r""" |
| 10006 typedef Foo(); |
| 10007 main(Foo foo) { |
| 10008 foo(); |
| 10009 } |
| 10010 """; |
| 10011 _resolveTestUnit(code); |
| 10012 // "foo" should be resolved to the "Foo" type |
| 10013 SimpleIdentifier identifier = _findIdentifier("foo();"); |
| 10014 DartType type = identifier.staticType; |
| 10015 expect(type, new isInstanceOf<FunctionType>()); |
| 10016 } |
| 10017 |
| 10018 void test_MethodInvocation_nameType_parameter_propagatedType() { |
| 10019 String code = r""" |
| 10020 typedef Foo(); |
| 10021 main(p) { |
| 10022 if (p is Foo) { |
| 10023 p(); |
| 10024 } |
| 10025 } |
| 10026 """; |
| 10027 _resolveTestUnit(code); |
| 10028 SimpleIdentifier identifier = _findIdentifier("p()"); |
| 10029 expect(identifier.staticType, DynamicTypeImpl.instance); |
| 10030 { |
| 10031 FunctionType type = identifier.propagatedType; |
| 10032 expect(type, isNotNull); |
| 10033 expect(type.name, 'Foo'); |
| 10034 } |
| 10035 } |
| 10036 |
| 10037 SimpleIdentifier _findIdentifier(String search) { |
| 10038 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 10039 testUnit, testCode, search, (node) => node is SimpleIdentifier); |
| 10040 return identifier; |
| 10041 } |
| 10042 |
| 10043 void _resolveTestUnit(String code) { |
| 10044 testCode = code; |
| 10045 testSource = addSource(testCode); |
| 10046 LibraryElement library = resolve2(testSource); |
| 10047 assertNoErrors(testSource); |
| 10048 verify([testSource]); |
| 10049 testUnit = resolveCompilationUnit(testSource, library); |
| 10050 } |
| 10051 } |
| 10052 |
| 10053 @reflectiveTest |
| 10054 class StaticTypeAnalyzerTest extends EngineTestCase { |
| 10055 /** |
| 10056 * The error listener to which errors will be reported. |
| 10057 */ |
| 10058 GatheringErrorListener _listener; |
| 10059 |
| 10060 /** |
| 10061 * The resolver visitor used to create the analyzer. |
| 10062 */ |
| 10063 ResolverVisitor _visitor; |
| 10064 |
| 10065 /** |
| 10066 * The analyzer being used to analyze the test cases. |
| 10067 */ |
| 10068 StaticTypeAnalyzer _analyzer; |
| 10069 |
| 10070 /** |
| 10071 * The type provider used to access the types. |
| 10072 */ |
| 10073 TestTypeProvider _typeProvider; |
| 10074 |
| 10075 void fail_visitFunctionExpressionInvocation() { |
| 10076 fail("Not yet tested"); |
| 10077 _listener.assertNoErrors(); |
| 10078 } |
| 10079 |
| 10080 void fail_visitMethodInvocation() { |
| 10081 fail("Not yet tested"); |
| 10082 _listener.assertNoErrors(); |
| 10083 } |
| 10084 |
| 10085 void fail_visitSimpleIdentifier() { |
| 10086 fail("Not yet tested"); |
| 10087 _listener.assertNoErrors(); |
| 10088 } |
| 10089 |
| 10090 @override |
| 10091 void setUp() { |
| 10092 _listener = new GatheringErrorListener(); |
| 10093 _typeProvider = new TestTypeProvider(); |
| 10094 _analyzer = _createAnalyzer(); |
| 10095 } |
| 10096 |
| 10097 void test_flatten_derived() { |
| 10098 // class Derived<T> extends Future<T> { ... } |
| 10099 ClassElementImpl derivedClass = |
| 10100 ElementFactory.classElement2('Derived', ['T']); |
| 10101 derivedClass.supertype = _typeProvider.futureType |
| 10102 .substitute4([derivedClass.typeParameters[0].type]); |
| 10103 InterfaceType intType = _typeProvider.intType; |
| 10104 DartType dynamicType = _typeProvider.dynamicType; |
| 10105 InterfaceType derivedIntType = derivedClass.type.substitute4([intType]); |
| 10106 // flatten(Derived) = dynamic |
| 10107 InterfaceType derivedDynamicType = |
| 10108 derivedClass.type.substitute4([dynamicType]); |
| 10109 expect(_flatten(derivedDynamicType), dynamicType); |
| 10110 // flatten(Derived<int>) = int |
| 10111 expect(_flatten(derivedIntType), intType); |
| 10112 // flatten(Derived<Derived>) = Derived |
| 10113 expect(_flatten(derivedClass.type.substitute4([derivedDynamicType])), |
| 10114 derivedDynamicType); |
| 10115 // flatten(Derived<Derived<int>>) = Derived<int> |
| 10116 expect(_flatten(derivedClass.type.substitute4([derivedIntType])), |
| 10117 derivedIntType); |
| 10118 } |
| 10119 |
| 10120 void test_flatten_inhibit_recursion() { |
| 10121 // class A extends B |
| 10122 // class B extends A |
| 10123 ClassElementImpl classA = ElementFactory.classElement2('A', []); |
| 10124 ClassElementImpl classB = ElementFactory.classElement2('B', []); |
| 10125 classA.supertype = classB.type; |
| 10126 classB.supertype = classA.type; |
| 10127 // flatten(A) = A and flatten(B) = B, since neither class contains Future |
| 10128 // in its class hierarchy. Even though there is a loop in the class |
| 10129 // hierarchy, flatten() should terminate. |
| 10130 expect(_flatten(classA.type), classA.type); |
| 10131 expect(_flatten(classB.type), classB.type); |
| 10132 } |
| 10133 |
| 10134 void test_flatten_related_derived_types() { |
| 10135 InterfaceType intType = _typeProvider.intType; |
| 10136 InterfaceType numType = _typeProvider.numType; |
| 10137 // class Derived<T> extends Future<T> |
| 10138 ClassElementImpl derivedClass = |
| 10139 ElementFactory.classElement2('Derived', ['T']); |
| 10140 derivedClass.supertype = _typeProvider.futureType |
| 10141 .substitute4([derivedClass.typeParameters[0].type]); |
| 10142 InterfaceType derivedType = derivedClass.type; |
| 10143 // class A extends Derived<int> implements Derived<num> { ... } |
| 10144 ClassElementImpl classA = |
| 10145 ElementFactory.classElement('A', derivedType.substitute4([intType])); |
| 10146 classA.interfaces = <InterfaceType>[ |
| 10147 derivedType.substitute4([numType]) |
| 10148 ]; |
| 10149 // class B extends Future<num> implements Future<int> { ... } |
| 10150 ClassElementImpl classB = |
| 10151 ElementFactory.classElement('B', derivedType.substitute4([numType])); |
| 10152 classB.interfaces = <InterfaceType>[ |
| 10153 derivedType.substitute4([intType]) |
| 10154 ]; |
| 10155 // flatten(A) = flatten(B) = int, since int is more specific than num. |
| 10156 // The code in flatten() that inhibits infinite recursion shouldn't be |
| 10157 // fooled by the fact that Derived appears twice in the type hierarchy. |
| 10158 expect(_flatten(classA.type), intType); |
| 10159 expect(_flatten(classB.type), intType); |
| 10160 } |
| 10161 |
| 10162 void test_flatten_related_types() { |
| 10163 InterfaceType futureType = _typeProvider.futureType; |
| 10164 InterfaceType intType = _typeProvider.intType; |
| 10165 InterfaceType numType = _typeProvider.numType; |
| 10166 // class A extends Future<int> implements Future<num> { ... } |
| 10167 ClassElementImpl classA = |
| 10168 ElementFactory.classElement('A', futureType.substitute4([intType])); |
| 10169 classA.interfaces = <InterfaceType>[ |
| 10170 futureType.substitute4([numType]) |
| 10171 ]; |
| 10172 // class B extends Future<num> implements Future<int> { ... } |
| 10173 ClassElementImpl classB = |
| 10174 ElementFactory.classElement('B', futureType.substitute4([numType])); |
| 10175 classB.interfaces = <InterfaceType>[ |
| 10176 futureType.substitute4([intType]) |
| 10177 ]; |
| 10178 // flatten(A) = flatten(B) = int, since int is more specific than num. |
| 10179 expect(_flatten(classA.type), intType); |
| 10180 expect(_flatten(classB.type), intType); |
| 10181 } |
| 10182 |
| 10183 void test_flatten_simple() { |
| 10184 InterfaceType intType = _typeProvider.intType; |
| 10185 DartType dynamicType = _typeProvider.dynamicType; |
| 10186 InterfaceType futureDynamicType = _typeProvider.futureDynamicType; |
| 10187 InterfaceType futureIntType = |
| 10188 _typeProvider.futureType.substitute4([intType]); |
| 10189 InterfaceType futureFutureDynamicType = |
| 10190 _typeProvider.futureType.substitute4([futureDynamicType]); |
| 10191 InterfaceType futureFutureIntType = |
| 10192 _typeProvider.futureType.substitute4([futureIntType]); |
| 10193 // flatten(int) = int |
| 10194 expect(_flatten(intType), intType); |
| 10195 // flatten(dynamic) = dynamic |
| 10196 expect(_flatten(dynamicType), dynamicType); |
| 10197 // flatten(Future) = dynamic |
| 10198 expect(_flatten(futureDynamicType), dynamicType); |
| 10199 // flatten(Future<int>) = int |
| 10200 expect(_flatten(futureIntType), intType); |
| 10201 // flatten(Future<Future>) = dynamic |
| 10202 expect(_flatten(futureFutureDynamicType), dynamicType); |
| 10203 // flatten(Future<Future<int>>) = int |
| 10204 expect(_flatten(futureFutureIntType), intType); |
| 10205 } |
| 10206 |
| 10207 void test_flatten_unrelated_types() { |
| 10208 InterfaceType futureType = _typeProvider.futureType; |
| 10209 InterfaceType intType = _typeProvider.intType; |
| 10210 InterfaceType stringType = _typeProvider.stringType; |
| 10211 // class A extends Future<int> implements Future<String> { ... } |
| 10212 ClassElementImpl classA = |
| 10213 ElementFactory.classElement('A', futureType.substitute4([intType])); |
| 10214 classA.interfaces = <InterfaceType>[ |
| 10215 futureType.substitute4([stringType]) |
| 10216 ]; |
| 10217 // class B extends Future<String> implements Future<int> { ... } |
| 10218 ClassElementImpl classB = |
| 10219 ElementFactory.classElement('B', futureType.substitute4([stringType])); |
| 10220 classB.interfaces = <InterfaceType>[ |
| 10221 futureType.substitute4([intType]) |
| 10222 ]; |
| 10223 // flatten(A) = A and flatten(B) = B, since neither string nor int is more |
| 10224 // specific than the other. |
| 10225 expect(_flatten(classA.type), classA.type); |
| 10226 expect(_flatten(classB.type), classB.type); |
| 10227 } |
| 10228 |
| 10229 void test_visitAdjacentStrings() { |
| 10230 // "a" "b" |
| 10231 Expression node = AstFactory |
| 10232 .adjacentStrings([_resolvedString("a"), _resolvedString("b")]); |
| 10233 expect(_analyze(node), same(_typeProvider.stringType)); |
| 10234 _listener.assertNoErrors(); |
| 10235 } |
| 10236 |
| 10237 void test_visitAsExpression() { |
| 10238 // class A { ... this as B ... } |
| 10239 // class B extends A {} |
| 10240 ClassElement superclass = ElementFactory.classElement2("A"); |
| 10241 InterfaceType superclassType = superclass.type; |
| 10242 ClassElement subclass = ElementFactory.classElement("B", superclassType); |
| 10243 Expression node = AstFactory.asExpression( |
| 10244 AstFactory.thisExpression(), AstFactory.typeName(subclass)); |
| 10245 expect(_analyze3(node, superclassType), same(subclass.type)); |
| 10246 _listener.assertNoErrors(); |
| 10247 } |
| 10248 |
| 10249 void test_visitAssignmentExpression_compound() { |
| 10250 // i += 1 |
| 10251 InterfaceType numType = _typeProvider.numType; |
| 10252 SimpleIdentifier identifier = _resolvedVariable(_typeProvider.intType, "i"); |
| 10253 AssignmentExpression node = AstFactory.assignmentExpression( |
| 10254 identifier, TokenType.PLUS_EQ, _resolvedInteger(1)); |
| 10255 MethodElement plusMethod = getMethod(numType, "+"); |
| 10256 node.staticElement = plusMethod; |
| 10257 expect(_analyze(node), same(numType)); |
| 10258 _listener.assertNoErrors(); |
| 10259 } |
| 10260 |
| 10261 void test_visitAssignmentExpression_compoundIfNull_differentTypes() { |
| 10262 // double d; d ??= 0 |
| 10263 Expression node = AstFactory.assignmentExpression( |
| 10264 _resolvedVariable(_typeProvider.doubleType, 'd'), |
| 10265 TokenType.QUESTION_QUESTION_EQ, |
| 10266 _resolvedInteger(0)); |
| 10267 expect(_analyze(node), same(_typeProvider.numType)); |
| 10268 _listener.assertNoErrors(); |
| 10269 } |
| 10270 |
| 10271 void test_visitAssignmentExpression_compoundIfNull_sameTypes() { |
| 10272 // int i; i ??= 0 |
| 10273 Expression node = AstFactory.assignmentExpression( |
| 10274 _resolvedVariable(_typeProvider.intType, 'i'), |
| 10275 TokenType.QUESTION_QUESTION_EQ, |
| 10276 _resolvedInteger(0)); |
| 10277 expect(_analyze(node), same(_typeProvider.intType)); |
| 10278 _listener.assertNoErrors(); |
| 10279 } |
| 10280 |
| 10281 void test_visitAssignmentExpression_simple() { |
| 10282 // i = 0 |
| 10283 InterfaceType intType = _typeProvider.intType; |
| 10284 Expression node = AstFactory.assignmentExpression( |
| 10285 _resolvedVariable(intType, "i"), TokenType.EQ, _resolvedInteger(0)); |
| 10286 expect(_analyze(node), same(intType)); |
| 10287 _listener.assertNoErrors(); |
| 10288 } |
| 10289 |
| 10290 void test_visitAwaitExpression_flattened() { |
| 10291 // await e, where e has type Future<Future<int>> |
| 10292 InterfaceType intType = _typeProvider.intType; |
| 10293 InterfaceType futureIntType = |
| 10294 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10295 InterfaceType futureFutureIntType = |
| 10296 _typeProvider.futureType.substitute4(<DartType>[futureIntType]); |
| 10297 Expression node = |
| 10298 AstFactory.awaitExpression(_resolvedVariable(futureFutureIntType, 'e')); |
| 10299 expect(_analyze(node), same(intType)); |
| 10300 _listener.assertNoErrors(); |
| 10301 } |
| 10302 |
| 10303 void test_visitAwaitExpression_simple() { |
| 10304 // await e, where e has type Future<int> |
| 10305 InterfaceType intType = _typeProvider.intType; |
| 10306 InterfaceType futureIntType = |
| 10307 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10308 Expression node = |
| 10309 AstFactory.awaitExpression(_resolvedVariable(futureIntType, 'e')); |
| 10310 expect(_analyze(node), same(intType)); |
| 10311 _listener.assertNoErrors(); |
| 10312 } |
| 10313 |
| 10314 void test_visitBinaryExpression_equals() { |
| 10315 // 2 == 3 |
| 10316 Expression node = AstFactory.binaryExpression( |
| 10317 _resolvedInteger(2), TokenType.EQ_EQ, _resolvedInteger(3)); |
| 10318 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10319 _listener.assertNoErrors(); |
| 10320 } |
| 10321 |
| 10322 void test_visitBinaryExpression_ifNull() { |
| 10323 // 1 ?? 1.5 |
| 10324 Expression node = AstFactory.binaryExpression( |
| 10325 _resolvedInteger(1), TokenType.QUESTION_QUESTION, _resolvedDouble(1.5)); |
| 10326 expect(_analyze(node), same(_typeProvider.numType)); |
| 10327 _listener.assertNoErrors(); |
| 10328 } |
| 10329 |
| 10330 void test_visitBinaryExpression_logicalAnd() { |
| 10331 // false && true |
| 10332 Expression node = AstFactory.binaryExpression( |
| 10333 AstFactory.booleanLiteral(false), |
| 10334 TokenType.AMPERSAND_AMPERSAND, |
| 10335 AstFactory.booleanLiteral(true)); |
| 10336 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10337 _listener.assertNoErrors(); |
| 10338 } |
| 10339 |
| 10340 void test_visitBinaryExpression_logicalOr() { |
| 10341 // false || true |
| 10342 Expression node = AstFactory.binaryExpression( |
| 10343 AstFactory.booleanLiteral(false), |
| 10344 TokenType.BAR_BAR, |
| 10345 AstFactory.booleanLiteral(true)); |
| 10346 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10347 _listener.assertNoErrors(); |
| 10348 } |
| 10349 |
| 10350 void test_visitBinaryExpression_minusID_propagated() { |
| 10351 // a - b |
| 10352 BinaryExpression node = AstFactory.binaryExpression( |
| 10353 _propagatedVariable(_typeProvider.intType, 'a'), |
| 10354 TokenType.MINUS, |
| 10355 _propagatedVariable(_typeProvider.doubleType, 'b')); |
| 10356 node.propagatedElement = getMethod(_typeProvider.numType, "+"); |
| 10357 _analyze(node); |
| 10358 expect(node.propagatedType, same(_typeProvider.doubleType)); |
| 10359 _listener.assertNoErrors(); |
| 10360 } |
| 10361 |
| 10362 void test_visitBinaryExpression_notEquals() { |
| 10363 // 2 != 3 |
| 10364 Expression node = AstFactory.binaryExpression( |
| 10365 _resolvedInteger(2), TokenType.BANG_EQ, _resolvedInteger(3)); |
| 10366 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10367 _listener.assertNoErrors(); |
| 10368 } |
| 10369 |
| 10370 void test_visitBinaryExpression_plusID() { |
| 10371 // 1 + 2.0 |
| 10372 BinaryExpression node = AstFactory.binaryExpression( |
| 10373 _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0)); |
| 10374 node.staticElement = getMethod(_typeProvider.numType, "+"); |
| 10375 expect(_analyze(node), same(_typeProvider.doubleType)); |
| 10376 _listener.assertNoErrors(); |
| 10377 } |
| 10378 |
| 10379 void test_visitBinaryExpression_plusII() { |
| 10380 // 1 + 2 |
| 10381 BinaryExpression node = AstFactory.binaryExpression( |
| 10382 _resolvedInteger(1), TokenType.PLUS, _resolvedInteger(2)); |
| 10383 node.staticElement = getMethod(_typeProvider.numType, "+"); |
| 10384 expect(_analyze(node), same(_typeProvider.intType)); |
| 10385 _listener.assertNoErrors(); |
| 10386 } |
| 10387 |
| 10388 void test_visitBinaryExpression_plusII_propagated() { |
| 10389 // a + b |
| 10390 BinaryExpression node = AstFactory.binaryExpression( |
| 10391 _propagatedVariable(_typeProvider.intType, 'a'), |
| 10392 TokenType.PLUS, |
| 10393 _propagatedVariable(_typeProvider.intType, 'b')); |
| 10394 node.propagatedElement = getMethod(_typeProvider.numType, "+"); |
| 10395 _analyze(node); |
| 10396 expect(node.propagatedType, same(_typeProvider.intType)); |
| 10397 _listener.assertNoErrors(); |
| 10398 } |
| 10399 |
| 10400 void test_visitBinaryExpression_slash() { |
| 10401 // 2 / 2 |
| 10402 BinaryExpression node = AstFactory.binaryExpression( |
| 10403 _resolvedInteger(2), TokenType.SLASH, _resolvedInteger(2)); |
| 10404 node.staticElement = getMethod(_typeProvider.numType, "/"); |
| 10405 expect(_analyze(node), same(_typeProvider.doubleType)); |
| 10406 _listener.assertNoErrors(); |
| 10407 } |
| 10408 |
| 10409 void test_visitBinaryExpression_star_notSpecial() { |
| 10410 // class A { |
| 10411 // A operator *(double value); |
| 10412 // } |
| 10413 // (a as A) * 2.0 |
| 10414 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 10415 InterfaceType typeA = classA.type; |
| 10416 MethodElement operator = |
| 10417 ElementFactory.methodElement("*", typeA, [_typeProvider.doubleType]); |
| 10418 classA.methods = <MethodElement>[operator]; |
| 10419 BinaryExpression node = AstFactory.binaryExpression( |
| 10420 AstFactory.asExpression( |
| 10421 AstFactory.identifier3("a"), AstFactory.typeName(classA)), |
| 10422 TokenType.PLUS, |
| 10423 _resolvedDouble(2.0)); |
| 10424 node.staticElement = operator; |
| 10425 expect(_analyze(node), same(typeA)); |
| 10426 _listener.assertNoErrors(); |
| 10427 } |
| 10428 |
| 10429 void test_visitBinaryExpression_starID() { |
| 10430 // 1 * 2.0 |
| 10431 BinaryExpression node = AstFactory.binaryExpression( |
| 10432 _resolvedInteger(1), TokenType.PLUS, _resolvedDouble(2.0)); |
| 10433 node.staticElement = getMethod(_typeProvider.numType, "*"); |
| 10434 expect(_analyze(node), same(_typeProvider.doubleType)); |
| 10435 _listener.assertNoErrors(); |
| 10436 } |
| 10437 |
| 10438 void test_visitBooleanLiteral_false() { |
| 10439 // false |
| 10440 Expression node = AstFactory.booleanLiteral(false); |
| 10441 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10442 _listener.assertNoErrors(); |
| 10443 } |
| 10444 |
| 10445 void test_visitBooleanLiteral_true() { |
| 10446 // true |
| 10447 Expression node = AstFactory.booleanLiteral(true); |
| 10448 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10449 _listener.assertNoErrors(); |
| 10450 } |
| 10451 |
| 10452 void test_visitCascadeExpression() { |
| 10453 // a..length |
| 10454 Expression node = AstFactory.cascadeExpression( |
| 10455 _resolvedString("a"), [AstFactory.propertyAccess2(null, "length")]); |
| 10456 expect(_analyze(node), same(_typeProvider.stringType)); |
| 10457 _listener.assertNoErrors(); |
| 10458 } |
| 10459 |
| 10460 void test_visitConditionalExpression_differentTypes() { |
| 10461 // true ? 1.0 : 0 |
| 10462 Expression node = AstFactory.conditionalExpression( |
| 10463 AstFactory.booleanLiteral(true), |
| 10464 _resolvedDouble(1.0), |
| 10465 _resolvedInteger(0)); |
| 10466 expect(_analyze(node), same(_typeProvider.numType)); |
| 10467 _listener.assertNoErrors(); |
| 10468 } |
| 10469 |
| 10470 void test_visitConditionalExpression_sameTypes() { |
| 10471 // true ? 1 : 0 |
| 10472 Expression node = AstFactory.conditionalExpression( |
| 10473 AstFactory.booleanLiteral(true), |
| 10474 _resolvedInteger(1), |
| 10475 _resolvedInteger(0)); |
| 10476 expect(_analyze(node), same(_typeProvider.intType)); |
| 10477 _listener.assertNoErrors(); |
| 10478 } |
| 10479 |
| 10480 void test_visitDoubleLiteral() { |
| 10481 // 4.33 |
| 10482 Expression node = AstFactory.doubleLiteral(4.33); |
| 10483 expect(_analyze(node), same(_typeProvider.doubleType)); |
| 10484 _listener.assertNoErrors(); |
| 10485 } |
| 10486 |
| 10487 void test_visitFunctionExpression_async_block() { |
| 10488 // () async {} |
| 10489 BlockFunctionBody body = AstFactory.blockFunctionBody2(); |
| 10490 body.keyword = TokenFactory.tokenFromString('async'); |
| 10491 FunctionExpression node = |
| 10492 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10493 DartType resultType = _analyze(node); |
| 10494 _assertFunctionType( |
| 10495 _typeProvider.futureDynamicType, null, null, null, resultType); |
| 10496 _listener.assertNoErrors(); |
| 10497 } |
| 10498 |
| 10499 void test_visitFunctionExpression_async_expression() { |
| 10500 // () async => e, where e has type int |
| 10501 InterfaceType intType = _typeProvider.intType; |
| 10502 InterfaceType futureIntType = |
| 10503 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10504 Expression expression = _resolvedVariable(intType, 'e'); |
| 10505 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); |
| 10506 body.keyword = TokenFactory.tokenFromString('async'); |
| 10507 FunctionExpression node = |
| 10508 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10509 DartType resultType = _analyze(node); |
| 10510 _assertFunctionType(futureIntType, null, null, null, resultType); |
| 10511 _listener.assertNoErrors(); |
| 10512 } |
| 10513 |
| 10514 void test_visitFunctionExpression_async_expression_flatten() { |
| 10515 // () async => e, where e has type Future<int> |
| 10516 InterfaceType intType = _typeProvider.intType; |
| 10517 InterfaceType futureIntType = |
| 10518 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10519 Expression expression = _resolvedVariable(futureIntType, 'e'); |
| 10520 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); |
| 10521 body.keyword = TokenFactory.tokenFromString('async'); |
| 10522 FunctionExpression node = |
| 10523 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10524 DartType resultType = _analyze(node); |
| 10525 _assertFunctionType(futureIntType, null, null, null, resultType); |
| 10526 _listener.assertNoErrors(); |
| 10527 } |
| 10528 |
| 10529 void test_visitFunctionExpression_async_expression_flatten_twice() { |
| 10530 // () async => e, where e has type Future<Future<int>> |
| 10531 InterfaceType intType = _typeProvider.intType; |
| 10532 InterfaceType futureIntType = |
| 10533 _typeProvider.futureType.substitute4(<DartType>[intType]); |
| 10534 InterfaceType futureFutureIntType = |
| 10535 _typeProvider.futureType.substitute4(<DartType>[futureIntType]); |
| 10536 Expression expression = _resolvedVariable(futureFutureIntType, 'e'); |
| 10537 ExpressionFunctionBody body = AstFactory.expressionFunctionBody(expression); |
| 10538 body.keyword = TokenFactory.tokenFromString('async'); |
| 10539 FunctionExpression node = |
| 10540 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10541 DartType resultType = _analyze(node); |
| 10542 _assertFunctionType(futureIntType, null, null, null, resultType); |
| 10543 _listener.assertNoErrors(); |
| 10544 } |
| 10545 |
| 10546 void test_visitFunctionExpression_generator_async() { |
| 10547 // () async* {} |
| 10548 BlockFunctionBody body = AstFactory.blockFunctionBody2(); |
| 10549 body.keyword = TokenFactory.tokenFromString('async'); |
| 10550 body.star = TokenFactory.tokenFromType(TokenType.STAR); |
| 10551 FunctionExpression node = |
| 10552 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10553 DartType resultType = _analyze(node); |
| 10554 _assertFunctionType( |
| 10555 _typeProvider.streamDynamicType, null, null, null, resultType); |
| 10556 _listener.assertNoErrors(); |
| 10557 } |
| 10558 |
| 10559 void test_visitFunctionExpression_generator_sync() { |
| 10560 // () sync* {} |
| 10561 BlockFunctionBody body = AstFactory.blockFunctionBody2(); |
| 10562 body.keyword = TokenFactory.tokenFromString('sync'); |
| 10563 body.star = TokenFactory.tokenFromType(TokenType.STAR); |
| 10564 FunctionExpression node = |
| 10565 _resolvedFunctionExpression(AstFactory.formalParameterList([]), body); |
| 10566 DartType resultType = _analyze(node); |
| 10567 _assertFunctionType( |
| 10568 _typeProvider.iterableDynamicType, null, null, null, resultType); |
| 10569 _listener.assertNoErrors(); |
| 10570 } |
| 10571 |
| 10572 void test_visitFunctionExpression_named_block() { |
| 10573 // ({p1 : 0, p2 : 0}) {} |
| 10574 DartType dynamicType = _typeProvider.dynamicType; |
| 10575 FormalParameter p1 = AstFactory.namedFormalParameter( |
| 10576 AstFactory.simpleFormalParameter3("p1"), _resolvedInteger(0)); |
| 10577 _setType(p1, dynamicType); |
| 10578 FormalParameter p2 = AstFactory.namedFormalParameter( |
| 10579 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10580 _setType(p2, dynamicType); |
| 10581 FunctionExpression node = _resolvedFunctionExpression( |
| 10582 AstFactory.formalParameterList([p1, p2]), |
| 10583 AstFactory.blockFunctionBody2()); |
| 10584 _analyze5(p1); |
| 10585 _analyze5(p2); |
| 10586 DartType resultType = _analyze(node); |
| 10587 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); |
| 10588 expectedNamedTypes["p1"] = dynamicType; |
| 10589 expectedNamedTypes["p2"] = dynamicType; |
| 10590 _assertFunctionType( |
| 10591 dynamicType, null, null, expectedNamedTypes, resultType); |
| 10592 _listener.assertNoErrors(); |
| 10593 } |
| 10594 |
| 10595 void test_visitFunctionExpression_named_expression() { |
| 10596 // ({p : 0}) -> 0; |
| 10597 DartType dynamicType = _typeProvider.dynamicType; |
| 10598 FormalParameter p = AstFactory.namedFormalParameter( |
| 10599 AstFactory.simpleFormalParameter3("p"), _resolvedInteger(0)); |
| 10600 _setType(p, dynamicType); |
| 10601 FunctionExpression node = _resolvedFunctionExpression( |
| 10602 AstFactory.formalParameterList([p]), |
| 10603 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10604 _analyze5(p); |
| 10605 DartType resultType = _analyze(node); |
| 10606 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); |
| 10607 expectedNamedTypes["p"] = dynamicType; |
| 10608 _assertFunctionType( |
| 10609 _typeProvider.intType, null, null, expectedNamedTypes, resultType); |
| 10610 _listener.assertNoErrors(); |
| 10611 } |
| 10612 |
| 10613 void test_visitFunctionExpression_normal_block() { |
| 10614 // (p1, p2) {} |
| 10615 DartType dynamicType = _typeProvider.dynamicType; |
| 10616 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10617 _setType(p1, dynamicType); |
| 10618 FormalParameter p2 = AstFactory.simpleFormalParameter3("p2"); |
| 10619 _setType(p2, dynamicType); |
| 10620 FunctionExpression node = _resolvedFunctionExpression( |
| 10621 AstFactory.formalParameterList([p1, p2]), |
| 10622 AstFactory.blockFunctionBody2()); |
| 10623 _analyze5(p1); |
| 10624 _analyze5(p2); |
| 10625 DartType resultType = _analyze(node); |
| 10626 _assertFunctionType(dynamicType, <DartType>[dynamicType, dynamicType], null, |
| 10627 null, resultType); |
| 10628 _listener.assertNoErrors(); |
| 10629 } |
| 10630 |
| 10631 void test_visitFunctionExpression_normal_expression() { |
| 10632 // (p1, p2) -> 0 |
| 10633 DartType dynamicType = _typeProvider.dynamicType; |
| 10634 FormalParameter p = AstFactory.simpleFormalParameter3("p"); |
| 10635 _setType(p, dynamicType); |
| 10636 FunctionExpression node = _resolvedFunctionExpression( |
| 10637 AstFactory.formalParameterList([p]), |
| 10638 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10639 _analyze5(p); |
| 10640 DartType resultType = _analyze(node); |
| 10641 _assertFunctionType( |
| 10642 _typeProvider.intType, <DartType>[dynamicType], null, null, resultType); |
| 10643 _listener.assertNoErrors(); |
| 10644 } |
| 10645 |
| 10646 void test_visitFunctionExpression_normalAndNamed_block() { |
| 10647 // (p1, {p2 : 0}) {} |
| 10648 DartType dynamicType = _typeProvider.dynamicType; |
| 10649 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10650 _setType(p1, dynamicType); |
| 10651 FormalParameter p2 = AstFactory.namedFormalParameter( |
| 10652 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10653 _setType(p2, dynamicType); |
| 10654 FunctionExpression node = _resolvedFunctionExpression( |
| 10655 AstFactory.formalParameterList([p1, p2]), |
| 10656 AstFactory.blockFunctionBody2()); |
| 10657 _analyze5(p2); |
| 10658 DartType resultType = _analyze(node); |
| 10659 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); |
| 10660 expectedNamedTypes["p2"] = dynamicType; |
| 10661 _assertFunctionType(dynamicType, <DartType>[dynamicType], null, |
| 10662 expectedNamedTypes, resultType); |
| 10663 _listener.assertNoErrors(); |
| 10664 } |
| 10665 |
| 10666 void test_visitFunctionExpression_normalAndNamed_expression() { |
| 10667 // (p1, {p2 : 0}) -> 0 |
| 10668 DartType dynamicType = _typeProvider.dynamicType; |
| 10669 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10670 _setType(p1, dynamicType); |
| 10671 FormalParameter p2 = AstFactory.namedFormalParameter( |
| 10672 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10673 _setType(p2, dynamicType); |
| 10674 FunctionExpression node = _resolvedFunctionExpression( |
| 10675 AstFactory.formalParameterList([p1, p2]), |
| 10676 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10677 _analyze5(p2); |
| 10678 DartType resultType = _analyze(node); |
| 10679 Map<String, DartType> expectedNamedTypes = new HashMap<String, DartType>(); |
| 10680 expectedNamedTypes["p2"] = dynamicType; |
| 10681 _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], null, |
| 10682 expectedNamedTypes, resultType); |
| 10683 _listener.assertNoErrors(); |
| 10684 } |
| 10685 |
| 10686 void test_visitFunctionExpression_normalAndPositional_block() { |
| 10687 // (p1, [p2 = 0]) {} |
| 10688 DartType dynamicType = _typeProvider.dynamicType; |
| 10689 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10690 _setType(p1, dynamicType); |
| 10691 FormalParameter p2 = AstFactory.positionalFormalParameter( |
| 10692 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10693 _setType(p2, dynamicType); |
| 10694 FunctionExpression node = _resolvedFunctionExpression( |
| 10695 AstFactory.formalParameterList([p1, p2]), |
| 10696 AstFactory.blockFunctionBody2()); |
| 10697 _analyze5(p1); |
| 10698 _analyze5(p2); |
| 10699 DartType resultType = _analyze(node); |
| 10700 _assertFunctionType(dynamicType, <DartType>[dynamicType], |
| 10701 <DartType>[dynamicType], null, resultType); |
| 10702 _listener.assertNoErrors(); |
| 10703 } |
| 10704 |
| 10705 void test_visitFunctionExpression_normalAndPositional_expression() { |
| 10706 // (p1, [p2 = 0]) -> 0 |
| 10707 DartType dynamicType = _typeProvider.dynamicType; |
| 10708 FormalParameter p1 = AstFactory.simpleFormalParameter3("p1"); |
| 10709 _setType(p1, dynamicType); |
| 10710 FormalParameter p2 = AstFactory.positionalFormalParameter( |
| 10711 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10712 _setType(p2, dynamicType); |
| 10713 FunctionExpression node = _resolvedFunctionExpression( |
| 10714 AstFactory.formalParameterList([p1, p2]), |
| 10715 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10716 _analyze5(p1); |
| 10717 _analyze5(p2); |
| 10718 DartType resultType = _analyze(node); |
| 10719 _assertFunctionType(_typeProvider.intType, <DartType>[dynamicType], |
| 10720 <DartType>[dynamicType], null, resultType); |
| 10721 _listener.assertNoErrors(); |
| 10722 } |
| 10723 |
| 10724 void test_visitFunctionExpression_positional_block() { |
| 10725 // ([p1 = 0, p2 = 0]) {} |
| 10726 DartType dynamicType = _typeProvider.dynamicType; |
| 10727 FormalParameter p1 = AstFactory.positionalFormalParameter( |
| 10728 AstFactory.simpleFormalParameter3("p1"), _resolvedInteger(0)); |
| 10729 _setType(p1, dynamicType); |
| 10730 FormalParameter p2 = AstFactory.positionalFormalParameter( |
| 10731 AstFactory.simpleFormalParameter3("p2"), _resolvedInteger(0)); |
| 10732 _setType(p2, dynamicType); |
| 10733 FunctionExpression node = _resolvedFunctionExpression( |
| 10734 AstFactory.formalParameterList([p1, p2]), |
| 10735 AstFactory.blockFunctionBody2()); |
| 10736 _analyze5(p1); |
| 10737 _analyze5(p2); |
| 10738 DartType resultType = _analyze(node); |
| 10739 _assertFunctionType(dynamicType, null, <DartType>[dynamicType, dynamicType], |
| 10740 null, resultType); |
| 10741 _listener.assertNoErrors(); |
| 10742 } |
| 10743 |
| 10744 void test_visitFunctionExpression_positional_expression() { |
| 10745 // ([p1 = 0, p2 = 0]) -> 0 |
| 10746 DartType dynamicType = _typeProvider.dynamicType; |
| 10747 FormalParameter p = AstFactory.positionalFormalParameter( |
| 10748 AstFactory.simpleFormalParameter3("p"), _resolvedInteger(0)); |
| 10749 _setType(p, dynamicType); |
| 10750 FunctionExpression node = _resolvedFunctionExpression( |
| 10751 AstFactory.formalParameterList([p]), |
| 10752 AstFactory.expressionFunctionBody(_resolvedInteger(0))); |
| 10753 _analyze5(p); |
| 10754 DartType resultType = _analyze(node); |
| 10755 _assertFunctionType( |
| 10756 _typeProvider.intType, null, <DartType>[dynamicType], null, resultType); |
| 10757 _listener.assertNoErrors(); |
| 10758 } |
| 10759 |
| 10760 void test_visitIndexExpression_getter() { |
| 10761 // List a; |
| 10762 // a[2] |
| 10763 InterfaceType listType = _typeProvider.listType; |
| 10764 SimpleIdentifier identifier = _resolvedVariable(listType, "a"); |
| 10765 IndexExpression node = |
| 10766 AstFactory.indexExpression(identifier, _resolvedInteger(2)); |
| 10767 MethodElement indexMethod = listType.element.methods[0]; |
| 10768 node.staticElement = indexMethod; |
| 10769 expect(_analyze(node), same(listType.typeArguments[0])); |
| 10770 _listener.assertNoErrors(); |
| 10771 } |
| 10772 |
| 10773 void test_visitIndexExpression_setter() { |
| 10774 // List a; |
| 10775 // a[2] = 0 |
| 10776 InterfaceType listType = _typeProvider.listType; |
| 10777 SimpleIdentifier identifier = _resolvedVariable(listType, "a"); |
| 10778 IndexExpression node = |
| 10779 AstFactory.indexExpression(identifier, _resolvedInteger(2)); |
| 10780 MethodElement indexMethod = listType.element.methods[1]; |
| 10781 node.staticElement = indexMethod; |
| 10782 AstFactory.assignmentExpression(node, TokenType.EQ, AstFactory.integer(0)); |
| 10783 expect(_analyze(node), same(listType.typeArguments[0])); |
| 10784 _listener.assertNoErrors(); |
| 10785 } |
| 10786 |
| 10787 void test_visitIndexExpression_typeParameters() { |
| 10788 // List<int> list = ... |
| 10789 // list[0] |
| 10790 InterfaceType intType = _typeProvider.intType; |
| 10791 InterfaceType listType = _typeProvider.listType; |
| 10792 // (int) -> E |
| 10793 MethodElement methodElement = getMethod(listType, "[]"); |
| 10794 // "list" has type List<int> |
| 10795 SimpleIdentifier identifier = AstFactory.identifier3("list"); |
| 10796 InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]); |
| 10797 identifier.staticType = listOfIntType; |
| 10798 // list[0] has MethodElement element (int) -> E |
| 10799 IndexExpression indexExpression = |
| 10800 AstFactory.indexExpression(identifier, AstFactory.integer(0)); |
| 10801 MethodElement indexMethod = MethodMember.from(methodElement, listOfIntType); |
| 10802 indexExpression.staticElement = indexMethod; |
| 10803 // analyze and assert result of the index expression |
| 10804 expect(_analyze(indexExpression), same(intType)); |
| 10805 _listener.assertNoErrors(); |
| 10806 } |
| 10807 |
| 10808 void test_visitIndexExpression_typeParameters_inSetterContext() { |
| 10809 // List<int> list = ... |
| 10810 // list[0] = 0; |
| 10811 InterfaceType intType = _typeProvider.intType; |
| 10812 InterfaceType listType = _typeProvider.listType; |
| 10813 // (int, E) -> void |
| 10814 MethodElement methodElement = getMethod(listType, "[]="); |
| 10815 // "list" has type List<int> |
| 10816 SimpleIdentifier identifier = AstFactory.identifier3("list"); |
| 10817 InterfaceType listOfIntType = listType.substitute4(<DartType>[intType]); |
| 10818 identifier.staticType = listOfIntType; |
| 10819 // list[0] has MethodElement element (int) -> E |
| 10820 IndexExpression indexExpression = |
| 10821 AstFactory.indexExpression(identifier, AstFactory.integer(0)); |
| 10822 MethodElement indexMethod = MethodMember.from(methodElement, listOfIntType); |
| 10823 indexExpression.staticElement = indexMethod; |
| 10824 // list[0] should be in a setter context |
| 10825 AstFactory.assignmentExpression( |
| 10826 indexExpression, TokenType.EQ, AstFactory.integer(0)); |
| 10827 // analyze and assert result of the index expression |
| 10828 expect(_analyze(indexExpression), same(intType)); |
| 10829 _listener.assertNoErrors(); |
| 10830 } |
| 10831 |
| 10832 void test_visitInstanceCreationExpression_named() { |
| 10833 // new C.m() |
| 10834 ClassElementImpl classElement = ElementFactory.classElement2("C"); |
| 10835 String constructorName = "m"; |
| 10836 ConstructorElementImpl constructor = |
| 10837 ElementFactory.constructorElement2(classElement, constructorName); |
| 10838 constructor.returnType = classElement.type; |
| 10839 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); |
| 10840 constructor.type = constructorType; |
| 10841 classElement.constructors = <ConstructorElement>[constructor]; |
| 10842 InstanceCreationExpression node = AstFactory.instanceCreationExpression2( |
| 10843 null, |
| 10844 AstFactory.typeName(classElement), |
| 10845 [AstFactory.identifier3(constructorName)]); |
| 10846 node.staticElement = constructor; |
| 10847 expect(_analyze(node), same(classElement.type)); |
| 10848 _listener.assertNoErrors(); |
| 10849 } |
| 10850 |
| 10851 void test_visitInstanceCreationExpression_typeParameters() { |
| 10852 // new C<I>() |
| 10853 ClassElementImpl elementC = ElementFactory.classElement2("C", ["E"]); |
| 10854 ClassElementImpl elementI = ElementFactory.classElement2("I"); |
| 10855 ConstructorElementImpl constructor = |
| 10856 ElementFactory.constructorElement2(elementC, null); |
| 10857 elementC.constructors = <ConstructorElement>[constructor]; |
| 10858 constructor.returnType = elementC.type; |
| 10859 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); |
| 10860 constructor.type = constructorType; |
| 10861 TypeName typeName = |
| 10862 AstFactory.typeName(elementC, [AstFactory.typeName(elementI)]); |
| 10863 typeName.type = elementC.type.substitute4(<DartType>[elementI.type]); |
| 10864 InstanceCreationExpression node = |
| 10865 AstFactory.instanceCreationExpression2(null, typeName); |
| 10866 node.staticElement = constructor; |
| 10867 InterfaceType interfaceType = _analyze(node) as InterfaceType; |
| 10868 List<DartType> typeArgs = interfaceType.typeArguments; |
| 10869 expect(typeArgs.length, 1); |
| 10870 expect(typeArgs[0], elementI.type); |
| 10871 _listener.assertNoErrors(); |
| 10872 } |
| 10873 |
| 10874 void test_visitInstanceCreationExpression_unnamed() { |
| 10875 // new C() |
| 10876 ClassElementImpl classElement = ElementFactory.classElement2("C"); |
| 10877 ConstructorElementImpl constructor = |
| 10878 ElementFactory.constructorElement2(classElement, null); |
| 10879 constructor.returnType = classElement.type; |
| 10880 FunctionTypeImpl constructorType = new FunctionTypeImpl(constructor); |
| 10881 constructor.type = constructorType; |
| 10882 classElement.constructors = <ConstructorElement>[constructor]; |
| 10883 InstanceCreationExpression node = AstFactory.instanceCreationExpression2( |
| 10884 null, AstFactory.typeName(classElement)); |
| 10885 node.staticElement = constructor; |
| 10886 expect(_analyze(node), same(classElement.type)); |
| 10887 _listener.assertNoErrors(); |
| 10888 } |
| 10889 |
| 10890 void test_visitIntegerLiteral() { |
| 10891 // 42 |
| 10892 Expression node = _resolvedInteger(42); |
| 10893 expect(_analyze(node), same(_typeProvider.intType)); |
| 10894 _listener.assertNoErrors(); |
| 10895 } |
| 10896 |
| 10897 void test_visitIsExpression_negated() { |
| 10898 // a is! String |
| 10899 Expression node = AstFactory.isExpression( |
| 10900 _resolvedString("a"), true, AstFactory.typeName4("String")); |
| 10901 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10902 _listener.assertNoErrors(); |
| 10903 } |
| 10904 |
| 10905 void test_visitIsExpression_notNegated() { |
| 10906 // a is String |
| 10907 Expression node = AstFactory.isExpression( |
| 10908 _resolvedString("a"), false, AstFactory.typeName4("String")); |
| 10909 expect(_analyze(node), same(_typeProvider.boolType)); |
| 10910 _listener.assertNoErrors(); |
| 10911 } |
| 10912 |
| 10913 void test_visitListLiteral_empty() { |
| 10914 // [] |
| 10915 Expression node = AstFactory.listLiteral(); |
| 10916 DartType resultType = _analyze(node); |
| 10917 _assertType2( |
| 10918 _typeProvider.listType |
| 10919 .substitute4(<DartType>[_typeProvider.dynamicType]), |
| 10920 resultType); |
| 10921 _listener.assertNoErrors(); |
| 10922 } |
| 10923 |
| 10924 void test_visitListLiteral_nonEmpty() { |
| 10925 // [0] |
| 10926 Expression node = AstFactory.listLiteral([_resolvedInteger(0)]); |
| 10927 DartType resultType = _analyze(node); |
| 10928 _assertType2( |
| 10929 _typeProvider.listType |
| 10930 .substitute4(<DartType>[_typeProvider.dynamicType]), |
| 10931 resultType); |
| 10932 _listener.assertNoErrors(); |
| 10933 } |
| 10934 |
| 10935 void test_visitMapLiteral_empty() { |
| 10936 // {} |
| 10937 Expression node = AstFactory.mapLiteral2(); |
| 10938 DartType resultType = _analyze(node); |
| 10939 _assertType2( |
| 10940 _typeProvider.mapType.substitute4( |
| 10941 <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]), |
| 10942 resultType); |
| 10943 _listener.assertNoErrors(); |
| 10944 } |
| 10945 |
| 10946 void test_visitMapLiteral_nonEmpty() { |
| 10947 // {"k" : 0} |
| 10948 Expression node = AstFactory |
| 10949 .mapLiteral2([AstFactory.mapLiteralEntry("k", _resolvedInteger(0))]); |
| 10950 DartType resultType = _analyze(node); |
| 10951 _assertType2( |
| 10952 _typeProvider.mapType.substitute4( |
| 10953 <DartType>[_typeProvider.dynamicType, _typeProvider.dynamicType]), |
| 10954 resultType); |
| 10955 _listener.assertNoErrors(); |
| 10956 } |
| 10957 |
| 10958 void test_visitMethodInvocation_then() { |
| 10959 // then() |
| 10960 Expression node = AstFactory.methodInvocation(null, "then"); |
| 10961 _analyze(node); |
| 10962 _listener.assertNoErrors(); |
| 10963 } |
| 10964 |
| 10965 void test_visitNamedExpression() { |
| 10966 // n: a |
| 10967 Expression node = AstFactory.namedExpression2("n", _resolvedString("a")); |
| 10968 expect(_analyze(node), same(_typeProvider.stringType)); |
| 10969 _listener.assertNoErrors(); |
| 10970 } |
| 10971 |
| 10972 void test_visitNullLiteral() { |
| 10973 // null |
| 10974 Expression node = AstFactory.nullLiteral(); |
| 10975 expect(_analyze(node), same(_typeProvider.bottomType)); |
| 10976 _listener.assertNoErrors(); |
| 10977 } |
| 10978 |
| 10979 void test_visitParenthesizedExpression() { |
| 10980 // (0) |
| 10981 Expression node = AstFactory.parenthesizedExpression(_resolvedInteger(0)); |
| 10982 expect(_analyze(node), same(_typeProvider.intType)); |
| 10983 _listener.assertNoErrors(); |
| 10984 } |
| 10985 |
| 10986 void test_visitPostfixExpression_minusMinus() { |
| 10987 // 0-- |
| 10988 PostfixExpression node = AstFactory.postfixExpression( |
| 10989 _resolvedInteger(0), TokenType.MINUS_MINUS); |
| 10990 expect(_analyze(node), same(_typeProvider.intType)); |
| 10991 _listener.assertNoErrors(); |
| 10992 } |
| 10993 |
| 10994 void test_visitPostfixExpression_plusPlus() { |
| 10995 // 0++ |
| 10996 PostfixExpression node = |
| 10997 AstFactory.postfixExpression(_resolvedInteger(0), TokenType.PLUS_PLUS); |
| 10998 expect(_analyze(node), same(_typeProvider.intType)); |
| 10999 _listener.assertNoErrors(); |
| 11000 } |
| 11001 |
| 11002 void test_visitPrefixedIdentifier_getter() { |
| 11003 DartType boolType = _typeProvider.boolType; |
| 11004 PropertyAccessorElementImpl getter = |
| 11005 ElementFactory.getterElement("b", false, boolType); |
| 11006 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); |
| 11007 node.identifier.staticElement = getter; |
| 11008 expect(_analyze(node), same(boolType)); |
| 11009 _listener.assertNoErrors(); |
| 11010 } |
| 11011 |
| 11012 void test_visitPrefixedIdentifier_setter() { |
| 11013 DartType boolType = _typeProvider.boolType; |
| 11014 FieldElementImpl field = |
| 11015 ElementFactory.fieldElement("b", false, false, false, boolType); |
| 11016 PropertyAccessorElement setter = field.setter; |
| 11017 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); |
| 11018 node.identifier.staticElement = setter; |
| 11019 expect(_analyze(node), same(boolType)); |
| 11020 _listener.assertNoErrors(); |
| 11021 } |
| 11022 |
| 11023 void test_visitPrefixedIdentifier_variable() { |
| 11024 VariableElementImpl variable = ElementFactory.localVariableElement2("b"); |
| 11025 variable.type = _typeProvider.boolType; |
| 11026 PrefixedIdentifier node = AstFactory.identifier5("a", "b"); |
| 11027 node.identifier.staticElement = variable; |
| 11028 expect(_analyze(node), same(_typeProvider.boolType)); |
| 11029 _listener.assertNoErrors(); |
| 11030 } |
| 11031 |
| 11032 void test_visitPrefixExpression_bang() { |
| 11033 // !0 |
| 11034 PrefixExpression node = |
| 11035 AstFactory.prefixExpression(TokenType.BANG, _resolvedInteger(0)); |
| 11036 expect(_analyze(node), same(_typeProvider.boolType)); |
| 11037 _listener.assertNoErrors(); |
| 11038 } |
| 11039 |
| 11040 void test_visitPrefixExpression_minus() { |
| 11041 // -0 |
| 11042 PrefixExpression node = |
| 11043 AstFactory.prefixExpression(TokenType.MINUS, _resolvedInteger(0)); |
| 11044 MethodElement minusMethod = getMethod(_typeProvider.numType, "-"); |
| 11045 node.staticElement = minusMethod; |
| 11046 expect(_analyze(node), same(_typeProvider.numType)); |
| 11047 _listener.assertNoErrors(); |
| 11048 } |
| 11049 |
| 11050 void test_visitPrefixExpression_minusMinus() { |
| 11051 // --0 |
| 11052 PrefixExpression node = |
| 11053 AstFactory.prefixExpression(TokenType.MINUS_MINUS, _resolvedInteger(0)); |
| 11054 MethodElement minusMethod = getMethod(_typeProvider.numType, "-"); |
| 11055 node.staticElement = minusMethod; |
| 11056 expect(_analyze(node), same(_typeProvider.intType)); |
| 11057 _listener.assertNoErrors(); |
| 11058 } |
| 11059 |
| 11060 void test_visitPrefixExpression_not() { |
| 11061 // !true |
| 11062 Expression node = AstFactory.prefixExpression( |
| 11063 TokenType.BANG, AstFactory.booleanLiteral(true)); |
| 11064 expect(_analyze(node), same(_typeProvider.boolType)); |
| 11065 _listener.assertNoErrors(); |
| 11066 } |
| 11067 |
| 11068 void test_visitPrefixExpression_plusPlus() { |
| 11069 // ++0 |
| 11070 PrefixExpression node = |
| 11071 AstFactory.prefixExpression(TokenType.PLUS_PLUS, _resolvedInteger(0)); |
| 11072 MethodElement plusMethod = getMethod(_typeProvider.numType, "+"); |
| 11073 node.staticElement = plusMethod; |
| 11074 expect(_analyze(node), same(_typeProvider.intType)); |
| 11075 _listener.assertNoErrors(); |
| 11076 } |
| 11077 |
| 11078 void test_visitPrefixExpression_tilde() { |
| 11079 // ~0 |
| 11080 PrefixExpression node = |
| 11081 AstFactory.prefixExpression(TokenType.TILDE, _resolvedInteger(0)); |
| 11082 MethodElement tildeMethod = getMethod(_typeProvider.intType, "~"); |
| 11083 node.staticElement = tildeMethod; |
| 11084 expect(_analyze(node), same(_typeProvider.intType)); |
| 11085 _listener.assertNoErrors(); |
| 11086 } |
| 11087 |
| 11088 void test_visitPropertyAccess_propagated_getter() { |
| 11089 DartType boolType = _typeProvider.boolType; |
| 11090 PropertyAccessorElementImpl getter = |
| 11091 ElementFactory.getterElement("b", false, boolType); |
| 11092 PropertyAccess node = |
| 11093 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); |
| 11094 node.propertyName.propagatedElement = getter; |
| 11095 expect(_analyze2(node, false), same(boolType)); |
| 11096 _listener.assertNoErrors(); |
| 11097 } |
| 11098 |
| 11099 void test_visitPropertyAccess_propagated_setter() { |
| 11100 DartType boolType = _typeProvider.boolType; |
| 11101 FieldElementImpl field = |
| 11102 ElementFactory.fieldElement("b", false, false, false, boolType); |
| 11103 PropertyAccessorElement setter = field.setter; |
| 11104 PropertyAccess node = |
| 11105 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); |
| 11106 node.propertyName.propagatedElement = setter; |
| 11107 expect(_analyze2(node, false), same(boolType)); |
| 11108 _listener.assertNoErrors(); |
| 11109 } |
| 11110 |
| 11111 void test_visitPropertyAccess_static_getter() { |
| 11112 DartType boolType = _typeProvider.boolType; |
| 11113 PropertyAccessorElementImpl getter = |
| 11114 ElementFactory.getterElement("b", false, boolType); |
| 11115 PropertyAccess node = |
| 11116 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); |
| 11117 node.propertyName.staticElement = getter; |
| 11118 expect(_analyze(node), same(boolType)); |
| 11119 _listener.assertNoErrors(); |
| 11120 } |
| 11121 |
| 11122 void test_visitPropertyAccess_static_setter() { |
| 11123 DartType boolType = _typeProvider.boolType; |
| 11124 FieldElementImpl field = |
| 11125 ElementFactory.fieldElement("b", false, false, false, boolType); |
| 11126 PropertyAccessorElement setter = field.setter; |
| 11127 PropertyAccess node = |
| 11128 AstFactory.propertyAccess2(AstFactory.identifier3("a"), "b"); |
| 11129 node.propertyName.staticElement = setter; |
| 11130 expect(_analyze(node), same(boolType)); |
| 11131 _listener.assertNoErrors(); |
| 11132 } |
| 11133 |
| 11134 void test_visitSimpleIdentifier_dynamic() { |
| 11135 // "dynamic" |
| 11136 SimpleIdentifier identifier = AstFactory.identifier3('dynamic'); |
| 11137 DynamicElementImpl element = DynamicElementImpl.instance; |
| 11138 identifier.staticElement = element; |
| 11139 identifier.staticType = _typeProvider.typeType; |
| 11140 expect(_analyze(identifier), same(_typeProvider.typeType)); |
| 11141 _listener.assertNoErrors(); |
| 11142 } |
| 11143 |
| 11144 void test_visitSimpleStringLiteral() { |
| 11145 // "a" |
| 11146 Expression node = _resolvedString("a"); |
| 11147 expect(_analyze(node), same(_typeProvider.stringType)); |
| 11148 _listener.assertNoErrors(); |
| 11149 } |
| 11150 |
| 11151 void test_visitStringInterpolation() { |
| 11152 // "a${'b'}c" |
| 11153 Expression node = AstFactory.string([ |
| 11154 AstFactory.interpolationString("a", "a"), |
| 11155 AstFactory.interpolationExpression(_resolvedString("b")), |
| 11156 AstFactory.interpolationString("c", "c") |
| 11157 ]); |
| 11158 expect(_analyze(node), same(_typeProvider.stringType)); |
| 11159 _listener.assertNoErrors(); |
| 11160 } |
| 11161 |
| 11162 void test_visitSuperExpression() { |
| 11163 // super |
| 11164 InterfaceType superType = ElementFactory.classElement2("A").type; |
| 11165 InterfaceType thisType = ElementFactory.classElement("B", superType).type; |
| 11166 Expression node = AstFactory.superExpression(); |
| 11167 expect(_analyze3(node, thisType), same(thisType)); |
| 11168 _listener.assertNoErrors(); |
| 11169 } |
| 11170 |
| 11171 void test_visitSymbolLiteral() { |
| 11172 expect(_analyze(AstFactory.symbolLiteral(["a"])), |
| 11173 same(_typeProvider.symbolType)); |
| 11174 } |
| 11175 |
| 11176 void test_visitThisExpression() { |
| 11177 // this |
| 11178 InterfaceType thisType = ElementFactory |
| 11179 .classElement("B", ElementFactory.classElement2("A").type) |
| 11180 .type; |
| 11181 Expression node = AstFactory.thisExpression(); |
| 11182 expect(_analyze3(node, thisType), same(thisType)); |
| 11183 _listener.assertNoErrors(); |
| 11184 } |
| 11185 |
| 11186 void test_visitThrowExpression_withoutValue() { |
| 11187 // throw |
| 11188 Expression node = AstFactory.throwExpression(); |
| 11189 expect(_analyze(node), same(_typeProvider.bottomType)); |
| 11190 _listener.assertNoErrors(); |
| 11191 } |
| 11192 |
| 11193 void test_visitThrowExpression_withValue() { |
| 11194 // throw 0 |
| 11195 Expression node = AstFactory.throwExpression2(_resolvedInteger(0)); |
| 11196 expect(_analyze(node), same(_typeProvider.bottomType)); |
| 11197 _listener.assertNoErrors(); |
| 11198 } |
| 11199 |
| 11200 /** |
| 11201 * Return the type associated with the given expression after the static type
analyzer has |
| 11202 * computed a type for it. |
| 11203 * |
| 11204 * @param node the expression with which the type is associated |
| 11205 * @return the type associated with the expression |
| 11206 */ |
| 11207 DartType _analyze(Expression node) => _analyze4(node, null, true); |
| 11208 |
| 11209 /** |
| 11210 * Return the type associated with the given expression after the static or pr
opagated type |
| 11211 * analyzer has computed a type for it. |
| 11212 * |
| 11213 * @param node the expression with which the type is associated |
| 11214 * @param useStaticType `true` if the static type is being requested, and `fal
se` if |
| 11215 * the propagated type is being requested |
| 11216 * @return the type associated with the expression |
| 11217 */ |
| 11218 DartType _analyze2(Expression node, bool useStaticType) => |
| 11219 _analyze4(node, null, useStaticType); |
| 11220 |
| 11221 /** |
| 11222 * Return the type associated with the given expression after the static type
analyzer has |
| 11223 * computed a type for it. |
| 11224 * |
| 11225 * @param node the expression with which the type is associated |
| 11226 * @param thisType the type of 'this' |
| 11227 * @return the type associated with the expression |
| 11228 */ |
| 11229 DartType _analyze3(Expression node, InterfaceType thisType) => |
| 11230 _analyze4(node, thisType, true); |
| 11231 |
| 11232 /** |
| 11233 * Return the type associated with the given expression after the static type
analyzer has |
| 11234 * computed a type for it. |
| 11235 * |
| 11236 * @param node the expression with which the type is associated |
| 11237 * @param thisType the type of 'this' |
| 11238 * @param useStaticType `true` if the static type is being requested, and `fal
se` if |
| 11239 * the propagated type is being requested |
| 11240 * @return the type associated with the expression |
| 11241 */ |
| 11242 DartType _analyze4( |
| 11243 Expression node, InterfaceType thisType, bool useStaticType) { |
| 11244 try { |
| 11245 _analyzer.thisType = thisType; |
| 11246 } catch (exception) { |
| 11247 throw new IllegalArgumentException( |
| 11248 "Could not set type of 'this'", exception); |
| 11249 } |
| 11250 node.accept(_analyzer); |
| 11251 if (useStaticType) { |
| 11252 return node.staticType; |
| 11253 } else { |
| 11254 return node.propagatedType; |
| 11255 } |
| 11256 } |
| 11257 |
| 11258 /** |
| 11259 * Return the type associated with the given parameter after the static type a
nalyzer has computed |
| 11260 * a type for it. |
| 11261 * |
| 11262 * @param node the parameter with which the type is associated |
| 11263 * @return the type associated with the parameter |
| 11264 */ |
| 11265 DartType _analyze5(FormalParameter node) { |
| 11266 node.accept(_analyzer); |
| 11267 return (node.identifier.staticElement as ParameterElement).type; |
| 11268 } |
| 11269 |
| 11270 /** |
| 11271 * Assert that the actual type is a function type with the expected characteri
stics. |
| 11272 * |
| 11273 * @param expectedReturnType the expected return type of the function |
| 11274 * @param expectedNormalTypes the expected types of the normal parameters |
| 11275 * @param expectedOptionalTypes the expected types of the optional parameters |
| 11276 * @param expectedNamedTypes the expected types of the named parameters |
| 11277 * @param actualType the type being tested |
| 11278 */ |
| 11279 void _assertFunctionType( |
| 11280 DartType expectedReturnType, |
| 11281 List<DartType> expectedNormalTypes, |
| 11282 List<DartType> expectedOptionalTypes, |
| 11283 Map<String, DartType> expectedNamedTypes, |
| 11284 DartType actualType) { |
| 11285 EngineTestCase.assertInstanceOf( |
| 11286 (obj) => obj is FunctionType, FunctionType, actualType); |
| 11287 FunctionType functionType = actualType as FunctionType; |
| 11288 List<DartType> normalTypes = functionType.normalParameterTypes; |
| 11289 if (expectedNormalTypes == null) { |
| 11290 expect(normalTypes, hasLength(0)); |
| 11291 } else { |
| 11292 int expectedCount = expectedNormalTypes.length; |
| 11293 expect(normalTypes, hasLength(expectedCount)); |
| 11294 for (int i = 0; i < expectedCount; i++) { |
| 11295 expect(normalTypes[i], same(expectedNormalTypes[i])); |
| 11296 } |
| 11297 } |
| 11298 List<DartType> optionalTypes = functionType.optionalParameterTypes; |
| 11299 if (expectedOptionalTypes == null) { |
| 11300 expect(optionalTypes, hasLength(0)); |
| 11301 } else { |
| 11302 int expectedCount = expectedOptionalTypes.length; |
| 11303 expect(optionalTypes, hasLength(expectedCount)); |
| 11304 for (int i = 0; i < expectedCount; i++) { |
| 11305 expect(optionalTypes[i], same(expectedOptionalTypes[i])); |
| 11306 } |
| 11307 } |
| 11308 Map<String, DartType> namedTypes = functionType.namedParameterTypes; |
| 11309 if (expectedNamedTypes == null) { |
| 11310 expect(namedTypes, hasLength(0)); |
| 11311 } else { |
| 11312 expect(namedTypes, hasLength(expectedNamedTypes.length)); |
| 11313 expectedNamedTypes.forEach((String name, DartType type) { |
| 11314 expect(namedTypes[name], same(type)); |
| 11315 }); |
| 11316 } |
| 11317 expect(functionType.returnType, equals(expectedReturnType)); |
| 11318 } |
| 11319 |
| 11320 void _assertType( |
| 11321 InterfaceTypeImpl expectedType, InterfaceTypeImpl actualType) { |
| 11322 expect(actualType.displayName, expectedType.displayName); |
| 11323 expect(actualType.element, expectedType.element); |
| 11324 List<DartType> expectedArguments = expectedType.typeArguments; |
| 11325 int length = expectedArguments.length; |
| 11326 List<DartType> actualArguments = actualType.typeArguments; |
| 11327 expect(actualArguments, hasLength(length)); |
| 11328 for (int i = 0; i < length; i++) { |
| 11329 _assertType2(expectedArguments[i], actualArguments[i]); |
| 11330 } |
| 11331 } |
| 11332 |
| 11333 void _assertType2(DartType expectedType, DartType actualType) { |
| 11334 if (expectedType is InterfaceTypeImpl) { |
| 11335 EngineTestCase.assertInstanceOf( |
| 11336 (obj) => obj is InterfaceTypeImpl, InterfaceTypeImpl, actualType); |
| 11337 _assertType(expectedType, actualType as InterfaceTypeImpl); |
| 11338 } |
| 11339 // TODO(brianwilkerson) Compare other kinds of types then make this a shared |
| 11340 // utility method. |
| 11341 } |
| 11342 |
| 11343 /** |
| 11344 * Create the analyzer used by the tests. |
| 11345 * |
| 11346 * @return the analyzer to be used by the tests |
| 11347 */ |
| 11348 StaticTypeAnalyzer _createAnalyzer() { |
| 11349 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 11350 FileBasedSource source = |
| 11351 new FileBasedSource(FileUtilities2.createFile("/lib.dart")); |
| 11352 CompilationUnitElementImpl definingCompilationUnit = |
| 11353 new CompilationUnitElementImpl("lib.dart"); |
| 11354 definingCompilationUnit.librarySource = |
| 11355 definingCompilationUnit.source = source; |
| 11356 LibraryElementImpl definingLibrary = |
| 11357 new LibraryElementImpl.forNode(context, null); |
| 11358 definingLibrary.definingCompilationUnit = definingCompilationUnit; |
| 11359 Library library = new Library(context, _listener, source); |
| 11360 library.libraryElement = definingLibrary; |
| 11361 _visitor = new ResolverVisitor( |
| 11362 library.libraryElement, source, _typeProvider, library.errorListener, |
| 11363 nameScope: library.libraryScope, |
| 11364 inheritanceManager: library.inheritanceManager); |
| 11365 _visitor.overrideManager.enterScope(); |
| 11366 try { |
| 11367 return _visitor.typeAnalyzer; |
| 11368 } catch (exception) { |
| 11369 throw new IllegalArgumentException( |
| 11370 "Could not create analyzer", exception); |
| 11371 } |
| 11372 } |
| 11373 |
| 11374 DartType _flatten(DartType type) => |
| 11375 StaticTypeAnalyzer.flattenFutures(_typeProvider, type); |
| 11376 |
| 11377 /** |
| 11378 * Return a simple identifier that has been resolved to a variable element wit
h the given type. |
| 11379 * |
| 11380 * @param type the type of the variable being represented |
| 11381 * @param variableName the name of the variable |
| 11382 * @return a simple identifier that has been resolved to a variable element wi
th the given type |
| 11383 */ |
| 11384 SimpleIdentifier _propagatedVariable( |
| 11385 InterfaceType type, String variableName) { |
| 11386 SimpleIdentifier identifier = AstFactory.identifier3(variableName); |
| 11387 VariableElementImpl element = |
| 11388 ElementFactory.localVariableElement(identifier); |
| 11389 element.type = type; |
| 11390 identifier.staticType = _typeProvider.dynamicType; |
| 11391 identifier.propagatedElement = element; |
| 11392 identifier.propagatedType = type; |
| 11393 return identifier; |
| 11394 } |
| 11395 |
| 11396 /** |
| 11397 * Return an integer literal that has been resolved to the correct type. |
| 11398 * |
| 11399 * @param value the value of the literal |
| 11400 * @return an integer literal that has been resolved to the correct type |
| 11401 */ |
| 11402 DoubleLiteral _resolvedDouble(double value) { |
| 11403 DoubleLiteral literal = AstFactory.doubleLiteral(value); |
| 11404 literal.staticType = _typeProvider.doubleType; |
| 11405 return literal; |
| 11406 } |
| 11407 |
| 11408 /** |
| 11409 * Create a function expression that has an element associated with it, where
the element has an |
| 11410 * incomplete type associated with it (just like the one |
| 11411 * [ElementBuilder.visitFunctionExpression] would have built if we had |
| 11412 * run it). |
| 11413 * |
| 11414 * @param parameters the parameters to the function |
| 11415 * @param body the body of the function |
| 11416 * @return a resolved function expression |
| 11417 */ |
| 11418 FunctionExpression _resolvedFunctionExpression( |
| 11419 FormalParameterList parameters, FunctionBody body) { |
| 11420 List<ParameterElement> parameterElements = new List<ParameterElement>(); |
| 11421 for (FormalParameter parameter in parameters.parameters) { |
| 11422 ParameterElementImpl element = |
| 11423 new ParameterElementImpl.forNode(parameter.identifier); |
| 11424 element.parameterKind = parameter.kind; |
| 11425 element.type = _typeProvider.dynamicType; |
| 11426 parameter.identifier.staticElement = element; |
| 11427 parameterElements.add(element); |
| 11428 } |
| 11429 FunctionExpression node = AstFactory.functionExpression2(parameters, body); |
| 11430 FunctionElementImpl element = new FunctionElementImpl.forNode(null); |
| 11431 element.parameters = parameterElements; |
| 11432 element.type = new FunctionTypeImpl(element); |
| 11433 node.element = element; |
| 11434 return node; |
| 11435 } |
| 11436 |
| 11437 /** |
| 11438 * Return an integer literal that has been resolved to the correct type. |
| 11439 * |
| 11440 * @param value the value of the literal |
| 11441 * @return an integer literal that has been resolved to the correct type |
| 11442 */ |
| 11443 IntegerLiteral _resolvedInteger(int value) { |
| 11444 IntegerLiteral literal = AstFactory.integer(value); |
| 11445 literal.staticType = _typeProvider.intType; |
| 11446 return literal; |
| 11447 } |
| 11448 |
| 11449 /** |
| 11450 * Return a string literal that has been resolved to the correct type. |
| 11451 * |
| 11452 * @param value the value of the literal |
| 11453 * @return a string literal that has been resolved to the correct type |
| 11454 */ |
| 11455 SimpleStringLiteral _resolvedString(String value) { |
| 11456 SimpleStringLiteral string = AstFactory.string2(value); |
| 11457 string.staticType = _typeProvider.stringType; |
| 11458 return string; |
| 11459 } |
| 11460 |
| 11461 /** |
| 11462 * Return a simple identifier that has been resolved to a variable element wit
h the given type. |
| 11463 * |
| 11464 * @param type the type of the variable being represented |
| 11465 * @param variableName the name of the variable |
| 11466 * @return a simple identifier that has been resolved to a variable element wi
th the given type |
| 11467 */ |
| 11468 SimpleIdentifier _resolvedVariable(InterfaceType type, String variableName) { |
| 11469 SimpleIdentifier identifier = AstFactory.identifier3(variableName); |
| 11470 VariableElementImpl element = |
| 11471 ElementFactory.localVariableElement(identifier); |
| 11472 element.type = type; |
| 11473 identifier.staticElement = element; |
| 11474 identifier.staticType = type; |
| 11475 return identifier; |
| 11476 } |
| 11477 |
| 11478 /** |
| 11479 * Set the type of the given parameter to the given type. |
| 11480 * |
| 11481 * @param parameter the parameter whose type is to be set |
| 11482 * @param type the new type of the given parameter |
| 11483 */ |
| 11484 void _setType(FormalParameter parameter, DartType type) { |
| 11485 SimpleIdentifier identifier = parameter.identifier; |
| 11486 Element element = identifier.staticElement; |
| 11487 if (element is! ParameterElement) { |
| 11488 element = new ParameterElementImpl.forNode(identifier); |
| 11489 identifier.staticElement = element; |
| 11490 } |
| 11491 (element as ParameterElementImpl).type = type; |
| 11492 } |
| 11493 } |
| 11494 |
| 11495 /** |
| 11496 * Instances of the class `StaticTypeVerifier` verify that all of the nodes in a
n AST |
| 11497 * structure that should have a static type associated with them do have a stati
c type. |
| 11498 */ |
| 11499 class StaticTypeVerifier extends GeneralizingAstVisitor<Object> { |
| 11500 /** |
| 11501 * A list containing all of the AST Expression nodes that were not resolved. |
| 11502 */ |
| 11503 List<Expression> _unresolvedExpressions = new List<Expression>(); |
| 11504 |
| 11505 /** |
| 11506 * A list containing all of the AST Expression nodes for which a propagated ty
pe was computed but |
| 11507 * where that type was not more specific than the static type. |
| 11508 */ |
| 11509 List<Expression> _invalidlyPropagatedExpressions = new List<Expression>(); |
| 11510 |
| 11511 /** |
| 11512 * A list containing all of the AST TypeName nodes that were not resolved. |
| 11513 */ |
| 11514 List<TypeName> _unresolvedTypes = new List<TypeName>(); |
| 11515 |
| 11516 /** |
| 11517 * Counter for the number of Expression nodes visited that are resolved. |
| 11518 */ |
| 11519 int _resolvedExpressionCount = 0; |
| 11520 |
| 11521 /** |
| 11522 * Counter for the number of Expression nodes visited that have propagated typ
e information. |
| 11523 */ |
| 11524 int _propagatedExpressionCount = 0; |
| 11525 |
| 11526 /** |
| 11527 * Counter for the number of TypeName nodes visited that are resolved. |
| 11528 */ |
| 11529 int _resolvedTypeCount = 0; |
| 11530 |
| 11531 /** |
| 11532 * Assert that all of the visited nodes have a static type associated with the
m. |
| 11533 */ |
| 11534 void assertResolved() { |
| 11535 if (!_unresolvedExpressions.isEmpty || !_unresolvedTypes.isEmpty) { |
| 11536 StringBuffer buffer = new StringBuffer(); |
| 11537 int unresolvedTypeCount = _unresolvedTypes.length; |
| 11538 if (unresolvedTypeCount > 0) { |
| 11539 buffer.write("Failed to resolve "); |
| 11540 buffer.write(unresolvedTypeCount); |
| 11541 buffer.write(" of "); |
| 11542 buffer.write(_resolvedTypeCount + unresolvedTypeCount); |
| 11543 buffer.writeln(" type names:"); |
| 11544 for (TypeName identifier in _unresolvedTypes) { |
| 11545 buffer.write(" "); |
| 11546 buffer.write(identifier.toString()); |
| 11547 buffer.write(" ("); |
| 11548 buffer.write(_getFileName(identifier)); |
| 11549 buffer.write(" : "); |
| 11550 buffer.write(identifier.offset); |
| 11551 buffer.writeln(")"); |
| 11552 } |
| 11553 } |
| 11554 int unresolvedExpressionCount = _unresolvedExpressions.length; |
| 11555 if (unresolvedExpressionCount > 0) { |
| 11556 buffer.writeln("Failed to resolve "); |
| 11557 buffer.write(unresolvedExpressionCount); |
| 11558 buffer.write(" of "); |
| 11559 buffer.write(_resolvedExpressionCount + unresolvedExpressionCount); |
| 11560 buffer.writeln(" expressions:"); |
| 11561 for (Expression expression in _unresolvedExpressions) { |
| 11562 buffer.write(" "); |
| 11563 buffer.write(expression.toString()); |
| 11564 buffer.write(" ("); |
| 11565 buffer.write(_getFileName(expression)); |
| 11566 buffer.write(" : "); |
| 11567 buffer.write(expression.offset); |
| 11568 buffer.writeln(")"); |
| 11569 } |
| 11570 } |
| 11571 int invalidlyPropagatedExpressionCount = |
| 11572 _invalidlyPropagatedExpressions.length; |
| 11573 if (invalidlyPropagatedExpressionCount > 0) { |
| 11574 buffer.writeln("Incorrectly propagated "); |
| 11575 buffer.write(invalidlyPropagatedExpressionCount); |
| 11576 buffer.write(" of "); |
| 11577 buffer.write(_propagatedExpressionCount); |
| 11578 buffer.writeln(" expressions:"); |
| 11579 for (Expression expression in _invalidlyPropagatedExpressions) { |
| 11580 buffer.write(" "); |
| 11581 buffer.write(expression.toString()); |
| 11582 buffer.write(" ["); |
| 11583 buffer.write(expression.staticType.displayName); |
| 11584 buffer.write(", "); |
| 11585 buffer.write(expression.propagatedType.displayName); |
| 11586 buffer.writeln("]"); |
| 11587 buffer.write(" "); |
| 11588 buffer.write(_getFileName(expression)); |
| 11589 buffer.write(" : "); |
| 11590 buffer.write(expression.offset); |
| 11591 buffer.writeln(")"); |
| 11592 } |
| 11593 } |
| 11594 fail(buffer.toString()); |
| 11595 } |
| 11596 } |
| 11597 |
| 11598 @override |
| 11599 Object visitBreakStatement(BreakStatement node) => null; |
| 11600 |
| 11601 @override |
| 11602 Object visitCommentReference(CommentReference node) => null; |
| 11603 |
| 11604 @override |
| 11605 Object visitContinueStatement(ContinueStatement node) => null; |
| 11606 |
| 11607 @override |
| 11608 Object visitExportDirective(ExportDirective node) => null; |
| 11609 |
| 11610 @override |
| 11611 Object visitExpression(Expression node) { |
| 11612 node.visitChildren(this); |
| 11613 DartType staticType = node.staticType; |
| 11614 if (staticType == null) { |
| 11615 _unresolvedExpressions.add(node); |
| 11616 } else { |
| 11617 _resolvedExpressionCount++; |
| 11618 DartType propagatedType = node.propagatedType; |
| 11619 if (propagatedType != null) { |
| 11620 _propagatedExpressionCount++; |
| 11621 if (!propagatedType.isMoreSpecificThan(staticType)) { |
| 11622 _invalidlyPropagatedExpressions.add(node); |
| 11623 } |
| 11624 } |
| 11625 } |
| 11626 return null; |
| 11627 } |
| 11628 |
| 11629 @override |
| 11630 Object visitImportDirective(ImportDirective node) => null; |
| 11631 |
| 11632 @override |
| 11633 Object visitLabel(Label node) => null; |
| 11634 |
| 11635 @override |
| 11636 Object visitLibraryIdentifier(LibraryIdentifier node) => null; |
| 11637 |
| 11638 @override |
| 11639 Object visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 11640 // In cases where we have a prefixed identifier where the prefix is dynamic, |
| 11641 // we don't want to assert that the node will have a type. |
| 11642 if (node.staticType == null && node.prefix.staticType.isDynamic) { |
| 11643 return null; |
| 11644 } |
| 11645 return super.visitPrefixedIdentifier(node); |
| 11646 } |
| 11647 |
| 11648 @override |
| 11649 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 11650 // In cases where identifiers are being used for something other than an |
| 11651 // expressions, then they can be ignored. |
| 11652 AstNode parent = node.parent; |
| 11653 if (parent is MethodInvocation && identical(node, parent.methodName)) { |
| 11654 return null; |
| 11655 } else if (parent is RedirectingConstructorInvocation && |
| 11656 identical(node, parent.constructorName)) { |
| 11657 return null; |
| 11658 } else if (parent is SuperConstructorInvocation && |
| 11659 identical(node, parent.constructorName)) { |
| 11660 return null; |
| 11661 } else if (parent is ConstructorName && identical(node, parent.name)) { |
| 11662 return null; |
| 11663 } else if (parent is ConstructorFieldInitializer && |
| 11664 identical(node, parent.fieldName)) { |
| 11665 return null; |
| 11666 } else if (node.staticElement is PrefixElement) { |
| 11667 // Prefixes don't have a type. |
| 11668 return null; |
| 11669 } |
| 11670 return super.visitSimpleIdentifier(node); |
| 11671 } |
| 11672 |
| 11673 @override |
| 11674 Object visitTypeName(TypeName node) { |
| 11675 // Note: do not visit children from this node, the child SimpleIdentifier in |
| 11676 // TypeName (i.e. "String") does not have a static type defined. |
| 11677 if (node.type == null) { |
| 11678 _unresolvedTypes.add(node); |
| 11679 } else { |
| 11680 _resolvedTypeCount++; |
| 11681 } |
| 11682 return null; |
| 11683 } |
| 11684 |
| 11685 String _getFileName(AstNode node) { |
| 11686 // TODO (jwren) there are two copies of this method, one here and one in |
| 11687 // ResolutionVerifier, they should be resolved into a single method |
| 11688 if (node != null) { |
| 11689 AstNode root = node.root; |
| 11690 if (root is CompilationUnit) { |
| 11691 CompilationUnit rootCU = root; |
| 11692 if (rootCU.element != null) { |
| 11693 return rootCU.element.source.fullName; |
| 11694 } else { |
| 11695 return "<unknown file- CompilationUnit.getElement() returned null>"; |
| 11696 } |
| 11697 } else { |
| 11698 return "<unknown file- CompilationUnit.getRoot() is not a CompilationUni
t>"; |
| 11699 } |
| 11700 } |
| 11701 return "<unknown file- ASTNode is null>"; |
| 11702 } |
| 11703 } |
| 11704 |
| 11705 /** |
| 11706 * The class `StrictModeTest` contains tests to ensure that the correct errors a
nd warnings |
| 11707 * are reported when the analysis engine is run in strict mode. |
| 11708 */ |
| 11709 @reflectiveTest |
| 11710 class StrictModeTest extends ResolverTestCase { |
| 11711 void fail_for() { |
| 11712 Source source = addSource(r''' |
| 11713 int f(List<int> list) { |
| 11714 num sum = 0; |
| 11715 for (num i = 0; i < list.length; i++) { |
| 11716 sum += list[i]; |
| 11717 } |
| 11718 }'''); |
| 11719 computeLibrarySourceErrors(source); |
| 11720 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11721 } |
| 11722 |
| 11723 @override |
| 11724 void setUp() { |
| 11725 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 11726 options.hint = false; |
| 11727 resetWithOptions(options); |
| 11728 } |
| 11729 |
| 11730 void test_assert_is() { |
| 11731 Source source = addSource(r''' |
| 11732 int f(num n) { |
| 11733 assert (n is int); |
| 11734 return n & 0x0F; |
| 11735 }'''); |
| 11736 computeLibrarySourceErrors(source); |
| 11737 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11738 } |
| 11739 |
| 11740 void test_conditional_and_is() { |
| 11741 Source source = addSource(r''' |
| 11742 int f(num n) { |
| 11743 return (n is int && n > 0) ? n & 0x0F : 0; |
| 11744 }'''); |
| 11745 computeLibrarySourceErrors(source); |
| 11746 assertNoErrors(source); |
| 11747 } |
| 11748 |
| 11749 void test_conditional_is() { |
| 11750 Source source = addSource(r''' |
| 11751 int f(num n) { |
| 11752 return (n is int) ? n & 0x0F : 0; |
| 11753 }'''); |
| 11754 computeLibrarySourceErrors(source); |
| 11755 assertNoErrors(source); |
| 11756 } |
| 11757 |
| 11758 void test_conditional_isNot() { |
| 11759 Source source = addSource(r''' |
| 11760 int f(num n) { |
| 11761 return (n is! int) ? 0 : n & 0x0F; |
| 11762 }'''); |
| 11763 computeLibrarySourceErrors(source); |
| 11764 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11765 } |
| 11766 |
| 11767 void test_conditional_or_is() { |
| 11768 Source source = addSource(r''' |
| 11769 int f(num n) { |
| 11770 return (n is! int || n < 0) ? 0 : n & 0x0F; |
| 11771 }'''); |
| 11772 computeLibrarySourceErrors(source); |
| 11773 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11774 } |
| 11775 |
| 11776 void test_forEach() { |
| 11777 Source source = addSource(r''' |
| 11778 int f(List<int> list) { |
| 11779 num sum = 0; |
| 11780 for (num n in list) { |
| 11781 sum += n & 0x0F; |
| 11782 } |
| 11783 }'''); |
| 11784 computeLibrarySourceErrors(source); |
| 11785 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11786 } |
| 11787 |
| 11788 void test_if_and_is() { |
| 11789 Source source = addSource(r''' |
| 11790 int f(num n) { |
| 11791 if (n is int && n > 0) { |
| 11792 return n & 0x0F; |
| 11793 } |
| 11794 return 0; |
| 11795 }'''); |
| 11796 computeLibrarySourceErrors(source); |
| 11797 assertNoErrors(source); |
| 11798 } |
| 11799 |
| 11800 void test_if_is() { |
| 11801 Source source = addSource(r''' |
| 11802 int f(num n) { |
| 11803 if (n is int) { |
| 11804 return n & 0x0F; |
| 11805 } |
| 11806 return 0; |
| 11807 }'''); |
| 11808 computeLibrarySourceErrors(source); |
| 11809 assertNoErrors(source); |
| 11810 } |
| 11811 |
| 11812 void test_if_isNot() { |
| 11813 Source source = addSource(r''' |
| 11814 int f(num n) { |
| 11815 if (n is! int) { |
| 11816 return 0; |
| 11817 } else { |
| 11818 return n & 0x0F; |
| 11819 } |
| 11820 }'''); |
| 11821 computeLibrarySourceErrors(source); |
| 11822 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11823 } |
| 11824 |
| 11825 void test_if_isNot_abrupt() { |
| 11826 Source source = addSource(r''' |
| 11827 int f(num n) { |
| 11828 if (n is! int) { |
| 11829 return 0; |
| 11830 } |
| 11831 return n & 0x0F; |
| 11832 }'''); |
| 11833 computeLibrarySourceErrors(source); |
| 11834 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11835 } |
| 11836 |
| 11837 void test_if_or_is() { |
| 11838 Source source = addSource(r''' |
| 11839 int f(num n) { |
| 11840 if (n is! int || n < 0) { |
| 11841 return 0; |
| 11842 } else { |
| 11843 return n & 0x0F; |
| 11844 } |
| 11845 }'''); |
| 11846 computeLibrarySourceErrors(source); |
| 11847 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11848 } |
| 11849 |
| 11850 void test_localVar() { |
| 11851 Source source = addSource(r''' |
| 11852 int f() { |
| 11853 num n = 1234; |
| 11854 return n & 0x0F; |
| 11855 }'''); |
| 11856 computeLibrarySourceErrors(source); |
| 11857 assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); |
| 11858 } |
| 11859 } |
| 11860 |
| 11861 @reflectiveTest |
| 11862 class SubtypeManagerTest extends EngineTestCase { |
| 11863 /** |
| 11864 * The inheritance manager being tested. |
| 11865 */ |
| 11866 SubtypeManager _subtypeManager; |
| 11867 |
| 11868 /** |
| 11869 * The compilation unit element containing all of the types setup in each test
. |
| 11870 */ |
| 11871 CompilationUnitElementImpl _definingCompilationUnit; |
| 11872 |
| 11873 @override |
| 11874 void setUp() { |
| 11875 super.setUp(); |
| 11876 AnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 11877 FileBasedSource source = |
| 11878 new FileBasedSource(FileUtilities2.createFile("/test.dart")); |
| 11879 _definingCompilationUnit = new CompilationUnitElementImpl("test.dart"); |
| 11880 _definingCompilationUnit.librarySource = |
| 11881 _definingCompilationUnit.source = source; |
| 11882 LibraryElementImpl definingLibrary = |
| 11883 ElementFactory.library(context, "test"); |
| 11884 definingLibrary.definingCompilationUnit = _definingCompilationUnit; |
| 11885 _subtypeManager = new SubtypeManager(); |
| 11886 } |
| 11887 |
| 11888 void test_computeAllSubtypes_infiniteLoop() { |
| 11889 // |
| 11890 // class A extends B |
| 11891 // class B extends A |
| 11892 // |
| 11893 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 11894 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 11895 classA.supertype = classB.type; |
| 11896 _definingCompilationUnit.types = <ClassElement>[classA, classB]; |
| 11897 HashSet<ClassElement> subtypesOfA = |
| 11898 _subtypeManager.computeAllSubtypes(classA); |
| 11899 List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA); |
| 11900 expect(subtypesOfA, hasLength(2)); |
| 11901 expect(arraySubtypesOfA, unorderedEquals([classA, classB])); |
| 11902 } |
| 11903 |
| 11904 void test_computeAllSubtypes_manyRecursiveSubtypes() { |
| 11905 // |
| 11906 // class A |
| 11907 // class B extends A |
| 11908 // class C extends B |
| 11909 // class D extends B |
| 11910 // class E extends B |
| 11911 // |
| 11912 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 11913 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 11914 ClassElementImpl classC = ElementFactory.classElement("C", classB.type); |
| 11915 ClassElementImpl classD = ElementFactory.classElement("D", classB.type); |
| 11916 ClassElementImpl classE = ElementFactory.classElement("E", classB.type); |
| 11917 _definingCompilationUnit.types = <ClassElement>[ |
| 11918 classA, |
| 11919 classB, |
| 11920 classC, |
| 11921 classD, |
| 11922 classE |
| 11923 ]; |
| 11924 HashSet<ClassElement> subtypesOfA = |
| 11925 _subtypeManager.computeAllSubtypes(classA); |
| 11926 List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA); |
| 11927 HashSet<ClassElement> subtypesOfB = |
| 11928 _subtypeManager.computeAllSubtypes(classB); |
| 11929 List<ClassElement> arraySubtypesOfB = new List.from(subtypesOfB); |
| 11930 expect(subtypesOfA, hasLength(4)); |
| 11931 expect(arraySubtypesOfA, unorderedEquals([classB, classC, classD, classE])); |
| 11932 expect(subtypesOfB, hasLength(3)); |
| 11933 expect(arraySubtypesOfB, unorderedEquals([classC, classD, classE])); |
| 11934 } |
| 11935 |
| 11936 void test_computeAllSubtypes_noSubtypes() { |
| 11937 // |
| 11938 // class A |
| 11939 // |
| 11940 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 11941 _definingCompilationUnit.types = <ClassElement>[classA]; |
| 11942 HashSet<ClassElement> subtypesOfA = |
| 11943 _subtypeManager.computeAllSubtypes(classA); |
| 11944 expect(subtypesOfA, hasLength(0)); |
| 11945 } |
| 11946 |
| 11947 void test_computeAllSubtypes_oneSubtype() { |
| 11948 // |
| 11949 // class A |
| 11950 // class B extends A |
| 11951 // |
| 11952 ClassElementImpl classA = ElementFactory.classElement2("A"); |
| 11953 ClassElementImpl classB = ElementFactory.classElement("B", classA.type); |
| 11954 _definingCompilationUnit.types = <ClassElement>[classA, classB]; |
| 11955 HashSet<ClassElement> subtypesOfA = |
| 11956 _subtypeManager.computeAllSubtypes(classA); |
| 11957 List<ClassElement> arraySubtypesOfA = new List.from(subtypesOfA); |
| 11958 expect(subtypesOfA, hasLength(1)); |
| 11959 expect(arraySubtypesOfA, unorderedEquals([classB])); |
| 11960 } |
| 11961 } |
| 11962 |
| 11963 @reflectiveTest |
| 11964 class TypeOverrideManagerTest extends EngineTestCase { |
| 11965 void test_exitScope_noScopes() { |
| 11966 TypeOverrideManager manager = new TypeOverrideManager(); |
| 11967 try { |
| 11968 manager.exitScope(); |
| 11969 fail("Expected IllegalStateException"); |
| 11970 } on IllegalStateException { |
| 11971 // Expected |
| 11972 } |
| 11973 } |
| 11974 |
| 11975 void test_exitScope_oneScope() { |
| 11976 TypeOverrideManager manager = new TypeOverrideManager(); |
| 11977 manager.enterScope(); |
| 11978 manager.exitScope(); |
| 11979 try { |
| 11980 manager.exitScope(); |
| 11981 fail("Expected IllegalStateException"); |
| 11982 } on IllegalStateException { |
| 11983 // Expected |
| 11984 } |
| 11985 } |
| 11986 |
| 11987 void test_exitScope_twoScopes() { |
| 11988 TypeOverrideManager manager = new TypeOverrideManager(); |
| 11989 manager.enterScope(); |
| 11990 manager.exitScope(); |
| 11991 manager.enterScope(); |
| 11992 manager.exitScope(); |
| 11993 try { |
| 11994 manager.exitScope(); |
| 11995 fail("Expected IllegalStateException"); |
| 11996 } on IllegalStateException { |
| 11997 // Expected |
| 11998 } |
| 11999 } |
| 12000 |
| 12001 void test_getType_enclosedOverride() { |
| 12002 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12003 LocalVariableElementImpl element = |
| 12004 ElementFactory.localVariableElement2("v"); |
| 12005 InterfaceType type = ElementFactory.classElement2("C").type; |
| 12006 manager.enterScope(); |
| 12007 manager.setType(element, type); |
| 12008 manager.enterScope(); |
| 12009 expect(manager.getType(element), same(type)); |
| 12010 } |
| 12011 |
| 12012 void test_getType_immediateOverride() { |
| 12013 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12014 LocalVariableElementImpl element = |
| 12015 ElementFactory.localVariableElement2("v"); |
| 12016 InterfaceType type = ElementFactory.classElement2("C").type; |
| 12017 manager.enterScope(); |
| 12018 manager.setType(element, type); |
| 12019 expect(manager.getType(element), same(type)); |
| 12020 } |
| 12021 |
| 12022 void test_getType_noOverride() { |
| 12023 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12024 manager.enterScope(); |
| 12025 expect(manager.getType(ElementFactory.localVariableElement2("v")), isNull); |
| 12026 } |
| 12027 |
| 12028 void test_getType_noScope() { |
| 12029 TypeOverrideManager manager = new TypeOverrideManager(); |
| 12030 expect(manager.getType(ElementFactory.localVariableElement2("v")), isNull); |
| 12031 } |
| 12032 } |
| 12033 |
| 12034 @reflectiveTest |
| 12035 class TypePropagationTest extends ResolverTestCase { |
| 12036 void fail_finalPropertyInducingVariable_classMember_instance() { |
| 12037 addNamedSource( |
| 12038 "/lib.dart", |
| 12039 r''' |
| 12040 class A { |
| 12041 final v = 0; |
| 12042 }'''); |
| 12043 String code = r''' |
| 12044 import 'lib.dart'; |
| 12045 f(A a) { |
| 12046 return a.v; // marker |
| 12047 }'''; |
| 12048 _assertTypeOfMarkedExpression( |
| 12049 code, typeProvider.dynamicType, typeProvider.intType); |
| 12050 } |
| 12051 |
| 12052 void fail_finalPropertyInducingVariable_classMember_instance_inherited() { |
| 12053 addNamedSource( |
| 12054 "/lib.dart", |
| 12055 r''' |
| 12056 class A { |
| 12057 final v = 0; |
| 12058 }'''); |
| 12059 String code = r''' |
| 12060 import 'lib.dart'; |
| 12061 class B extends A { |
| 12062 m() { |
| 12063 return v; // marker |
| 12064 } |
| 12065 }'''; |
| 12066 _assertTypeOfMarkedExpression( |
| 12067 code, typeProvider.dynamicType, typeProvider.intType); |
| 12068 } |
| 12069 |
| 12070 void fail_finalPropertyInducingVariable_classMember_instance_propagatedTarget(
) { |
| 12071 addNamedSource( |
| 12072 "/lib.dart", |
| 12073 r''' |
| 12074 class A { |
| 12075 final v = 0; |
| 12076 }'''); |
| 12077 String code = r''' |
| 12078 import 'lib.dart'; |
| 12079 f(p) { |
| 12080 if (p is A) { |
| 12081 return p.v; // marker |
| 12082 } |
| 12083 }'''; |
| 12084 _assertTypeOfMarkedExpression( |
| 12085 code, typeProvider.dynamicType, typeProvider.intType); |
| 12086 } |
| 12087 |
| 12088 void fail_finalPropertyInducingVariable_classMember_static() { |
| 12089 addNamedSource( |
| 12090 "/lib.dart", |
| 12091 r''' |
| 12092 class A { |
| 12093 static final V = 0; |
| 12094 }'''); |
| 12095 String code = r''' |
| 12096 import 'lib.dart'; |
| 12097 f() { |
| 12098 return A.V; // marker |
| 12099 }'''; |
| 12100 _assertTypeOfMarkedExpression( |
| 12101 code, typeProvider.dynamicType, typeProvider.intType); |
| 12102 } |
| 12103 |
| 12104 void fail_finalPropertyInducingVariable_topLevelVaraible_prefixed() { |
| 12105 addNamedSource("/lib.dart", "final V = 0;"); |
| 12106 String code = r''' |
| 12107 import 'lib.dart' as p; |
| 12108 f() { |
| 12109 var v2 = p.V; // marker prefixed |
| 12110 }'''; |
| 12111 _assertTypeOfMarkedExpression( |
| 12112 code, typeProvider.dynamicType, typeProvider.intType); |
| 12113 } |
| 12114 |
| 12115 void fail_finalPropertyInducingVariable_topLevelVaraible_simple() { |
| 12116 addNamedSource("/lib.dart", "final V = 0;"); |
| 12117 String code = r''' |
| 12118 import 'lib.dart'; |
| 12119 f() { |
| 12120 return V; // marker simple |
| 12121 }'''; |
| 12122 _assertTypeOfMarkedExpression( |
| 12123 code, typeProvider.dynamicType, typeProvider.intType); |
| 12124 } |
| 12125 |
| 12126 void fail_mergePropagatedTypesAtJoinPoint_1() { |
| 12127 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12128 _assertTypeOfMarkedExpression( |
| 12129 r''' |
| 12130 f1(x) { |
| 12131 var y = []; |
| 12132 if (x) { |
| 12133 y = 0; |
| 12134 } else { |
| 12135 y = ''; |
| 12136 } |
| 12137 // Propagated type is [List] here: incorrect. |
| 12138 // Best we can do is [Object]? |
| 12139 return y; // marker |
| 12140 }''', |
| 12141 null, |
| 12142 typeProvider.dynamicType); |
| 12143 } |
| 12144 |
| 12145 void fail_mergePropagatedTypesAtJoinPoint_2() { |
| 12146 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12147 _assertTypeOfMarkedExpression( |
| 12148 r''' |
| 12149 f2(x) { |
| 12150 var y = []; |
| 12151 if (x) { |
| 12152 y = 0; |
| 12153 } else { |
| 12154 } |
| 12155 // Propagated type is [List] here: incorrect. |
| 12156 // Best we can do is [Object]? |
| 12157 return y; // marker |
| 12158 }''', |
| 12159 null, |
| 12160 typeProvider.dynamicType); |
| 12161 } |
| 12162 |
| 12163 void fail_mergePropagatedTypesAtJoinPoint_3() { |
| 12164 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12165 _assertTypeOfMarkedExpression( |
| 12166 r''' |
| 12167 f4(x) { |
| 12168 var y = []; |
| 12169 if (x) { |
| 12170 y = 0; |
| 12171 } else { |
| 12172 y = 1.5; |
| 12173 } |
| 12174 // Propagated type is [List] here: incorrect. |
| 12175 // A correct answer is the least upper bound of [int] and [double], |
| 12176 // i.e. [num]. |
| 12177 return y; // marker |
| 12178 }''', |
| 12179 null, |
| 12180 typeProvider.numType); |
| 12181 } |
| 12182 |
| 12183 void fail_mergePropagatedTypesAtJoinPoint_5() { |
| 12184 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12185 _assertTypeOfMarkedExpression( |
| 12186 r''' |
| 12187 f6(x,y) { |
| 12188 var z = []; |
| 12189 if (x || (z = y) < 0) { |
| 12190 } else { |
| 12191 z = 0; |
| 12192 } |
| 12193 // Propagated type is [List] here: incorrect. |
| 12194 // Best we can do is [Object]? |
| 12195 return z; // marker |
| 12196 }''', |
| 12197 null, |
| 12198 typeProvider.dynamicType); |
| 12199 } |
| 12200 |
| 12201 void fail_mergePropagatedTypesAtJoinPoint_7() { |
| 12202 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12203 // |
| 12204 // In general [continue]s are unsafe for the purposes of |
| 12205 // [isAbruptTerminationStatement]. |
| 12206 // |
| 12207 // This is like example 6, but less tricky: the code in the branch that |
| 12208 // [continue]s is in effect after the [if]. |
| 12209 String code = r''' |
| 12210 f() { |
| 12211 var x = 0; |
| 12212 var c = false; |
| 12213 var d = true; |
| 12214 while (d) { |
| 12215 if (c) { |
| 12216 d = false; |
| 12217 } else { |
| 12218 x = ''; |
| 12219 c = true; |
| 12220 continue; |
| 12221 } |
| 12222 x; // marker |
| 12223 } |
| 12224 }'''; |
| 12225 DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType; |
| 12226 expect(typeProvider.intType.isSubtypeOf(t), isTrue); |
| 12227 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); |
| 12228 } |
| 12229 |
| 12230 void fail_mergePropagatedTypesAtJoinPoint_8() { |
| 12231 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 12232 // |
| 12233 // In nested loops [breaks]s are unsafe for the purposes of |
| 12234 // [isAbruptTerminationStatement]. |
| 12235 // |
| 12236 // This is a combination of 6 and 7: we use an unlabeled [break] |
| 12237 // like a continue for the outer loop / like a labeled [break] to |
| 12238 // jump just above the [if]. |
| 12239 String code = r''' |
| 12240 f() { |
| 12241 var x = 0; |
| 12242 var c = false; |
| 12243 var d = true; |
| 12244 while (d) { |
| 12245 while (d) { |
| 12246 if (c) { |
| 12247 d = false; |
| 12248 } else { |
| 12249 x = ''; |
| 12250 c = true; |
| 12251 break; |
| 12252 } |
| 12253 x; // marker |
| 12254 } |
| 12255 } |
| 12256 }'''; |
| 12257 DartType t = _findMarkedIdentifier(code, "; // marker").propagatedType; |
| 12258 expect(typeProvider.intType.isSubtypeOf(t), isTrue); |
| 12259 expect(typeProvider.stringType.isSubtypeOf(t), isTrue); |
| 12260 } |
| 12261 |
| 12262 void fail_propagatedReturnType_functionExpression() { |
| 12263 // TODO(scheglov) disabled because we don't resolve function expression |
| 12264 String code = r''' |
| 12265 main() { |
| 12266 var v = (() {return 42;})(); |
| 12267 }'''; |
| 12268 _assertPropagatedAssignedType( |
| 12269 code, typeProvider.dynamicType, typeProvider.intType); |
| 12270 } |
| 12271 |
| 12272 void test_as() { |
| 12273 Source source = addSource(r''' |
| 12274 class A { |
| 12275 bool get g => true; |
| 12276 } |
| 12277 A f(var p) { |
| 12278 if ((p as A).g) { |
| 12279 return p; |
| 12280 } else { |
| 12281 return null; |
| 12282 } |
| 12283 }'''); |
| 12284 LibraryElement library = resolve2(source); |
| 12285 assertNoErrors(source); |
| 12286 verify([source]); |
| 12287 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12288 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12289 InterfaceType typeA = classA.element.type; |
| 12290 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12291 BlockFunctionBody body = |
| 12292 function.functionExpression.body as BlockFunctionBody; |
| 12293 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 12294 ReturnStatement statement = |
| 12295 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 12296 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12297 expect(variableName.propagatedType, same(typeA)); |
| 12298 } |
| 12299 |
| 12300 void test_assert() { |
| 12301 Source source = addSource(r''' |
| 12302 class A {} |
| 12303 A f(var p) { |
| 12304 assert (p is A); |
| 12305 return p; |
| 12306 }'''); |
| 12307 LibraryElement library = resolve2(source); |
| 12308 assertNoErrors(source); |
| 12309 verify([source]); |
| 12310 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12311 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12312 InterfaceType typeA = classA.element.type; |
| 12313 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12314 BlockFunctionBody body = |
| 12315 function.functionExpression.body as BlockFunctionBody; |
| 12316 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 12317 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12318 expect(variableName.propagatedType, same(typeA)); |
| 12319 } |
| 12320 |
| 12321 void test_assignment() { |
| 12322 Source source = addSource(r''' |
| 12323 f() { |
| 12324 var v; |
| 12325 v = 0; |
| 12326 return v; |
| 12327 }'''); |
| 12328 LibraryElement library = resolve2(source); |
| 12329 assertNoErrors(source); |
| 12330 verify([source]); |
| 12331 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12332 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 12333 BlockFunctionBody body = |
| 12334 function.functionExpression.body as BlockFunctionBody; |
| 12335 ReturnStatement statement = body.block.statements[2] as ReturnStatement; |
| 12336 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12337 expect(variableName.propagatedType, same(typeProvider.intType)); |
| 12338 } |
| 12339 |
| 12340 void test_assignment_afterInitializer() { |
| 12341 Source source = addSource(r''' |
| 12342 f() { |
| 12343 var v = 0; |
| 12344 v = 1.0; |
| 12345 return v; |
| 12346 }'''); |
| 12347 LibraryElement library = resolve2(source); |
| 12348 assertNoErrors(source); |
| 12349 verify([source]); |
| 12350 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12351 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 12352 BlockFunctionBody body = |
| 12353 function.functionExpression.body as BlockFunctionBody; |
| 12354 ReturnStatement statement = body.block.statements[2] as ReturnStatement; |
| 12355 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12356 expect(variableName.propagatedType, same(typeProvider.doubleType)); |
| 12357 } |
| 12358 |
| 12359 void test_assignment_null() { |
| 12360 String code = r''' |
| 12361 main() { |
| 12362 int v; // declare |
| 12363 v = null; |
| 12364 return v; // return |
| 12365 }'''; |
| 12366 CompilationUnit unit; |
| 12367 { |
| 12368 Source source = addSource(code); |
| 12369 LibraryElement library = resolve2(source); |
| 12370 assertNoErrors(source); |
| 12371 verify([source]); |
| 12372 unit = resolveCompilationUnit(source, library); |
| 12373 } |
| 12374 { |
| 12375 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12376 unit, code, "v; // declare", (node) => node is SimpleIdentifier); |
| 12377 expect(identifier.staticType, same(typeProvider.intType)); |
| 12378 expect(identifier.propagatedType, same(null)); |
| 12379 } |
| 12380 { |
| 12381 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12382 unit, code, "v = null;", (node) => node is SimpleIdentifier); |
| 12383 expect(identifier.staticType, same(typeProvider.intType)); |
| 12384 expect(identifier.propagatedType, same(null)); |
| 12385 } |
| 12386 { |
| 12387 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12388 unit, code, "v; // return", (node) => node is SimpleIdentifier); |
| 12389 expect(identifier.staticType, same(typeProvider.intType)); |
| 12390 expect(identifier.propagatedType, same(null)); |
| 12391 } |
| 12392 } |
| 12393 |
| 12394 void test_CanvasElement_getContext() { |
| 12395 String code = r''' |
| 12396 import 'dart:html'; |
| 12397 main(CanvasElement canvas) { |
| 12398 var context = canvas.getContext('2d'); |
| 12399 }'''; |
| 12400 Source source = addSource(code); |
| 12401 LibraryElement library = resolve2(source); |
| 12402 assertNoErrors(source); |
| 12403 verify([source]); |
| 12404 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12405 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12406 unit, code, "context", (node) => node is SimpleIdentifier); |
| 12407 expect(identifier.propagatedType.name, "CanvasRenderingContext2D"); |
| 12408 } |
| 12409 |
| 12410 void test_forEach() { |
| 12411 String code = r''' |
| 12412 main() { |
| 12413 var list = <String> []; |
| 12414 for (var e in list) { |
| 12415 e; |
| 12416 } |
| 12417 }'''; |
| 12418 Source source = addSource(code); |
| 12419 LibraryElement library = resolve2(source); |
| 12420 assertNoErrors(source); |
| 12421 verify([source]); |
| 12422 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12423 InterfaceType stringType = typeProvider.stringType; |
| 12424 // in the declaration |
| 12425 { |
| 12426 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12427 unit, code, "e in", (node) => node is SimpleIdentifier); |
| 12428 expect(identifier.propagatedType, same(stringType)); |
| 12429 } |
| 12430 // in the loop body |
| 12431 { |
| 12432 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12433 unit, code, "e;", (node) => node is SimpleIdentifier); |
| 12434 expect(identifier.propagatedType, same(stringType)); |
| 12435 } |
| 12436 } |
| 12437 |
| 12438 void test_forEach_async() { |
| 12439 String code = r''' |
| 12440 import 'dart:async'; |
| 12441 f(Stream<String> stream) async { |
| 12442 await for (var e in stream) { |
| 12443 e; |
| 12444 } |
| 12445 }'''; |
| 12446 Source source = addSource(code); |
| 12447 LibraryElement library = resolve2(source); |
| 12448 assertNoErrors(source); |
| 12449 verify([source]); |
| 12450 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12451 InterfaceType stringType = typeProvider.stringType; |
| 12452 // in the declaration |
| 12453 { |
| 12454 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12455 unit, code, "e in", (node) => node is SimpleIdentifier); |
| 12456 expect(identifier.propagatedType, same(stringType)); |
| 12457 } |
| 12458 // in the loop body |
| 12459 { |
| 12460 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12461 unit, code, "e;", (node) => node is SimpleIdentifier); |
| 12462 expect(identifier.propagatedType, same(stringType)); |
| 12463 } |
| 12464 } |
| 12465 |
| 12466 void test_functionExpression_asInvocationArgument() { |
| 12467 String code = r''' |
| 12468 class MyMap<K, V> { |
| 12469 forEach(f(K key, V value)) {} |
| 12470 } |
| 12471 f(MyMap<int, String> m) { |
| 12472 m.forEach((k, v) { |
| 12473 k; |
| 12474 v; |
| 12475 }); |
| 12476 }'''; |
| 12477 Source source = addSource(code); |
| 12478 LibraryElement library = resolve2(source); |
| 12479 assertNoErrors(source); |
| 12480 verify([source]); |
| 12481 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12482 // k |
| 12483 DartType intType = typeProvider.intType; |
| 12484 FormalParameter kParameter = EngineTestCase.findNode( |
| 12485 unit, code, "k, ", (node) => node is SimpleFormalParameter); |
| 12486 expect(kParameter.identifier.propagatedType, same(intType)); |
| 12487 SimpleIdentifier kIdentifier = EngineTestCase.findNode( |
| 12488 unit, code, "k;", (node) => node is SimpleIdentifier); |
| 12489 expect(kIdentifier.propagatedType, same(intType)); |
| 12490 expect(kIdentifier.staticType, same(typeProvider.dynamicType)); |
| 12491 // v |
| 12492 DartType stringType = typeProvider.stringType; |
| 12493 FormalParameter vParameter = EngineTestCase.findNode( |
| 12494 unit, code, "v)", (node) => node is SimpleFormalParameter); |
| 12495 expect(vParameter.identifier.propagatedType, same(stringType)); |
| 12496 SimpleIdentifier vIdentifier = EngineTestCase.findNode( |
| 12497 unit, code, "v;", (node) => node is SimpleIdentifier); |
| 12498 expect(vIdentifier.propagatedType, same(stringType)); |
| 12499 expect(vIdentifier.staticType, same(typeProvider.dynamicType)); |
| 12500 } |
| 12501 |
| 12502 void test_functionExpression_asInvocationArgument_fromInferredInvocation() { |
| 12503 String code = r''' |
| 12504 class MyMap<K, V> { |
| 12505 forEach(f(K key, V value)) {} |
| 12506 } |
| 12507 f(MyMap<int, String> m) { |
| 12508 var m2 = m; |
| 12509 m2.forEach((k, v) {}); |
| 12510 }'''; |
| 12511 Source source = addSource(code); |
| 12512 LibraryElement library = resolve2(source); |
| 12513 assertNoErrors(source); |
| 12514 verify([source]); |
| 12515 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12516 // k |
| 12517 DartType intType = typeProvider.intType; |
| 12518 FormalParameter kParameter = EngineTestCase.findNode( |
| 12519 unit, code, "k, ", (node) => node is SimpleFormalParameter); |
| 12520 expect(kParameter.identifier.propagatedType, same(intType)); |
| 12521 // v |
| 12522 DartType stringType = typeProvider.stringType; |
| 12523 FormalParameter vParameter = EngineTestCase.findNode( |
| 12524 unit, code, "v)", (node) => node is SimpleFormalParameter); |
| 12525 expect(vParameter.identifier.propagatedType, same(stringType)); |
| 12526 } |
| 12527 |
| 12528 void test_functionExpression_asInvocationArgument_functionExpressionInvocation
() { |
| 12529 String code = r''' |
| 12530 main() { |
| 12531 (f(String value)) {} ((v) { |
| 12532 v; |
| 12533 }); |
| 12534 }'''; |
| 12535 Source source = addSource(code); |
| 12536 LibraryElement library = resolve2(source); |
| 12537 assertNoErrors(source); |
| 12538 verify([source]); |
| 12539 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12540 // v |
| 12541 DartType dynamicType = typeProvider.dynamicType; |
| 12542 DartType stringType = typeProvider.stringType; |
| 12543 FormalParameter vParameter = EngineTestCase.findNode( |
| 12544 unit, code, "v)", (node) => node is FormalParameter); |
| 12545 expect(vParameter.identifier.propagatedType, same(stringType)); |
| 12546 expect(vParameter.identifier.staticType, same(dynamicType)); |
| 12547 SimpleIdentifier vIdentifier = EngineTestCase.findNode( |
| 12548 unit, code, "v;", (node) => node is SimpleIdentifier); |
| 12549 expect(vIdentifier.propagatedType, same(stringType)); |
| 12550 expect(vIdentifier.staticType, same(dynamicType)); |
| 12551 } |
| 12552 |
| 12553 void test_functionExpression_asInvocationArgument_keepIfLessSpecific() { |
| 12554 String code = r''' |
| 12555 class MyList { |
| 12556 forEach(f(Object value)) {} |
| 12557 } |
| 12558 f(MyList list) { |
| 12559 list.forEach((int v) { |
| 12560 v; |
| 12561 }); |
| 12562 }'''; |
| 12563 Source source = addSource(code); |
| 12564 LibraryElement library = resolve2(source); |
| 12565 assertNoErrors(source); |
| 12566 verify([source]); |
| 12567 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12568 // v |
| 12569 DartType intType = typeProvider.intType; |
| 12570 FormalParameter vParameter = EngineTestCase.findNode( |
| 12571 unit, code, "v)", (node) => node is SimpleFormalParameter); |
| 12572 expect(vParameter.identifier.propagatedType, same(null)); |
| 12573 expect(vParameter.identifier.staticType, same(intType)); |
| 12574 SimpleIdentifier vIdentifier = EngineTestCase.findNode( |
| 12575 unit, code, "v;", (node) => node is SimpleIdentifier); |
| 12576 expect(vIdentifier.staticType, same(intType)); |
| 12577 expect(vIdentifier.propagatedType, same(null)); |
| 12578 } |
| 12579 |
| 12580 void test_functionExpression_asInvocationArgument_notSubtypeOfStaticType() { |
| 12581 String code = r''' |
| 12582 class A { |
| 12583 m(void f(int i)) {} |
| 12584 } |
| 12585 x() { |
| 12586 A a = new A(); |
| 12587 a.m(() => 0); |
| 12588 }'''; |
| 12589 Source source = addSource(code); |
| 12590 LibraryElement library = resolve2(source); |
| 12591 assertErrors(source, [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]); |
| 12592 verify([source]); |
| 12593 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12594 // () => 0 |
| 12595 FunctionExpression functionExpression = EngineTestCase.findNode( |
| 12596 unit, code, "() => 0)", (node) => node is FunctionExpression); |
| 12597 expect((functionExpression.staticType as FunctionType).parameters.length, |
| 12598 same(0)); |
| 12599 expect(functionExpression.propagatedType, same(null)); |
| 12600 } |
| 12601 |
| 12602 void test_functionExpression_asInvocationArgument_replaceIfMoreSpecific() { |
| 12603 String code = r''' |
| 12604 class MyList<E> { |
| 12605 forEach(f(E value)) {} |
| 12606 } |
| 12607 f(MyList<String> list) { |
| 12608 list.forEach((Object v) { |
| 12609 v; |
| 12610 }); |
| 12611 }'''; |
| 12612 Source source = addSource(code); |
| 12613 LibraryElement library = resolve2(source); |
| 12614 assertNoErrors(source); |
| 12615 verify([source]); |
| 12616 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12617 // v |
| 12618 DartType stringType = typeProvider.stringType; |
| 12619 FormalParameter vParameter = EngineTestCase.findNode( |
| 12620 unit, code, "v)", (node) => node is SimpleFormalParameter); |
| 12621 expect(vParameter.identifier.propagatedType, same(stringType)); |
| 12622 expect(vParameter.identifier.staticType, same(typeProvider.objectType)); |
| 12623 SimpleIdentifier vIdentifier = EngineTestCase.findNode( |
| 12624 unit, code, "v;", (node) => node is SimpleIdentifier); |
| 12625 expect(vIdentifier.propagatedType, same(stringType)); |
| 12626 } |
| 12627 |
| 12628 void test_Future_then() { |
| 12629 String code = r''' |
| 12630 import 'dart:async'; |
| 12631 main(Future<int> firstFuture) { |
| 12632 firstFuture.then((p1) { |
| 12633 return 1.0; |
| 12634 }).then((p2) { |
| 12635 return new Future<String>.value('str'); |
| 12636 }).then((p3) { |
| 12637 }); |
| 12638 }'''; |
| 12639 Source source = addSource(code); |
| 12640 LibraryElement library = resolve2(source); |
| 12641 assertNoErrors(source); |
| 12642 verify([source]); |
| 12643 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12644 // p1 |
| 12645 FormalParameter p1 = EngineTestCase.findNode( |
| 12646 unit, code, "p1) {", (node) => node is SimpleFormalParameter); |
| 12647 expect(p1.identifier.propagatedType, same(typeProvider.intType)); |
| 12648 // p2 |
| 12649 FormalParameter p2 = EngineTestCase.findNode( |
| 12650 unit, code, "p2) {", (node) => node is SimpleFormalParameter); |
| 12651 expect(p2.identifier.propagatedType, same(typeProvider.doubleType)); |
| 12652 // p3 |
| 12653 FormalParameter p3 = EngineTestCase.findNode( |
| 12654 unit, code, "p3) {", (node) => node is SimpleFormalParameter); |
| 12655 expect(p3.identifier.propagatedType, same(typeProvider.stringType)); |
| 12656 } |
| 12657 |
| 12658 void test_initializer() { |
| 12659 Source source = addSource(r''' |
| 12660 f() { |
| 12661 var v = 0; |
| 12662 return v; |
| 12663 }'''); |
| 12664 LibraryElement library = resolve2(source); |
| 12665 assertNoErrors(source); |
| 12666 verify([source]); |
| 12667 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12668 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 12669 BlockFunctionBody body = |
| 12670 function.functionExpression.body as BlockFunctionBody; |
| 12671 NodeList<Statement> statements = body.block.statements; |
| 12672 // Type of 'v' in declaration. |
| 12673 { |
| 12674 VariableDeclarationStatement statement = |
| 12675 statements[0] as VariableDeclarationStatement; |
| 12676 SimpleIdentifier variableName = statement.variables.variables[0].name; |
| 12677 expect(variableName.staticType, same(typeProvider.dynamicType)); |
| 12678 expect(variableName.propagatedType, same(typeProvider.intType)); |
| 12679 } |
| 12680 // Type of 'v' in reference. |
| 12681 { |
| 12682 ReturnStatement statement = statements[1] as ReturnStatement; |
| 12683 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12684 expect(variableName.propagatedType, same(typeProvider.intType)); |
| 12685 } |
| 12686 } |
| 12687 |
| 12688 void test_initializer_dereference() { |
| 12689 Source source = addSource(r''' |
| 12690 f() { |
| 12691 var v = 'String'; |
| 12692 v. |
| 12693 }'''); |
| 12694 LibraryElement library = resolve2(source); |
| 12695 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12696 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 12697 BlockFunctionBody body = |
| 12698 function.functionExpression.body as BlockFunctionBody; |
| 12699 ExpressionStatement statement = |
| 12700 body.block.statements[1] as ExpressionStatement; |
| 12701 PrefixedIdentifier invocation = statement.expression as PrefixedIdentifier; |
| 12702 SimpleIdentifier variableName = invocation.prefix; |
| 12703 expect(variableName.propagatedType, same(typeProvider.stringType)); |
| 12704 } |
| 12705 |
| 12706 void test_initializer_hasStaticType() { |
| 12707 Source source = addSource(r''' |
| 12708 f() { |
| 12709 int v = 0; |
| 12710 return v; |
| 12711 }'''); |
| 12712 LibraryElement library = resolve2(source); |
| 12713 assertNoErrors(source); |
| 12714 verify([source]); |
| 12715 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12716 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 12717 BlockFunctionBody body = |
| 12718 function.functionExpression.body as BlockFunctionBody; |
| 12719 NodeList<Statement> statements = body.block.statements; |
| 12720 // Type of 'v' in declaration. |
| 12721 { |
| 12722 VariableDeclarationStatement statement = |
| 12723 statements[0] as VariableDeclarationStatement; |
| 12724 SimpleIdentifier variableName = statement.variables.variables[0].name; |
| 12725 expect(variableName.staticType, same(typeProvider.intType)); |
| 12726 expect(variableName.propagatedType, isNull); |
| 12727 } |
| 12728 // Type of 'v' in reference. |
| 12729 { |
| 12730 ReturnStatement statement = statements[1] as ReturnStatement; |
| 12731 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12732 expect(variableName.staticType, same(typeProvider.intType)); |
| 12733 expect(variableName.propagatedType, isNull); |
| 12734 } |
| 12735 } |
| 12736 |
| 12737 void test_initializer_hasStaticType_parameterized() { |
| 12738 Source source = addSource(r''' |
| 12739 f() { |
| 12740 List<int> v = <int>[]; |
| 12741 return v; |
| 12742 }'''); |
| 12743 LibraryElement library = resolve2(source); |
| 12744 assertNoErrors(source); |
| 12745 verify([source]); |
| 12746 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12747 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 12748 BlockFunctionBody body = |
| 12749 function.functionExpression.body as BlockFunctionBody; |
| 12750 NodeList<Statement> statements = body.block.statements; |
| 12751 // Type of 'v' in declaration. |
| 12752 { |
| 12753 VariableDeclarationStatement statement = |
| 12754 statements[0] as VariableDeclarationStatement; |
| 12755 SimpleIdentifier variableName = statement.variables.variables[0].name; |
| 12756 expect(variableName.staticType, isNotNull); |
| 12757 expect(variableName.propagatedType, isNull); |
| 12758 } |
| 12759 // Type of 'v' in reference. |
| 12760 { |
| 12761 ReturnStatement statement = statements[1] as ReturnStatement; |
| 12762 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12763 expect(variableName.staticType, isNotNull); |
| 12764 expect(variableName.propagatedType, isNull); |
| 12765 } |
| 12766 } |
| 12767 |
| 12768 void test_initializer_null() { |
| 12769 String code = r''' |
| 12770 main() { |
| 12771 int v = null; |
| 12772 return v; // marker |
| 12773 }'''; |
| 12774 CompilationUnit unit; |
| 12775 { |
| 12776 Source source = addSource(code); |
| 12777 LibraryElement library = resolve2(source); |
| 12778 assertNoErrors(source); |
| 12779 verify([source]); |
| 12780 unit = resolveCompilationUnit(source, library); |
| 12781 } |
| 12782 { |
| 12783 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12784 unit, code, "v = null;", (node) => node is SimpleIdentifier); |
| 12785 expect(identifier.staticType, same(typeProvider.intType)); |
| 12786 expect(identifier.propagatedType, same(null)); |
| 12787 } |
| 12788 { |
| 12789 SimpleIdentifier identifier = EngineTestCase.findNode( |
| 12790 unit, code, "v; // marker", (node) => node is SimpleIdentifier); |
| 12791 expect(identifier.staticType, same(typeProvider.intType)); |
| 12792 expect(identifier.propagatedType, same(null)); |
| 12793 } |
| 12794 } |
| 12795 |
| 12796 void test_is_conditional() { |
| 12797 Source source = addSource(r''' |
| 12798 class A {} |
| 12799 A f(var p) { |
| 12800 return (p is A) ? p : null; |
| 12801 }'''); |
| 12802 LibraryElement library = resolve2(source); |
| 12803 assertNoErrors(source); |
| 12804 verify([source]); |
| 12805 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12806 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12807 InterfaceType typeA = classA.element.type; |
| 12808 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12809 BlockFunctionBody body = |
| 12810 function.functionExpression.body as BlockFunctionBody; |
| 12811 ReturnStatement statement = body.block.statements[0] as ReturnStatement; |
| 12812 ConditionalExpression conditional = |
| 12813 statement.expression as ConditionalExpression; |
| 12814 SimpleIdentifier variableName = |
| 12815 conditional.thenExpression as SimpleIdentifier; |
| 12816 expect(variableName.propagatedType, same(typeA)); |
| 12817 } |
| 12818 |
| 12819 void test_is_if() { |
| 12820 Source source = addSource(r''' |
| 12821 class A {} |
| 12822 A f(var p) { |
| 12823 if (p is A) { |
| 12824 return p; |
| 12825 } else { |
| 12826 return null; |
| 12827 } |
| 12828 }'''); |
| 12829 LibraryElement library = resolve2(source); |
| 12830 assertNoErrors(source); |
| 12831 verify([source]); |
| 12832 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12833 // prepare A |
| 12834 InterfaceType typeA; |
| 12835 { |
| 12836 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12837 typeA = classA.element.type; |
| 12838 } |
| 12839 // verify "f" |
| 12840 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12841 BlockFunctionBody body = |
| 12842 function.functionExpression.body as BlockFunctionBody; |
| 12843 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 12844 // "p is A" |
| 12845 { |
| 12846 IsExpression isExpression = ifStatement.condition; |
| 12847 SimpleIdentifier variableName = isExpression.expression; |
| 12848 expect(variableName.propagatedType, isNull); |
| 12849 } |
| 12850 // "return p;" |
| 12851 { |
| 12852 ReturnStatement statement = |
| 12853 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 12854 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12855 expect(variableName.propagatedType, same(typeA)); |
| 12856 } |
| 12857 } |
| 12858 |
| 12859 void test_is_if_lessSpecific() { |
| 12860 Source source = addSource(r''' |
| 12861 class A {} |
| 12862 A f(A p) { |
| 12863 if (p is String) { |
| 12864 return p; |
| 12865 } else { |
| 12866 return null; |
| 12867 } |
| 12868 }'''); |
| 12869 LibraryElement library = resolve2(source); |
| 12870 assertNoErrors(source); |
| 12871 verify([source]); |
| 12872 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12873 // ClassDeclaration classA = (ClassDeclaration) unit.getDeclarations().get(0)
; |
| 12874 // InterfaceType typeA = classA.getElement().getType(); |
| 12875 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12876 BlockFunctionBody body = |
| 12877 function.functionExpression.body as BlockFunctionBody; |
| 12878 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 12879 ReturnStatement statement = |
| 12880 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 12881 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12882 expect(variableName.propagatedType, same(null)); |
| 12883 } |
| 12884 |
| 12885 void test_is_if_logicalAnd() { |
| 12886 Source source = addSource(r''' |
| 12887 class A {} |
| 12888 A f(var p) { |
| 12889 if (p is A && p != null) { |
| 12890 return p; |
| 12891 } else { |
| 12892 return null; |
| 12893 } |
| 12894 }'''); |
| 12895 LibraryElement library = resolve2(source); |
| 12896 assertNoErrors(source); |
| 12897 verify([source]); |
| 12898 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12899 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12900 InterfaceType typeA = classA.element.type; |
| 12901 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12902 BlockFunctionBody body = |
| 12903 function.functionExpression.body as BlockFunctionBody; |
| 12904 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 12905 ReturnStatement statement = |
| 12906 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 12907 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12908 expect(variableName.propagatedType, same(typeA)); |
| 12909 } |
| 12910 |
| 12911 void test_is_postConditional() { |
| 12912 Source source = addSource(r''' |
| 12913 class A {} |
| 12914 A f(var p) { |
| 12915 A a = (p is A) ? p : throw null; |
| 12916 return p; |
| 12917 }'''); |
| 12918 LibraryElement library = resolve2(source); |
| 12919 assertNoErrors(source); |
| 12920 verify([source]); |
| 12921 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12922 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12923 InterfaceType typeA = classA.element.type; |
| 12924 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12925 BlockFunctionBody body = |
| 12926 function.functionExpression.body as BlockFunctionBody; |
| 12927 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 12928 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12929 expect(variableName.propagatedType, same(typeA)); |
| 12930 } |
| 12931 |
| 12932 void test_is_postIf() { |
| 12933 Source source = addSource(r''' |
| 12934 class A {} |
| 12935 A f(var p) { |
| 12936 if (p is A) { |
| 12937 A a = p; |
| 12938 } else { |
| 12939 return null; |
| 12940 } |
| 12941 return p; |
| 12942 }'''); |
| 12943 LibraryElement library = resolve2(source); |
| 12944 assertNoErrors(source); |
| 12945 verify([source]); |
| 12946 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12947 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12948 InterfaceType typeA = classA.element.type; |
| 12949 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12950 BlockFunctionBody body = |
| 12951 function.functionExpression.body as BlockFunctionBody; |
| 12952 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 12953 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 12954 expect(variableName.propagatedType, same(typeA)); |
| 12955 } |
| 12956 |
| 12957 void test_is_subclass() { |
| 12958 Source source = addSource(r''' |
| 12959 class A {} |
| 12960 class B extends A { |
| 12961 B m() => this; |
| 12962 } |
| 12963 A f(A p) { |
| 12964 if (p is B) { |
| 12965 return p.m(); |
| 12966 } |
| 12967 return p; |
| 12968 }'''); |
| 12969 LibraryElement library = resolve2(source); |
| 12970 assertNoErrors(source); |
| 12971 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12972 FunctionDeclaration function = unit.declarations[2] as FunctionDeclaration; |
| 12973 BlockFunctionBody body = |
| 12974 function.functionExpression.body as BlockFunctionBody; |
| 12975 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 12976 ReturnStatement statement = |
| 12977 (ifStatement.thenStatement as Block).statements[0] as ReturnStatement; |
| 12978 MethodInvocation invocation = statement.expression as MethodInvocation; |
| 12979 expect(invocation.methodName.staticElement, isNotNull); |
| 12980 expect(invocation.methodName.propagatedElement, isNull); |
| 12981 } |
| 12982 |
| 12983 void test_is_while() { |
| 12984 Source source = addSource(r''' |
| 12985 class A {} |
| 12986 A f(var p) { |
| 12987 while (p is A) { |
| 12988 return p; |
| 12989 } |
| 12990 return p; |
| 12991 }'''); |
| 12992 LibraryElement library = resolve2(source); |
| 12993 assertNoErrors(source); |
| 12994 verify([source]); |
| 12995 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 12996 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 12997 InterfaceType typeA = classA.element.type; |
| 12998 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 12999 BlockFunctionBody body = |
| 13000 function.functionExpression.body as BlockFunctionBody; |
| 13001 WhileStatement whileStatement = body.block.statements[0] as WhileStatement; |
| 13002 ReturnStatement statement = |
| 13003 (whileStatement.body as Block).statements[0] as ReturnStatement; |
| 13004 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13005 expect(variableName.propagatedType, same(typeA)); |
| 13006 } |
| 13007 |
| 13008 void test_isNot_conditional() { |
| 13009 Source source = addSource(r''' |
| 13010 class A {} |
| 13011 A f(var p) { |
| 13012 return (p is! A) ? null : p; |
| 13013 }'''); |
| 13014 LibraryElement library = resolve2(source); |
| 13015 assertNoErrors(source); |
| 13016 verify([source]); |
| 13017 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13018 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13019 InterfaceType typeA = classA.element.type; |
| 13020 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13021 BlockFunctionBody body = |
| 13022 function.functionExpression.body as BlockFunctionBody; |
| 13023 ReturnStatement statement = body.block.statements[0] as ReturnStatement; |
| 13024 ConditionalExpression conditional = |
| 13025 statement.expression as ConditionalExpression; |
| 13026 SimpleIdentifier variableName = |
| 13027 conditional.elseExpression as SimpleIdentifier; |
| 13028 expect(variableName.propagatedType, same(typeA)); |
| 13029 } |
| 13030 |
| 13031 void test_isNot_if() { |
| 13032 Source source = addSource(r''' |
| 13033 class A {} |
| 13034 A f(var p) { |
| 13035 if (p is! A) { |
| 13036 return null; |
| 13037 } else { |
| 13038 return p; |
| 13039 } |
| 13040 }'''); |
| 13041 LibraryElement library = resolve2(source); |
| 13042 assertNoErrors(source); |
| 13043 verify([source]); |
| 13044 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13045 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13046 InterfaceType typeA = classA.element.type; |
| 13047 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13048 BlockFunctionBody body = |
| 13049 function.functionExpression.body as BlockFunctionBody; |
| 13050 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 13051 ReturnStatement statement = |
| 13052 (ifStatement.elseStatement as Block).statements[0] as ReturnStatement; |
| 13053 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13054 expect(variableName.propagatedType, same(typeA)); |
| 13055 } |
| 13056 |
| 13057 void test_isNot_if_logicalOr() { |
| 13058 Source source = addSource(r''' |
| 13059 class A {} |
| 13060 A f(var p) { |
| 13061 if (p is! A || null == p) { |
| 13062 return null; |
| 13063 } else { |
| 13064 return p; |
| 13065 } |
| 13066 }'''); |
| 13067 LibraryElement library = resolve2(source); |
| 13068 assertNoErrors(source); |
| 13069 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13070 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13071 InterfaceType typeA = classA.element.type; |
| 13072 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13073 BlockFunctionBody body = |
| 13074 function.functionExpression.body as BlockFunctionBody; |
| 13075 IfStatement ifStatement = body.block.statements[0] as IfStatement; |
| 13076 ReturnStatement statement = |
| 13077 (ifStatement.elseStatement as Block).statements[0] as ReturnStatement; |
| 13078 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13079 expect(variableName.propagatedType, same(typeA)); |
| 13080 } |
| 13081 |
| 13082 void test_isNot_postConditional() { |
| 13083 Source source = addSource(r''' |
| 13084 class A {} |
| 13085 A f(var p) { |
| 13086 A a = (p is! A) ? throw null : p; |
| 13087 return p; |
| 13088 }'''); |
| 13089 LibraryElement library = resolve2(source); |
| 13090 assertNoErrors(source); |
| 13091 verify([source]); |
| 13092 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13093 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13094 InterfaceType typeA = classA.element.type; |
| 13095 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13096 BlockFunctionBody body = |
| 13097 function.functionExpression.body as BlockFunctionBody; |
| 13098 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13099 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13100 expect(variableName.propagatedType, same(typeA)); |
| 13101 } |
| 13102 |
| 13103 void test_isNot_postIf() { |
| 13104 Source source = addSource(r''' |
| 13105 class A {} |
| 13106 A f(var p) { |
| 13107 if (p is! A) { |
| 13108 return null; |
| 13109 } |
| 13110 return p; |
| 13111 }'''); |
| 13112 LibraryElement library = resolve2(source); |
| 13113 assertNoErrors(source); |
| 13114 verify([source]); |
| 13115 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13116 ClassDeclaration classA = unit.declarations[0] as ClassDeclaration; |
| 13117 InterfaceType typeA = classA.element.type; |
| 13118 FunctionDeclaration function = unit.declarations[1] as FunctionDeclaration; |
| 13119 BlockFunctionBody body = |
| 13120 function.functionExpression.body as BlockFunctionBody; |
| 13121 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13122 SimpleIdentifier variableName = statement.expression as SimpleIdentifier; |
| 13123 expect(variableName.propagatedType, same(typeA)); |
| 13124 } |
| 13125 |
| 13126 void test_issue20904BuggyTypePromotionAtIfJoin_5() { |
| 13127 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 13128 // |
| 13129 // This is not an example of the 20904 bug, but rather, |
| 13130 // an example of something that one obvious fix changes inadvertently: we |
| 13131 // want to avoid using type information from is-checks when it |
| 13132 // loses precision. I can't see how to get a bad hint this way, since |
| 13133 // it seems the propagated type is not used to generate hints when a |
| 13134 // more precise type would cause no hint. For example, for code like the |
| 13135 // following, when the propagated type of [x] is [A] -- as happens for the |
| 13136 // fix these tests aim to warn against -- there is no warning for |
| 13137 |
| 13138 // calling a method defined on [B] but not [A] (there aren't any, but |
| 13139 // pretend), but there is for calling a method not defined on either. |
| 13140 // By not overriding the propagated type via an is-check that loses |
| 13141 // precision, we get more precise completion under an is-check. However, |
| 13142 // I can only imagine strange code would make use of this feature. |
| 13143 // |
| 13144 // Here the is-check improves precision, so we use it. |
| 13145 String code = r''' |
| 13146 class A {} |
| 13147 class B extends A {} |
| 13148 f() { |
| 13149 var a = new A(); |
| 13150 var b = new B(); |
| 13151 b; // B |
| 13152 if (a is B) { |
| 13153 return a; // marker |
| 13154 } |
| 13155 }'''; |
| 13156 DartType tB = _findMarkedIdentifier(code, "; // B").propagatedType; |
| 13157 _assertTypeOfMarkedExpression(code, null, tB); |
| 13158 } |
| 13159 |
| 13160 void test_issue20904BuggyTypePromotionAtIfJoin_6() { |
| 13161 // https://code.google.com/p/dart/issues/detail?id=20904 |
| 13162 // |
| 13163 // The other half of the *_5() test. |
| 13164 // |
| 13165 // Here the is-check loses precision, so we don't use it. |
| 13166 String code = r''' |
| 13167 class A {} |
| 13168 class B extends A {} |
| 13169 f() { |
| 13170 var b = new B(); |
| 13171 b; // B |
| 13172 if (b is A) { |
| 13173 return b; // marker |
| 13174 } |
| 13175 }'''; |
| 13176 DartType tB = _findMarkedIdentifier(code, "; // B").propagatedType; |
| 13177 _assertTypeOfMarkedExpression(code, null, tB); |
| 13178 } |
| 13179 |
| 13180 void test_listLiteral_different() { |
| 13181 Source source = addSource(r''' |
| 13182 f() { |
| 13183 var v = [0, '1', 2]; |
| 13184 return v[2]; |
| 13185 }'''); |
| 13186 LibraryElement library = resolve2(source); |
| 13187 assertNoErrors(source); |
| 13188 verify([source]); |
| 13189 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13190 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13191 BlockFunctionBody body = |
| 13192 function.functionExpression.body as BlockFunctionBody; |
| 13193 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13194 IndexExpression indexExpression = statement.expression as IndexExpression; |
| 13195 expect(indexExpression.propagatedType, isNull); |
| 13196 } |
| 13197 |
| 13198 void test_listLiteral_same() { |
| 13199 Source source = addSource(r''' |
| 13200 f() { |
| 13201 var v = [0, 1, 2]; |
| 13202 return v[2]; |
| 13203 }'''); |
| 13204 LibraryElement library = resolve2(source); |
| 13205 assertNoErrors(source); |
| 13206 verify([source]); |
| 13207 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13208 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13209 BlockFunctionBody body = |
| 13210 function.functionExpression.body as BlockFunctionBody; |
| 13211 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13212 IndexExpression indexExpression = statement.expression as IndexExpression; |
| 13213 expect(indexExpression.propagatedType, isNull); |
| 13214 Expression v = indexExpression.target; |
| 13215 InterfaceType propagatedType = v.propagatedType as InterfaceType; |
| 13216 expect(propagatedType.element, same(typeProvider.listType.element)); |
| 13217 List<DartType> typeArguments = propagatedType.typeArguments; |
| 13218 expect(typeArguments, hasLength(1)); |
| 13219 expect(typeArguments[0], same(typeProvider.dynamicType)); |
| 13220 } |
| 13221 |
| 13222 void test_mapLiteral_different() { |
| 13223 Source source = addSource(r''' |
| 13224 f() { |
| 13225 var v = {'0' : 0, 1 : '1', '2' : 2}; |
| 13226 return v; |
| 13227 }'''); |
| 13228 LibraryElement library = resolve2(source); |
| 13229 assertNoErrors(source); |
| 13230 verify([source]); |
| 13231 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13232 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13233 BlockFunctionBody body = |
| 13234 function.functionExpression.body as BlockFunctionBody; |
| 13235 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13236 SimpleIdentifier identifier = statement.expression as SimpleIdentifier; |
| 13237 InterfaceType propagatedType = identifier.propagatedType as InterfaceType; |
| 13238 expect(propagatedType.element, same(typeProvider.mapType.element)); |
| 13239 List<DartType> typeArguments = propagatedType.typeArguments; |
| 13240 expect(typeArguments, hasLength(2)); |
| 13241 expect(typeArguments[0], same(typeProvider.dynamicType)); |
| 13242 expect(typeArguments[1], same(typeProvider.dynamicType)); |
| 13243 } |
| 13244 |
| 13245 void test_mapLiteral_same() { |
| 13246 Source source = addSource(r''' |
| 13247 f() { |
| 13248 var v = {'a' : 0, 'b' : 1, 'c' : 2}; |
| 13249 return v; |
| 13250 }'''); |
| 13251 LibraryElement library = resolve2(source); |
| 13252 assertNoErrors(source); |
| 13253 verify([source]); |
| 13254 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13255 FunctionDeclaration function = unit.declarations[0] as FunctionDeclaration; |
| 13256 BlockFunctionBody body = |
| 13257 function.functionExpression.body as BlockFunctionBody; |
| 13258 ReturnStatement statement = body.block.statements[1] as ReturnStatement; |
| 13259 SimpleIdentifier identifier = statement.expression as SimpleIdentifier; |
| 13260 InterfaceType propagatedType = identifier.propagatedType as InterfaceType; |
| 13261 expect(propagatedType.element, same(typeProvider.mapType.element)); |
| 13262 List<DartType> typeArguments = propagatedType.typeArguments; |
| 13263 expect(typeArguments, hasLength(2)); |
| 13264 expect(typeArguments[0], same(typeProvider.dynamicType)); |
| 13265 expect(typeArguments[1], same(typeProvider.dynamicType)); |
| 13266 } |
| 13267 |
| 13268 void test_mergePropagatedTypes_afterIfThen_different() { |
| 13269 String code = r''' |
| 13270 main() { |
| 13271 var v = 0; |
| 13272 if (v != null) { |
| 13273 v = ''; |
| 13274 } |
| 13275 return v; |
| 13276 }'''; |
| 13277 { |
| 13278 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v;"); |
| 13279 expect(identifier.propagatedType, null); |
| 13280 } |
| 13281 { |
| 13282 SimpleIdentifier identifier = _findMarkedIdentifier(code, "v = '';"); |
| 13283 expect(identifier.propagatedType, typeProvider.stringType); |
| 13284 } |
| 13285 } |
| 13286 |
| 13287 void test_mergePropagatedTypes_afterIfThen_same() { |
| 13288 _assertTypeOfMarkedExpression( |
| 13289 r''' |
| 13290 main() { |
| 13291 var v = 1; |
| 13292 if (v != null) { |
| 13293 v = 2; |
| 13294 } |
| 13295 return v; // marker |
| 13296 }''', |
| 13297 null, |
| 13298 typeProvider.intType); |
| 13299 } |
| 13300 |
| 13301 void test_mergePropagatedTypes_afterIfThenElse_different() { |
| 13302 _assertTypeOfMarkedExpression( |
| 13303 r''' |
| 13304 main() { |
| 13305 var v = 1; |
| 13306 if (v != null) { |
| 13307 v = 2; |
| 13308 } else { |
| 13309 v = '3'; |
| 13310 } |
| 13311 return v; // marker |
| 13312 }''', |
| 13313 null, |
| 13314 null); |
| 13315 } |
| 13316 |
| 13317 void test_mergePropagatedTypes_afterIfThenElse_same() { |
| 13318 _assertTypeOfMarkedExpression( |
| 13319 r''' |
| 13320 main() { |
| 13321 var v = 1; |
| 13322 if (v != null) { |
| 13323 v = 2; |
| 13324 } else { |
| 13325 v = 3; |
| 13326 } |
| 13327 return v; // marker |
| 13328 }''', |
| 13329 null, |
| 13330 typeProvider.intType); |
| 13331 } |
| 13332 |
| 13333 void test_mergePropagatedTypesAtJoinPoint_4() { |
| 13334 // https://code.google.com/p/dart/issues/detail?id=19929 |
| 13335 _assertTypeOfMarkedExpression( |
| 13336 r''' |
| 13337 f5(x) { |
| 13338 var y = []; |
| 13339 if (x) { |
| 13340 y = 0; |
| 13341 } else { |
| 13342 return y; |
| 13343 } |
| 13344 // Propagated type is [int] here: correct. |
| 13345 return y; // marker |
| 13346 }''', |
| 13347 null, |
| 13348 typeProvider.intType); |
| 13349 } |
| 13350 |
| 13351 void test_mutatedOutsideScope() { |
| 13352 // https://code.google.com/p/dart/issues/detail?id=22732 |
| 13353 Source source = addSource(r''' |
| 13354 class Base { |
| 13355 } |
| 13356 |
| 13357 class Derived extends Base { |
| 13358 get y => null; |
| 13359 } |
| 13360 |
| 13361 class C { |
| 13362 void f() { |
| 13363 Base x = null; |
| 13364 if (x is Derived) { |
| 13365 print(x.y); // BAD |
| 13366 } |
| 13367 x = null; |
| 13368 } |
| 13369 } |
| 13370 |
| 13371 void g() { |
| 13372 Base x = null; |
| 13373 if (x is Derived) { |
| 13374 print(x.y); // GOOD |
| 13375 } |
| 13376 x = null; |
| 13377 }'''); |
| 13378 computeLibrarySourceErrors(source); |
| 13379 assertNoErrors(source); |
| 13380 } |
| 13381 |
| 13382 void test_objectMethodOnDynamicExpression_doubleEquals() { |
| 13383 // https://code.google.com/p/dart/issues/detail?id=20342 |
| 13384 // |
| 13385 // This was not actually part of Issue 20342, since the spec specifies a |
| 13386 // static type of [bool] for [==] comparison and the implementation |
| 13387 // was already consistent with the spec there. But, it's another |
| 13388 // [Object] method, so it's included here. |
| 13389 _assertTypeOfMarkedExpression( |
| 13390 r''' |
| 13391 f1(x) { |
| 13392 var v = (x == x); |
| 13393 return v; // marker |
| 13394 }''', |
| 13395 null, |
| 13396 typeProvider.boolType); |
| 13397 } |
| 13398 |
| 13399 void test_objectMethodOnDynamicExpression_hashCode() { |
| 13400 // https://code.google.com/p/dart/issues/detail?id=20342 |
| 13401 _assertTypeOfMarkedExpression( |
| 13402 r''' |
| 13403 f1(x) { |
| 13404 var v = x.hashCode; |
| 13405 return v; // marker |
| 13406 }''', |
| 13407 null, |
| 13408 typeProvider.intType); |
| 13409 } |
| 13410 |
| 13411 void test_objectMethodOnDynamicExpression_runtimeType() { |
| 13412 // https://code.google.com/p/dart/issues/detail?id=20342 |
| 13413 _assertTypeOfMarkedExpression( |
| 13414 r''' |
| 13415 f1(x) { |
| 13416 var v = x.runtimeType; |
| 13417 return v; // marker |
| 13418 }''', |
| 13419 null, |
| 13420 typeProvider.typeType); |
| 13421 } |
| 13422 |
| 13423 void test_objectMethodOnDynamicExpression_toString() { |
| 13424 // https://code.google.com/p/dart/issues/detail?id=20342 |
| 13425 _assertTypeOfMarkedExpression( |
| 13426 r''' |
| 13427 f1(x) { |
| 13428 var v = x.toString(); |
| 13429 return v; // marker |
| 13430 }''', |
| 13431 null, |
| 13432 typeProvider.stringType); |
| 13433 } |
| 13434 |
| 13435 void test_propagatedReturnType_function_hasReturnType_returnsNull() { |
| 13436 String code = r''' |
| 13437 String f() => null; |
| 13438 main() { |
| 13439 var v = f(); |
| 13440 }'''; |
| 13441 _assertPropagatedAssignedType( |
| 13442 code, typeProvider.dynamicType, typeProvider.stringType); |
| 13443 } |
| 13444 |
| 13445 void test_propagatedReturnType_function_lessSpecificStaticReturnType() { |
| 13446 String code = r''' |
| 13447 Object f() => 42; |
| 13448 main() { |
| 13449 var v = f(); |
| 13450 }'''; |
| 13451 _assertPropagatedAssignedType( |
| 13452 code, typeProvider.dynamicType, typeProvider.intType); |
| 13453 } |
| 13454 |
| 13455 void test_propagatedReturnType_function_moreSpecificStaticReturnType() { |
| 13456 String code = r''' |
| 13457 int f(v) => (v as num); |
| 13458 main() { |
| 13459 var v = f(3); |
| 13460 }'''; |
| 13461 _assertPropagatedAssignedType( |
| 13462 code, typeProvider.dynamicType, typeProvider.intType); |
| 13463 } |
| 13464 |
| 13465 void test_propagatedReturnType_function_noReturnTypeName_blockBody_multipleRet
urns() { |
| 13466 String code = r''' |
| 13467 f() { |
| 13468 if (true) return 0; |
| 13469 return 1.0; |
| 13470 } |
| 13471 main() { |
| 13472 var v = f(); |
| 13473 }'''; |
| 13474 _assertPropagatedAssignedType( |
| 13475 code, typeProvider.dynamicType, typeProvider.numType); |
| 13476 } |
| 13477 |
| 13478 void test_propagatedReturnType_function_noReturnTypeName_blockBody_oneReturn()
{ |
| 13479 String code = r''' |
| 13480 f() { |
| 13481 var z = 42; |
| 13482 return z; |
| 13483 } |
| 13484 main() { |
| 13485 var v = f(); |
| 13486 }'''; |
| 13487 _assertPropagatedAssignedType( |
| 13488 code, typeProvider.dynamicType, typeProvider.intType); |
| 13489 } |
| 13490 |
| 13491 void test_propagatedReturnType_function_noReturnTypeName_expressionBody() { |
| 13492 String code = r''' |
| 13493 f() => 42; |
| 13494 main() { |
| 13495 var v = f(); |
| 13496 }'''; |
| 13497 _assertPropagatedAssignedType( |
| 13498 code, typeProvider.dynamicType, typeProvider.intType); |
| 13499 } |
| 13500 |
| 13501 void test_propagatedReturnType_localFunction() { |
| 13502 String code = r''' |
| 13503 main() { |
| 13504 f() => 42; |
| 13505 var v = f(); |
| 13506 }'''; |
| 13507 _assertPropagatedAssignedType( |
| 13508 code, typeProvider.dynamicType, typeProvider.intType); |
| 13509 } |
| 13510 |
| 13511 void test_query() { |
| 13512 Source source = addSource(r''' |
| 13513 import 'dart:html'; |
| 13514 |
| 13515 main() { |
| 13516 var v1 = query('a'); |
| 13517 var v2 = query('A'); |
| 13518 var v3 = query('body:active'); |
| 13519 var v4 = query('button[foo="bar"]'); |
| 13520 var v5 = query('div.class'); |
| 13521 var v6 = query('input#id'); |
| 13522 var v7 = query('select#id'); |
| 13523 // invocation of method |
| 13524 var m1 = document.query('div'); |
| 13525 // unsupported currently |
| 13526 var b1 = query('noSuchTag'); |
| 13527 var b2 = query('DART_EDITOR_NO_SUCH_TYPE'); |
| 13528 var b3 = query('body div'); |
| 13529 return [v1, v2, v3, v4, v5, v6, v7, m1, b1, b2, b3]; |
| 13530 }'''); |
| 13531 LibraryElement library = resolve2(source); |
| 13532 assertNoErrors(source); |
| 13533 verify([source]); |
| 13534 CompilationUnit unit = resolveCompilationUnit(source, library); |
| 13535 FunctionDeclaration main = unit.declarations[0] as FunctionDeclaration; |
| 13536 BlockFunctionBody body = main.functionExpression.body as BlockFunctionBody; |
| 13537 ReturnStatement statement = body.block.statements[11] as ReturnStatement; |
| 13538 NodeList<Expression> elements = |
| 13539 (statement.expression as ListLiteral).elements; |
| 13540 expect(elements[0].propagatedType.name, "AnchorElement"); |
| 13541 expect(elements[1].propagatedType.name, "AnchorElement"); |
| 13542 expect(elements[2].propagatedType.name, "BodyElement"); |
| 13543 expect(elements[3].propagatedType.name, "ButtonElement"); |
| 13544 expect(elements[4].propagatedType.name, "DivElement"); |
| 13545 expect(elements[5].propagatedType.name, "InputElement"); |
| 13546 expect(elements[6].propagatedType.name, "SelectElement"); |
| 13547 expect(elements[7].propagatedType.name, "DivElement"); |
| 13548 expect(elements[8].propagatedType.name, "Element"); |
| 13549 expect(elements[9].propagatedType.name, "Element"); |
| 13550 expect(elements[10].propagatedType.name, "Element"); |
| 13551 } |
| 13552 } |
| 13553 |
| 13554 @reflectiveTest |
| 13555 class StrongModeTypePropagationTest extends ResolverTestCase { |
| 13556 @override |
| 13557 void setUp() { |
| 13558 AnalysisOptionsImpl options = new AnalysisOptionsImpl(); |
| 13559 options.strongMode = true; |
| 13560 resetWithOptions(options); |
| 13561 } |
| 13562 |
| 13563 void test_localVariableInference_constant() { |
| 13564 String code = r''' |
| 13565 main() { |
| 13566 var v = 3; |
| 13567 return v; // marker |
| 13568 }'''; |
| 13569 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13570 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13571 } |
| 13572 |
| 13573 void test_localVariableInference_transitive_local() { |
| 13574 String code = r''' |
| 13575 main() { |
| 13576 var x = 3; |
| 13577 var v = x; |
| 13578 return v; // marker |
| 13579 }'''; |
| 13580 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13581 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13582 } |
| 13583 |
| 13584 void test_localVariableInference_transitive_list_local() { |
| 13585 String code = r''' |
| 13586 main() { |
| 13587 var x = <int>[3]; |
| 13588 var v = x[0]; |
| 13589 return v; // marker |
| 13590 }'''; |
| 13591 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13592 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13593 } |
| 13594 |
| 13595 void test_localVariableInference_transitive_toplevel_lexical() { |
| 13596 String code = r''' |
| 13597 int x = 3; |
| 13598 main() { |
| 13599 var v = x; |
| 13600 return v; // marker |
| 13601 } |
| 13602 '''; |
| 13603 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13604 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13605 } |
| 13606 |
| 13607 void test_localVariableInference_transitive_toplevel_reversed() { |
| 13608 String code = r''' |
| 13609 main() { |
| 13610 var v = x; |
| 13611 return v; // marker |
| 13612 } |
| 13613 int x = 3; |
| 13614 '''; |
| 13615 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13616 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13617 } |
| 13618 |
| 13619 void fail_localVariableInference_transitive_toplevel_inferred_lexical() { |
| 13620 String code = r''' |
| 13621 final x = 3; |
| 13622 main() { |
| 13623 var v = x; |
| 13624 return v; // marker |
| 13625 } |
| 13626 '''; |
| 13627 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13628 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13629 } |
| 13630 |
| 13631 void fail_localVariableInference_transitive_toplevel_inferred_reversed() { |
| 13632 String code = r''' |
| 13633 main() { |
| 13634 var v = x; |
| 13635 return v; // marker |
| 13636 } |
| 13637 final x = 3; |
| 13638 '''; |
| 13639 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13640 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13641 } |
| 13642 |
| 13643 void test_localVariableInference_transitive_field_lexical() { |
| 13644 String code = r''' |
| 13645 class A { |
| 13646 int x = 3; |
| 13647 f() { |
| 13648 var v = x; |
| 13649 return v; // marker |
| 13650 } |
| 13651 } |
| 13652 main() { |
| 13653 } |
| 13654 '''; |
| 13655 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13656 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13657 } |
| 13658 |
| 13659 void test_localVariableInference_transitive_field_reversed() { |
| 13660 String code = r''' |
| 13661 class A { |
| 13662 f() { |
| 13663 var v = x; |
| 13664 return v; // marker |
| 13665 } |
| 13666 int x = 3; |
| 13667 } |
| 13668 main() { |
| 13669 } |
| 13670 '''; |
| 13671 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13672 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13673 } |
| 13674 |
| 13675 void fail_localVariableInference_transitive_field_inferred_lexical() { |
| 13676 String code = r''' |
| 13677 class A { |
| 13678 final x = 3; |
| 13679 f() { |
| 13680 var v = x; |
| 13681 return v; // marker |
| 13682 } |
| 13683 } |
| 13684 main() { |
| 13685 } |
| 13686 '''; |
| 13687 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13688 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13689 } |
| 13690 |
| 13691 void fail_localVariableInference_transitive_field_inferred_reversed() { |
| 13692 String code = r''' |
| 13693 class A { |
| 13694 f() { |
| 13695 var v = x; |
| 13696 return v; // marker |
| 13697 } |
| 13698 final x = 3; |
| 13699 } |
| 13700 main() { |
| 13701 } |
| 13702 '''; |
| 13703 _assertPropagatedAssignedType(code, typeProvider.intType, null); |
| 13704 _assertTypeOfMarkedExpression(code, typeProvider.intType, null); |
| 13705 } |
| 13706 |
| 13707 void test_localVariableInference_declaredType_disabled() { |
| 13708 String code = r''' |
| 13709 main() { |
| 13710 dynamic v = 3; |
| 13711 return v; // marker |
| 13712 }'''; |
| 13713 _assertPropagatedAssignedType( |
| 13714 code, typeProvider.dynamicType, typeProvider.intType); |
| 13715 _assertTypeOfMarkedExpression( |
| 13716 code, typeProvider.dynamicType, typeProvider.intType); |
| 13717 } |
| 13718 |
| 13719 void test_localVariableInference_bottom_disabled() { |
| 13720 String code = r''' |
| 13721 main() { |
| 13722 var v = null; |
| 13723 return v; // marker |
| 13724 }'''; |
| 13725 _assertPropagatedAssignedType(code, typeProvider.dynamicType, null); |
| 13726 _assertTypeOfMarkedExpression(code, typeProvider.dynamicType, null); |
| 13727 } |
| 13728 |
| 13729 void test_localVariableInference_noInitializer_disabled() { |
| 13730 String code = r''' |
| 13731 main() { |
| 13732 var v; |
| 13733 v = 3; |
| 13734 return v; // marker |
| 13735 }'''; |
| 13736 _assertPropagatedAssignedType( |
| 13737 code, typeProvider.dynamicType, typeProvider.intType); |
| 13738 _assertTypeOfMarkedExpression( |
| 13739 code, typeProvider.dynamicType, typeProvider.intType); |
| 13740 } |
| 13741 } |
| 13742 |
| 13743 @reflectiveTest |
| 13744 class TypeProviderImplTest extends EngineTestCase { |
| 13745 void test_creation() { |
| 13746 // |
| 13747 // Create a mock library element with the types expected to be in dart:core. |
| 13748 // We cannot use either ElementFactory or TestTypeProvider (which uses |
| 13749 // ElementFactory) because we side-effect the elements in ways that would |
| 13750 // break other tests. |
| 13751 // |
| 13752 InterfaceType objectType = _classElement("Object", null).type; |
| 13753 InterfaceType boolType = _classElement("bool", objectType).type; |
| 13754 InterfaceType numType = _classElement("num", objectType).type; |
| 13755 InterfaceType doubleType = _classElement("double", numType).type; |
| 13756 InterfaceType functionType = _classElement("Function", objectType).type; |
| 13757 InterfaceType futureType = _classElement("Future", objectType, ["T"]).type; |
| 13758 InterfaceType intType = _classElement("int", numType).type; |
| 13759 InterfaceType iterableType = |
| 13760 _classElement("Iterable", objectType, ["T"]).type; |
| 13761 InterfaceType listType = _classElement("List", objectType, ["E"]).type; |
| 13762 InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type; |
| 13763 InterfaceType stackTraceType = _classElement("StackTrace", objectType).type; |
| 13764 InterfaceType streamType = _classElement("Stream", objectType, ["T"]).type; |
| 13765 InterfaceType stringType = _classElement("String", objectType).type; |
| 13766 InterfaceType symbolType = _classElement("Symbol", objectType).type; |
| 13767 InterfaceType typeType = _classElement("Type", objectType).type; |
| 13768 CompilationUnitElementImpl coreUnit = |
| 13769 new CompilationUnitElementImpl("core.dart"); |
| 13770 coreUnit.types = <ClassElement>[ |
| 13771 boolType.element, |
| 13772 doubleType.element, |
| 13773 functionType.element, |
| 13774 intType.element, |
| 13775 iterableType.element, |
| 13776 listType.element, |
| 13777 mapType.element, |
| 13778 objectType.element, |
| 13779 stackTraceType.element, |
| 13780 stringType.element, |
| 13781 symbolType.element, |
| 13782 typeType.element |
| 13783 ]; |
| 13784 CompilationUnitElementImpl asyncUnit = |
| 13785 new CompilationUnitElementImpl("async.dart"); |
| 13786 asyncUnit.types = <ClassElement>[futureType.element, streamType.element]; |
| 13787 AnalysisContext context = AnalysisEngine.instance.createAnalysisContext(); |
| 13788 LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode( |
| 13789 context, AstFactory.libraryIdentifier2(["dart.core"])); |
| 13790 coreLibrary.definingCompilationUnit = coreUnit; |
| 13791 LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode( |
| 13792 context, AstFactory.libraryIdentifier2(["dart.async"])); |
| 13793 asyncLibrary.definingCompilationUnit = asyncUnit; |
| 13794 // |
| 13795 // Create a type provider and ensure that it can return the expected types. |
| 13796 // |
| 13797 TypeProviderImpl provider = new TypeProviderImpl(coreLibrary, asyncLibrary); |
| 13798 expect(provider.boolType, same(boolType)); |
| 13799 expect(provider.bottomType, isNotNull); |
| 13800 expect(provider.doubleType, same(doubleType)); |
| 13801 expect(provider.dynamicType, isNotNull); |
| 13802 expect(provider.functionType, same(functionType)); |
| 13803 expect(provider.futureType, same(futureType)); |
| 13804 expect(provider.intType, same(intType)); |
| 13805 expect(provider.listType, same(listType)); |
| 13806 expect(provider.mapType, same(mapType)); |
| 13807 expect(provider.objectType, same(objectType)); |
| 13808 expect(provider.stackTraceType, same(stackTraceType)); |
| 13809 expect(provider.stringType, same(stringType)); |
| 13810 expect(provider.symbolType, same(symbolType)); |
| 13811 expect(provider.typeType, same(typeType)); |
| 13812 } |
| 13813 |
| 13814 ClassElement _classElement(String typeName, InterfaceType superclassType, |
| 13815 [List<String> parameterNames]) { |
| 13816 ClassElementImpl element = |
| 13817 new ClassElementImpl.forNode(AstFactory.identifier3(typeName)); |
| 13818 element.supertype = superclassType; |
| 13819 InterfaceTypeImpl type = new InterfaceTypeImpl(element); |
| 13820 element.type = type; |
| 13821 if (parameterNames != null) { |
| 13822 int count = parameterNames.length; |
| 13823 if (count > 0) { |
| 13824 List<TypeParameterElementImpl> typeParameters = |
| 13825 new List<TypeParameterElementImpl>(count); |
| 13826 List<TypeParameterTypeImpl> typeArguments = |
| 13827 new List<TypeParameterTypeImpl>(count); |
| 13828 for (int i = 0; i < count; i++) { |
| 13829 TypeParameterElementImpl typeParameter = |
| 13830 new TypeParameterElementImpl.forNode( |
| 13831 AstFactory.identifier3(parameterNames[i])); |
| 13832 typeParameters[i] = typeParameter; |
| 13833 typeArguments[i] = new TypeParameterTypeImpl(typeParameter); |
| 13834 typeParameter.type = typeArguments[i]; |
| 13835 } |
| 13836 element.typeParameters = typeParameters; |
| 13837 type.typeArguments = typeArguments; |
| 13838 } |
| 13839 } |
| 13840 return element; |
| 13841 } |
| 13842 } |
| 13843 |
| 13844 @reflectiveTest |
| 13845 class TypeResolverVisitorTest extends EngineTestCase { |
| 13846 /** |
| 13847 * The error listener to which errors will be reported. |
| 13848 */ |
| 13849 GatheringErrorListener _listener; |
| 13850 |
| 13851 /** |
| 13852 * The object representing the information about the library in which the type
s are being |
| 13853 * resolved. |
| 13854 */ |
| 13855 Library _library; |
| 13856 |
| 13857 /** |
| 13858 * The type provider used to access the types. |
| 13859 */ |
| 13860 TestTypeProvider _typeProvider; |
| 13861 |
| 13862 /** |
| 13863 * The visitor used to resolve types needed to form the type hierarchy. |
| 13864 */ |
| 13865 TypeResolverVisitor _visitor; |
| 13866 |
| 13867 void fail_visitConstructorDeclaration() { |
| 13868 fail("Not yet tested"); |
| 13869 _listener.assertNoErrors(); |
| 13870 } |
| 13871 |
| 13872 void fail_visitFunctionTypeAlias() { |
| 13873 fail("Not yet tested"); |
| 13874 _listener.assertNoErrors(); |
| 13875 } |
| 13876 |
| 13877 void fail_visitVariableDeclaration() { |
| 13878 fail("Not yet tested"); |
| 13879 ClassElement type = ElementFactory.classElement2("A"); |
| 13880 VariableDeclaration node = AstFactory.variableDeclaration("a"); |
| 13881 AstFactory.variableDeclarationList(null, AstFactory.typeName(type), [node]); |
| 13882 //resolve(node); |
| 13883 expect(node.name.staticType, same(type.type)); |
| 13884 _listener.assertNoErrors(); |
| 13885 } |
| 13886 |
| 13887 @override |
| 13888 void setUp() { |
| 13889 _listener = new GatheringErrorListener(); |
| 13890 InternalAnalysisContext context = AnalysisContextFactory.contextWithCore(); |
| 13891 Source librarySource = |
| 13892 new FileBasedSource(FileUtilities2.createFile("/lib.dart")); |
| 13893 _library = new Library(context, _listener, librarySource); |
| 13894 LibraryElementImpl element = new LibraryElementImpl.forNode( |
| 13895 context, AstFactory.libraryIdentifier2(["lib"])); |
| 13896 element.definingCompilationUnit = |
| 13897 new CompilationUnitElementImpl("lib.dart"); |
| 13898 _library.libraryElement = element; |
| 13899 _typeProvider = new TestTypeProvider(); |
| 13900 _visitor = new TypeResolverVisitor(_library.libraryElement, librarySource, |
| 13901 _typeProvider, _library.errorListener, |
| 13902 nameScope: _library.libraryScope); |
| 13903 } |
| 13904 |
| 13905 void test_visitCatchClause_exception() { |
| 13906 // catch (e) |
| 13907 CatchClause clause = AstFactory.catchClause("e"); |
| 13908 SimpleIdentifier exceptionParameter = clause.exceptionParameter; |
| 13909 exceptionParameter.staticElement = |
| 13910 new LocalVariableElementImpl.forNode(exceptionParameter); |
| 13911 _resolveCatchClause(clause, _typeProvider.dynamicType, null); |
| 13912 _listener.assertNoErrors(); |
| 13913 } |
| 13914 |
| 13915 void test_visitCatchClause_exception_stackTrace() { |
| 13916 // catch (e, s) |
| 13917 CatchClause clause = AstFactory.catchClause2("e", "s"); |
| 13918 SimpleIdentifier exceptionParameter = clause.exceptionParameter; |
| 13919 exceptionParameter.staticElement = |
| 13920 new LocalVariableElementImpl.forNode(exceptionParameter); |
| 13921 SimpleIdentifier stackTraceParameter = clause.stackTraceParameter; |
| 13922 stackTraceParameter.staticElement = |
| 13923 new LocalVariableElementImpl.forNode(stackTraceParameter); |
| 13924 _resolveCatchClause( |
| 13925 clause, _typeProvider.dynamicType, _typeProvider.stackTraceType); |
| 13926 _listener.assertNoErrors(); |
| 13927 } |
| 13928 |
| 13929 void test_visitCatchClause_on_exception() { |
| 13930 // on E catch (e) |
| 13931 ClassElement exceptionElement = ElementFactory.classElement2("E"); |
| 13932 TypeName exceptionType = AstFactory.typeName(exceptionElement); |
| 13933 CatchClause clause = AstFactory.catchClause4(exceptionType, "e"); |
| 13934 SimpleIdentifier exceptionParameter = clause.exceptionParameter; |
| 13935 exceptionParameter.staticElement = |
| 13936 new LocalVariableElementImpl.forNode(exceptionParameter); |
| 13937 _resolveCatchClause( |
| 13938 clause, exceptionElement.type, null, [exceptionElement]); |
| 13939 _listener.assertNoErrors(); |
| 13940 } |
| 13941 |
| 13942 void test_visitCatchClause_on_exception_stackTrace() { |
| 13943 // on E catch (e, s) |
| 13944 ClassElement exceptionElement = ElementFactory.classElement2("E"); |
| 13945 TypeName exceptionType = AstFactory.typeName(exceptionElement); |
| 13946 (exceptionType.name as SimpleIdentifier).staticElement = exceptionElement; |
| 13947 CatchClause clause = AstFactory.catchClause5(exceptionType, "e", "s"); |
| 13948 SimpleIdentifier exceptionParameter = clause.exceptionParameter; |
| 13949 exceptionParameter.staticElement = |
| 13950 new LocalVariableElementImpl.forNode(exceptionParameter); |
| 13951 SimpleIdentifier stackTraceParameter = clause.stackTraceParameter; |
| 13952 stackTraceParameter.staticElement = |
| 13953 new LocalVariableElementImpl.forNode(stackTraceParameter); |
| 13954 _resolveCatchClause(clause, exceptionElement.type, |
| 13955 _typeProvider.stackTraceType, [exceptionElement]); |
| 13956 _listener.assertNoErrors(); |
| 13957 } |
| 13958 |
| 13959 void test_visitClassDeclaration() { |
| 13960 // class A extends B with C implements D {} |
| 13961 // class B {} |
| 13962 // class C {} |
| 13963 // class D {} |
| 13964 ClassElement elementA = ElementFactory.classElement2("A"); |
| 13965 ClassElement elementB = ElementFactory.classElement2("B"); |
| 13966 ClassElement elementC = ElementFactory.classElement2("C"); |
| 13967 ClassElement elementD = ElementFactory.classElement2("D"); |
| 13968 ExtendsClause extendsClause = |
| 13969 AstFactory.extendsClause(AstFactory.typeName(elementB)); |
| 13970 WithClause withClause = |
| 13971 AstFactory.withClause([AstFactory.typeName(elementC)]); |
| 13972 ImplementsClause implementsClause = |
| 13973 AstFactory.implementsClause([AstFactory.typeName(elementD)]); |
| 13974 ClassDeclaration declaration = AstFactory.classDeclaration( |
| 13975 null, "A", null, extendsClause, withClause, implementsClause); |
| 13976 declaration.name.staticElement = elementA; |
| 13977 _resolveNode(declaration, [elementA, elementB, elementC, elementD]); |
| 13978 expect(elementA.supertype, same(elementB.type)); |
| 13979 List<InterfaceType> mixins = elementA.mixins; |
| 13980 expect(mixins, hasLength(1)); |
| 13981 expect(mixins[0], same(elementC.type)); |
| 13982 List<InterfaceType> interfaces = elementA.interfaces; |
| 13983 expect(interfaces, hasLength(1)); |
| 13984 expect(interfaces[0], same(elementD.type)); |
| 13985 _listener.assertNoErrors(); |
| 13986 } |
| 13987 |
| 13988 void test_visitClassDeclaration_instanceMemberCollidesWithClass() { |
| 13989 // class A {} |
| 13990 // class B extends A { |
| 13991 // void A() {} |
| 13992 // } |
| 13993 ClassElementImpl elementA = ElementFactory.classElement2("A"); |
| 13994 ClassElementImpl elementB = ElementFactory.classElement2("B"); |
| 13995 elementB.methods = <MethodElement>[ |
| 13996 ElementFactory.methodElement("A", VoidTypeImpl.instance) |
| 13997 ]; |
| 13998 ExtendsClause extendsClause = |
| 13999 AstFactory.extendsClause(AstFactory.typeName(elementA)); |
| 14000 ClassDeclaration declaration = |
| 14001 AstFactory.classDeclaration(null, "B", null, extendsClause, null, null); |
| 14002 declaration.name.staticElement = elementB; |
| 14003 _resolveNode(declaration, [elementA, elementB]); |
| 14004 expect(elementB.supertype, same(elementA.type)); |
| 14005 _listener.assertNoErrors(); |
| 14006 } |
| 14007 |
| 14008 void test_visitClassTypeAlias() { |
| 14009 // class A = B with C implements D; |
| 14010 ClassElement elementA = ElementFactory.classElement2("A"); |
| 14011 ClassElement elementB = ElementFactory.classElement2("B"); |
| 14012 ClassElement elementC = ElementFactory.classElement2("C"); |
| 14013 ClassElement elementD = ElementFactory.classElement2("D"); |
| 14014 WithClause withClause = |
| 14015 AstFactory.withClause([AstFactory.typeName(elementC)]); |
| 14016 ImplementsClause implementsClause = |
| 14017 AstFactory.implementsClause([AstFactory.typeName(elementD)]); |
| 14018 ClassTypeAlias alias = AstFactory.classTypeAlias("A", null, null, |
| 14019 AstFactory.typeName(elementB), withClause, implementsClause); |
| 14020 alias.name.staticElement = elementA; |
| 14021 _resolveNode(alias, [elementA, elementB, elementC, elementD]); |
| 14022 expect(elementA.supertype, same(elementB.type)); |
| 14023 List<InterfaceType> mixins = elementA.mixins; |
| 14024 expect(mixins, hasLength(1)); |
| 14025 expect(mixins[0], same(elementC.type)); |
| 14026 List<InterfaceType> interfaces = elementA.interfaces; |
| 14027 expect(interfaces, hasLength(1)); |
| 14028 expect(interfaces[0], same(elementD.type)); |
| 14029 _listener.assertNoErrors(); |
| 14030 } |
| 14031 |
| 14032 void test_visitClassTypeAlias_constructorWithOptionalParams_ignored() { |
| 14033 // class T {} |
| 14034 // class B { |
| 14035 // B.c1(); |
| 14036 // B.c2([T a0]); |
| 14037 // B.c3({T a0}); |
| 14038 // } |
| 14039 // class M {} |
| 14040 // class C = B with M |
| 14041 ClassElement classT = ElementFactory.classElement2('T', []); |
| 14042 ClassElementImpl classB = ElementFactory.classElement2('B', []); |
| 14043 ConstructorElementImpl constructorBc1 = |
| 14044 ElementFactory.constructorElement2(classB, 'c1', []); |
| 14045 ConstructorElementImpl constructorBc2 = |
| 14046 ElementFactory.constructorElement2(classB, 'c2', [classT.type]); |
| 14047 (constructorBc2.parameters[0] as ParameterElementImpl).parameterKind = |
| 14048 ParameterKind.POSITIONAL; |
| 14049 ConstructorElementImpl constructorBc3 = |
| 14050 ElementFactory.constructorElement2(classB, 'c3', [classT.type]); |
| 14051 (constructorBc3.parameters[0] as ParameterElementImpl).parameterKind = |
| 14052 ParameterKind.NAMED; |
| 14053 classB.constructors = [constructorBc1, constructorBc2, constructorBc3]; |
| 14054 ClassElement classM = ElementFactory.classElement2('M', []); |
| 14055 WithClause withClause = |
| 14056 AstFactory.withClause([AstFactory.typeName(classM, [])]); |
| 14057 ClassElement classC = ElementFactory.classTypeAlias2('C', []); |
| 14058 ClassTypeAlias alias = AstFactory.classTypeAlias( |
| 14059 'C', null, null, AstFactory.typeName(classB, []), withClause, null); |
| 14060 alias.name.staticElement = classC; |
| 14061 _resolveNode(alias, [classT, classB, classM, classC]); |
| 14062 expect(classC.constructors, hasLength(1)); |
| 14063 ConstructorElement constructor = classC.constructors[0]; |
| 14064 expect(constructor.isFactory, isFalse); |
| 14065 expect(constructor.isSynthetic, isTrue); |
| 14066 expect(constructor.name, 'c1'); |
| 14067 expect(constructor.functions, hasLength(0)); |
| 14068 expect(constructor.labels, hasLength(0)); |
| 14069 expect(constructor.localVariables, hasLength(0)); |
| 14070 expect(constructor.parameters, isEmpty); |
| 14071 } |
| 14072 |
| 14073 void test_visitClassTypeAlias_constructorWithParams() { |
| 14074 // class T {} |
| 14075 // class B { |
| 14076 // B(T a0); |
| 14077 // } |
| 14078 // class M {} |
| 14079 // class C = B with M |
| 14080 ClassElement classT = ElementFactory.classElement2('T', []); |
| 14081 ClassElementImpl classB = ElementFactory.classElement2('B', []); |
| 14082 ConstructorElementImpl constructorB = |
| 14083 ElementFactory.constructorElement2(classB, '', [classT.type]); |
| 14084 classB.constructors = [constructorB]; |
| 14085 ClassElement classM = ElementFactory.classElement2('M', []); |
| 14086 WithClause withClause = |
| 14087 AstFactory.withClause([AstFactory.typeName(classM, [])]); |
| 14088 ClassElement classC = ElementFactory.classTypeAlias2('C', []); |
| 14089 ClassTypeAlias alias = AstFactory.classTypeAlias( |
| 14090 'C', null, null, AstFactory.typeName(classB, []), withClause, null); |
| 14091 alias.name.staticElement = classC; |
| 14092 _resolveNode(alias, [classT, classB, classM, classC]); |
| 14093 expect(classC.constructors, hasLength(1)); |
| 14094 ConstructorElement constructor = classC.constructors[0]; |
| 14095 expect(constructor.isFactory, isFalse); |
| 14096 expect(constructor.isSynthetic, isTrue); |
| 14097 expect(constructor.name, ''); |
| 14098 expect(constructor.functions, hasLength(0)); |
| 14099 expect(constructor.labels, hasLength(0)); |
| 14100 expect(constructor.localVariables, hasLength(0)); |
| 14101 expect(constructor.parameters, hasLength(1)); |
| 14102 expect(constructor.parameters[0].type, equals(classT.type)); |
| 14103 expect(constructor.parameters[0].name, |
| 14104 equals(constructorB.parameters[0].name)); |
| 14105 } |
| 14106 |
| 14107 void test_visitClassTypeAlias_defaultConstructor() { |
| 14108 // class B {} |
| 14109 // class M {} |
| 14110 // class C = B with M |
| 14111 ClassElementImpl classB = ElementFactory.classElement2('B', []); |
| 14112 ConstructorElementImpl constructorB = |
| 14113 ElementFactory.constructorElement2(classB, '', []); |
| 14114 constructorB.setModifier(Modifier.SYNTHETIC, true); |
| 14115 classB.constructors = [constructorB]; |
| 14116 ClassElement classM = ElementFactory.classElement2('M', []); |
| 14117 WithClause withClause = |
| 14118 AstFactory.withClause([AstFactory.typeName(classM, [])]); |
| 14119 ClassElement classC = ElementFactory.classTypeAlias2('C', []); |
| 14120 ClassTypeAlias alias = AstFactory.classTypeAlias( |
| 14121 'C', null, null, AstFactory.typeName(classB, []), withClause, null); |
| 14122 alias.name.staticElement = classC; |
| 14123 _resolveNode(alias, [classB, classM, classC]); |
| 14124 expect(classC.constructors, hasLength(1)); |
| 14125 ConstructorElement constructor = classC.constructors[0]; |
| 14126 expect(constructor.isFactory, isFalse); |
| 14127 expect(constructor.isSynthetic, isTrue); |
| 14128 expect(constructor.name, ''); |
| 14129 expect(constructor.functions, hasLength(0)); |
| 14130 expect(constructor.labels, hasLength(0)); |
| 14131 expect(constructor.localVariables, hasLength(0)); |
| 14132 expect(constructor.parameters, isEmpty); |
| 14133 } |
| 14134 |
| 14135 void test_visitFieldFormalParameter_functionType() { |
| 14136 InterfaceType intType = _typeProvider.intType; |
| 14137 TypeName intTypeName = AstFactory.typeName4("int"); |
| 14138 String innerParameterName = "a"; |
| 14139 SimpleFormalParameter parameter = |
| 14140 AstFactory.simpleFormalParameter3(innerParameterName); |
| 14141 parameter.identifier.staticElement = |
| 14142 ElementFactory.requiredParameter(innerParameterName); |
| 14143 String outerParameterName = "p"; |
| 14144 FormalParameter node = AstFactory.fieldFormalParameter(null, intTypeName, |
| 14145 outerParameterName, AstFactory.formalParameterList([parameter])); |
| 14146 node.identifier.staticElement = |
| 14147 ElementFactory.requiredParameter(outerParameterName); |
| 14148 DartType parameterType = _resolveFormalParameter(node, [intType.element]); |
| 14149 EngineTestCase.assertInstanceOf( |
| 14150 (obj) => obj is FunctionType, FunctionType, parameterType); |
| 14151 FunctionType functionType = parameterType as FunctionType; |
| 14152 expect(functionType.returnType, same(intType)); |
| 14153 expect(functionType.parameters, hasLength(1)); |
| 14154 _listener.assertNoErrors(); |
| 14155 } |
| 14156 |
| 14157 void test_visitFieldFormalParameter_noType() { |
| 14158 String parameterName = "p"; |
| 14159 FormalParameter node = |
| 14160 AstFactory.fieldFormalParameter(Keyword.VAR, null, parameterName); |
| 14161 node.identifier.staticElement = |
| 14162 ElementFactory.requiredParameter(parameterName); |
| 14163 expect(_resolveFormalParameter(node), same(_typeProvider.dynamicType)); |
| 14164 _listener.assertNoErrors(); |
| 14165 } |
| 14166 |
| 14167 void test_visitFieldFormalParameter_type() { |
| 14168 InterfaceType intType = _typeProvider.intType; |
| 14169 TypeName intTypeName = AstFactory.typeName4("int"); |
| 14170 String parameterName = "p"; |
| 14171 FormalParameter node = |
| 14172 AstFactory.fieldFormalParameter(null, intTypeName, parameterName); |
| 14173 node.identifier.staticElement = |
| 14174 ElementFactory.requiredParameter(parameterName); |
| 14175 expect(_resolveFormalParameter(node, [intType.element]), same(intType)); |
| 14176 _listener.assertNoErrors(); |
| 14177 } |
| 14178 |
| 14179 void test_visitFunctionDeclaration() { |
| 14180 // R f(P p) {} |
| 14181 // class R {} |
| 14182 // class P {} |
| 14183 ClassElement elementR = ElementFactory.classElement2('R'); |
| 14184 ClassElement elementP = ElementFactory.classElement2('P'); |
| 14185 FunctionElement elementF = ElementFactory.functionElement('f'); |
| 14186 FunctionDeclaration declaration = AstFactory.functionDeclaration( |
| 14187 AstFactory.typeName4('R'), |
| 14188 null, |
| 14189 'f', |
| 14190 AstFactory.functionExpression2( |
| 14191 AstFactory.formalParameterList([ |
| 14192 AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p') |
| 14193 ]), |
| 14194 null)); |
| 14195 declaration.name.staticElement = elementF; |
| 14196 _resolveNode(declaration, [elementR, elementP]); |
| 14197 expect(declaration.returnType.type, elementR.type); |
| 14198 SimpleFormalParameter parameter = |
| 14199 declaration.functionExpression.parameters.parameters[0]; |
| 14200 expect(parameter.type.type, elementP.type); |
| 14201 _listener.assertNoErrors(); |
| 14202 } |
| 14203 |
| 14204 void test_visitFunctionDeclaration_typeParameter() { |
| 14205 // E f<E>(E e) {} |
| 14206 TypeParameterElement elementE = ElementFactory.typeParameterElement('E'); |
| 14207 FunctionElementImpl elementF = ElementFactory.functionElement('f'); |
| 14208 elementF.typeParameters = <TypeParameterElement>[elementE]; |
| 14209 FunctionDeclaration declaration = AstFactory.functionDeclaration( |
| 14210 AstFactory.typeName4('E'), |
| 14211 null, |
| 14212 'f', |
| 14213 AstFactory.functionExpression2( |
| 14214 AstFactory.formalParameterList([ |
| 14215 AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e') |
| 14216 ]), |
| 14217 null)); |
| 14218 declaration.name.staticElement = elementF; |
| 14219 _resolveNode(declaration, []); |
| 14220 expect(declaration.returnType.type, elementE.type); |
| 14221 SimpleFormalParameter parameter = |
| 14222 declaration.functionExpression.parameters.parameters[0]; |
| 14223 expect(parameter.type.type, elementE.type); |
| 14224 _listener.assertNoErrors(); |
| 14225 } |
| 14226 |
| 14227 void test_visitFunctionTypedFormalParameter() { |
| 14228 // R f(R g(P p)) {} |
| 14229 // class R {} |
| 14230 // class P {} |
| 14231 ClassElement elementR = ElementFactory.classElement2('R'); |
| 14232 ClassElement elementP = ElementFactory.classElement2('P'); |
| 14233 FunctionElement elementF = ElementFactory.functionElement('f'); |
| 14234 ParameterElementImpl requiredParameter = |
| 14235 ElementFactory.requiredParameter('p'); |
| 14236 FunctionTypedFormalParameter parameterDeclaration = AstFactory |
| 14237 .functionTypedFormalParameter(AstFactory.typeName4('R'), 'g', [ |
| 14238 AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p') |
| 14239 ]); |
| 14240 parameterDeclaration.identifier.staticElement = requiredParameter; |
| 14241 FunctionDeclaration declaration = AstFactory.functionDeclaration( |
| 14242 AstFactory.typeName4('R'), |
| 14243 null, |
| 14244 'f', |
| 14245 AstFactory.functionExpression2( |
| 14246 AstFactory.formalParameterList([parameterDeclaration]), null)); |
| 14247 declaration.name.staticElement = elementF; |
| 14248 _resolveNode(declaration, [elementR, elementP]); |
| 14249 expect(declaration.returnType.type, elementR.type); |
| 14250 FunctionTypedFormalParameter parameter = |
| 14251 declaration.functionExpression.parameters.parameters[0]; |
| 14252 expect(parameter.returnType.type, elementR.type); |
| 14253 SimpleFormalParameter innerParameter = parameter.parameters.parameters[0]; |
| 14254 expect(innerParameter.type.type, elementP.type); |
| 14255 _listener.assertNoErrors(); |
| 14256 } |
| 14257 |
| 14258 void test_visitFunctionTypedFormalParameter_typeParameter() { |
| 14259 // R f(R g<E>(E e)) {} |
| 14260 // class R {} |
| 14261 ClassElement elementR = ElementFactory.classElement2('R'); |
| 14262 TypeParameterElement elementE = ElementFactory.typeParameterElement('E'); |
| 14263 FunctionElement elementF = ElementFactory.functionElement('f'); |
| 14264 ParameterElementImpl requiredParameter = |
| 14265 ElementFactory.requiredParameter('g'); |
| 14266 requiredParameter.typeParameters = <TypeParameterElement>[elementE]; |
| 14267 FunctionTypedFormalParameter parameterDeclaration = AstFactory |
| 14268 .functionTypedFormalParameter(AstFactory.typeName4('R'), 'g', [ |
| 14269 AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e') |
| 14270 ]); |
| 14271 parameterDeclaration.identifier.staticElement = requiredParameter; |
| 14272 FunctionDeclaration declaration = AstFactory.functionDeclaration( |
| 14273 AstFactory.typeName4('R'), |
| 14274 null, |
| 14275 'f', |
| 14276 AstFactory.functionExpression2( |
| 14277 AstFactory.formalParameterList([parameterDeclaration]), null)); |
| 14278 declaration.name.staticElement = elementF; |
| 14279 _resolveNode(declaration, [elementR]); |
| 14280 expect(declaration.returnType.type, elementR.type); |
| 14281 FunctionTypedFormalParameter parameter = |
| 14282 declaration.functionExpression.parameters.parameters[0]; |
| 14283 expect(parameter.returnType.type, elementR.type); |
| 14284 SimpleFormalParameter innerParameter = parameter.parameters.parameters[0]; |
| 14285 expect(innerParameter.type.type, elementE.type); |
| 14286 _listener.assertNoErrors(); |
| 14287 } |
| 14288 |
| 14289 void test_visitMethodDeclaration() { |
| 14290 // class A { |
| 14291 // R m(P p) {} |
| 14292 // } |
| 14293 // class R {} |
| 14294 // class P {} |
| 14295 ClassElementImpl elementA = ElementFactory.classElement2('A'); |
| 14296 ClassElement elementR = ElementFactory.classElement2('R'); |
| 14297 ClassElement elementP = ElementFactory.classElement2('P'); |
| 14298 MethodElement elementM = ElementFactory.methodElement('m', null); |
| 14299 elementA.methods = <MethodElement>[elementM]; |
| 14300 MethodDeclaration declaration = AstFactory.methodDeclaration( |
| 14301 null, |
| 14302 AstFactory.typeName4('R'), |
| 14303 null, |
| 14304 null, |
| 14305 AstFactory.identifier3('m'), |
| 14306 AstFactory.formalParameterList([ |
| 14307 AstFactory.simpleFormalParameter4(AstFactory.typeName4('P'), 'p') |
| 14308 ])); |
| 14309 declaration.name.staticElement = elementM; |
| 14310 _resolveNode(declaration, [elementA, elementR, elementP]); |
| 14311 expect(declaration.returnType.type, elementR.type); |
| 14312 SimpleFormalParameter parameter = declaration.parameters.parameters[0]; |
| 14313 expect(parameter.type.type, elementP.type); |
| 14314 _listener.assertNoErrors(); |
| 14315 } |
| 14316 |
| 14317 void test_visitMethodDeclaration_typeParameter() { |
| 14318 // class A { |
| 14319 // E m<E>(E e) {} |
| 14320 // } |
| 14321 ClassElementImpl elementA = ElementFactory.classElement2('A'); |
| 14322 TypeParameterElement elementE = ElementFactory.typeParameterElement('E'); |
| 14323 MethodElementImpl elementM = ElementFactory.methodElement('m', null); |
| 14324 elementM.typeParameters = <TypeParameterElement>[elementE]; |
| 14325 elementA.methods = <MethodElement>[elementM]; |
| 14326 MethodDeclaration declaration = AstFactory.methodDeclaration( |
| 14327 null, |
| 14328 AstFactory.typeName4('E'), |
| 14329 null, |
| 14330 null, |
| 14331 AstFactory.identifier3('m'), |
| 14332 AstFactory.formalParameterList([ |
| 14333 AstFactory.simpleFormalParameter4(AstFactory.typeName4('E'), 'e') |
| 14334 ])); |
| 14335 declaration.name.staticElement = elementM; |
| 14336 _resolveNode(declaration, [elementA]); |
| 14337 expect(declaration.returnType.type, elementE.type); |
| 14338 SimpleFormalParameter parameter = declaration.parameters.parameters[0]; |
| 14339 expect(parameter.type.type, elementE.type); |
| 14340 _listener.assertNoErrors(); |
| 14341 } |
| 14342 |
| 14343 void test_visitSimpleFormalParameter_noType() { |
| 14344 // p |
| 14345 FormalParameter node = AstFactory.simpleFormalParameter3("p"); |
| 14346 node.identifier.staticElement = |
| 14347 new ParameterElementImpl.forNode(AstFactory.identifier3("p")); |
| 14348 expect(_resolveFormalParameter(node), same(_typeProvider.dynamicType)); |
| 14349 _listener.assertNoErrors(); |
| 14350 } |
| 14351 |
| 14352 void test_visitSimpleFormalParameter_type() { |
| 14353 // int p |
| 14354 InterfaceType intType = _typeProvider.intType; |
| 14355 ClassElement intElement = intType.element; |
| 14356 FormalParameter node = |
| 14357 AstFactory.simpleFormalParameter4(AstFactory.typeName(intElement), "p"); |
| 14358 SimpleIdentifier identifier = node.identifier; |
| 14359 ParameterElementImpl element = new ParameterElementImpl.forNode(identifier); |
| 14360 identifier.staticElement = element; |
| 14361 expect(_resolveFormalParameter(node, [intElement]), same(intType)); |
| 14362 _listener.assertNoErrors(); |
| 14363 } |
| 14364 |
| 14365 void test_visitTypeName_noParameters_noArguments() { |
| 14366 ClassElement classA = ElementFactory.classElement2("A"); |
| 14367 TypeName typeName = AstFactory.typeName(classA); |
| 14368 typeName.type = null; |
| 14369 _resolveNode(typeName, [classA]); |
| 14370 expect(typeName.type, same(classA.type)); |
| 14371 _listener.assertNoErrors(); |
| 14372 } |
| 14373 |
| 14374 void test_visitTypeName_parameters_arguments() { |
| 14375 ClassElement classA = ElementFactory.classElement2("A", ["E"]); |
| 14376 ClassElement classB = ElementFactory.classElement2("B"); |
| 14377 TypeName typeName = |
| 14378 AstFactory.typeName(classA, [AstFactory.typeName(classB)]); |
| 14379 typeName.type = null; |
| 14380 _resolveNode(typeName, [classA, classB]); |
| 14381 InterfaceType resultType = typeName.type as InterfaceType; |
| 14382 expect(resultType.element, same(classA)); |
| 14383 List<DartType> resultArguments = resultType.typeArguments; |
| 14384 expect(resultArguments, hasLength(1)); |
| 14385 expect(resultArguments[0], same(classB.type)); |
| 14386 _listener.assertNoErrors(); |
| 14387 } |
| 14388 |
| 14389 void test_visitTypeName_parameters_noArguments() { |
| 14390 ClassElement classA = ElementFactory.classElement2("A", ["E"]); |
| 14391 TypeName typeName = AstFactory.typeName(classA); |
| 14392 typeName.type = null; |
| 14393 _resolveNode(typeName, [classA]); |
| 14394 InterfaceType resultType = typeName.type as InterfaceType; |
| 14395 expect(resultType.element, same(classA)); |
| 14396 List<DartType> resultArguments = resultType.typeArguments; |
| 14397 expect(resultArguments, hasLength(1)); |
| 14398 expect(resultArguments[0], same(DynamicTypeImpl.instance)); |
| 14399 _listener.assertNoErrors(); |
| 14400 } |
| 14401 |
| 14402 void test_visitTypeName_void() { |
| 14403 ClassElement classA = ElementFactory.classElement2("A"); |
| 14404 TypeName typeName = AstFactory.typeName4("void"); |
| 14405 _resolveNode(typeName, [classA]); |
| 14406 expect(typeName.type, same(VoidTypeImpl.instance)); |
| 14407 _listener.assertNoErrors(); |
| 14408 } |
| 14409 |
| 14410 /** |
| 14411 * Analyze the given catch clause and assert that the types of the parameters
have been set to the |
| 14412 * given types. The types can be null if the catch clause does not have the co
rresponding |
| 14413 * parameter. |
| 14414 * |
| 14415 * @param node the catch clause to be analyzed |
| 14416 * @param exceptionType the expected type of the exception parameter |
| 14417 * @param stackTraceType the expected type of the stack trace parameter |
| 14418 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 14419 * being resolved |
| 14420 */ |
| 14421 void _resolveCatchClause( |
| 14422 CatchClause node, DartType exceptionType, InterfaceType stackTraceType, |
| 14423 [List<Element> definedElements]) { |
| 14424 _resolveNode(node, definedElements); |
| 14425 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| 14426 if (exceptionParameter != null) { |
| 14427 expect(exceptionParameter.staticType, same(exceptionType)); |
| 14428 } |
| 14429 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; |
| 14430 if (stackTraceParameter != null) { |
| 14431 expect(stackTraceParameter.staticType, same(stackTraceType)); |
| 14432 } |
| 14433 } |
| 14434 |
| 14435 /** |
| 14436 * Return the type associated with the given parameter after the static type a
nalyzer has computed |
| 14437 * a type for it. |
| 14438 * |
| 14439 * @param node the parameter with which the type is associated |
| 14440 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 14441 * being resolved |
| 14442 * @return the type associated with the parameter |
| 14443 */ |
| 14444 DartType _resolveFormalParameter(FormalParameter node, |
| 14445 [List<Element> definedElements]) { |
| 14446 _resolveNode(node, definedElements); |
| 14447 return (node.identifier.staticElement as ParameterElement).type; |
| 14448 } |
| 14449 |
| 14450 /** |
| 14451 * Return the element associated with the given identifier after the resolver
has resolved the |
| 14452 * identifier. |
| 14453 * |
| 14454 * @param node the expression to be resolved |
| 14455 * @param definedElements the elements that are to be defined in the scope in
which the element is |
| 14456 * being resolved |
| 14457 * @return the element to which the expression was resolved |
| 14458 */ |
| 14459 void _resolveNode(AstNode node, [List<Element> definedElements]) { |
| 14460 if (definedElements != null) { |
| 14461 for (Element element in definedElements) { |
| 14462 _library.libraryScope.define(element); |
| 14463 } |
| 14464 } |
| 14465 node.accept(_visitor); |
| 14466 } |
| 14467 } |
| 14468 |
| 14469 class _AnalysisContextFactory_initContextWithCore |
| 14470 extends DirectoryBasedDartSdk { |
| 14471 _AnalysisContextFactory_initContextWithCore(JavaFile arg0) : super(arg0); |
| 14472 |
| 14473 @override |
| 14474 LibraryMap initialLibraryMap(bool useDart2jsPaths) { |
| 14475 LibraryMap map = new LibraryMap(); |
| 14476 _addLibrary(map, DartSdk.DART_ASYNC, false, "async.dart"); |
| 14477 _addLibrary(map, DartSdk.DART_CORE, false, "core.dart"); |
| 14478 _addLibrary(map, DartSdk.DART_HTML, false, "html_dartium.dart"); |
| 14479 _addLibrary(map, AnalysisContextFactory._DART_MATH, false, "math.dart"); |
| 14480 _addLibrary(map, AnalysisContextFactory._DART_INTERCEPTORS, true, |
| 14481 "_interceptors.dart"); |
| 14482 _addLibrary( |
| 14483 map, AnalysisContextFactory._DART_JS_HELPER, true, "_js_helper.dart"); |
| 14484 return map; |
| 14485 } |
| 14486 |
| 14487 void _addLibrary(LibraryMap map, String uri, bool isInternal, String path) { |
| 14488 SdkLibraryImpl library = new SdkLibraryImpl(uri); |
| 14489 if (isInternal) { |
| 14490 library.category = "Internal"; |
| 14491 } |
| 14492 library.path = path; |
| 14493 map.setLibrary(uri, library); |
| 14494 } |
| 14495 } |
| 14496 |
| 14497 class _SimpleResolverTest_localVariable_types_invoked |
| 14498 extends RecursiveAstVisitor<Object> { |
| 14499 final SimpleResolverTest test; |
| 14500 |
| 14501 List<bool> found; |
| 14502 |
| 14503 List<CaughtException> thrownException; |
| 14504 |
| 14505 _SimpleResolverTest_localVariable_types_invoked( |
| 14506 this.test, this.found, this.thrownException) |
| 14507 : super(); |
| 14508 |
| 14509 @override |
| 14510 Object visitSimpleIdentifier(SimpleIdentifier node) { |
| 14511 if (node.name == "myVar" && node.parent is MethodInvocation) { |
| 14512 try { |
| 14513 found[0] = true; |
| 14514 // check static type |
| 14515 DartType staticType = node.staticType; |
| 14516 expect(staticType, same(test.typeProvider.dynamicType)); |
| 14517 // check propagated type |
| 14518 FunctionType propagatedType = node.propagatedType as FunctionType; |
| 14519 expect(propagatedType.returnType, test.typeProvider.stringType); |
| 14520 } on AnalysisException catch (e, stackTrace) { |
| 14521 thrownException[0] = new CaughtException(e, stackTrace); |
| 14522 } |
| 14523 } |
| 14524 return null; |
| 14525 } |
| 14526 } |
OLD | NEW |