| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.resolution; | 5 library dart2js.resolution; |
| 6 | 6 |
| 7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../common/names.dart' show | 10 import '../common/names.dart' show Identifiers; |
| 11 Identifiers; | 11 import '../common/resolution.dart' |
| 12 import '../common/resolution.dart' show | 12 show Feature, Parsing, Resolution, ResolutionImpact; |
| 13 Feature, | 13 import '../common/tasks.dart' show CompilerTask, DeferredAction; |
| 14 Parsing, | 14 import '../compiler.dart' show Compiler; |
| 15 Resolution, | 15 import '../compile_time_constants.dart' show ConstantCompiler; |
| 16 ResolutionImpact; | 16 import '../constants/expressions.dart' |
| 17 import '../common/tasks.dart' show | 17 show |
| 18 CompilerTask, | 18 ConstantExpression, |
| 19 DeferredAction; | 19 ConstantExpressionKind, |
| 20 import '../compiler.dart' show | 20 ConstructedConstantExpression, |
| 21 Compiler; | 21 ErroneousConstantExpression; |
| 22 import '../compile_time_constants.dart' show | 22 import '../constants/values.dart' show ConstantValue; |
| 23 ConstantCompiler; | 23 import '../core_types.dart' show CoreClasses, CoreTypes; |
| 24 import '../constants/expressions.dart' show | |
| 25 ConstantExpression, | |
| 26 ConstantExpressionKind, | |
| 27 ConstructedConstantExpression, | |
| 28 ErroneousConstantExpression; | |
| 29 import '../constants/values.dart' show | |
| 30 ConstantValue; | |
| 31 import '../core_types.dart' show | |
| 32 CoreClasses, | |
| 33 CoreTypes; | |
| 34 import '../dart_types.dart'; | 24 import '../dart_types.dart'; |
| 35 import '../elements/elements.dart'; | 25 import '../elements/elements.dart'; |
| 36 import '../elements/modelx.dart' show | 26 import '../elements/modelx.dart' |
| 37 BaseClassElementX, | 27 show |
| 38 BaseFunctionElementX, | 28 BaseClassElementX, |
| 39 ConstructorElementX, | 29 BaseFunctionElementX, |
| 40 FieldElementX, | 30 ConstructorElementX, |
| 41 FunctionElementX, | 31 FieldElementX, |
| 42 GetterElementX, | 32 FunctionElementX, |
| 43 MetadataAnnotationX, | 33 GetterElementX, |
| 44 MixinApplicationElementX, | 34 MetadataAnnotationX, |
| 45 ParameterMetadataAnnotation, | 35 MixinApplicationElementX, |
| 46 SetterElementX, | 36 ParameterMetadataAnnotation, |
| 47 TypedefElementX; | 37 SetterElementX, |
| 48 import '../tokens/token.dart' show | 38 TypedefElementX; |
| 49 isBinaryOperator, | 39 import '../tokens/token.dart' |
| 50 isMinusOperator, | 40 show |
| 51 isTernaryOperator, | 41 isBinaryOperator, |
| 52 isUnaryOperator, | 42 isMinusOperator, |
| 53 isUserDefinableOperator; | 43 isTernaryOperator, |
| 44 isUnaryOperator, |
| 45 isUserDefinableOperator; |
| 54 import '../tree/tree.dart'; | 46 import '../tree/tree.dart'; |
| 55 import '../universe/call_structure.dart' show | 47 import '../universe/call_structure.dart' show CallStructure; |
| 56 CallStructure; | 48 import '../universe/use.dart' show StaticUse, TypeUse; |
| 57 import '../universe/use.dart' show | 49 import '../universe/world_impact.dart' show WorldImpact; |
| 58 StaticUse, | 50 import '../util/util.dart' show Link, LinkBuilder, Setlet; |
| 59 TypeUse; | |
| 60 import '../universe/world_impact.dart' show | |
| 61 WorldImpact; | |
| 62 import '../util/util.dart' show | |
| 63 Link, | |
| 64 LinkBuilder, | |
| 65 Setlet; | |
| 66 | 51 |
| 67 import 'class_hierarchy.dart'; | 52 import 'class_hierarchy.dart'; |
| 68 import 'class_members.dart' show MembersCreator; | 53 import 'class_members.dart' show MembersCreator; |
| 69 import 'constructors.dart'; | 54 import 'constructors.dart'; |
| 70 import 'members.dart'; | 55 import 'members.dart'; |
| 71 import 'registry.dart'; | 56 import 'registry.dart'; |
| 72 import 'signatures.dart'; | 57 import 'signatures.dart'; |
| 73 import 'tree_elements.dart'; | 58 import 'tree_elements.dart'; |
| 74 import 'typedefs.dart'; | 59 import 'typedefs.dart'; |
| 75 | 60 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 return processMetadata(const ResolutionImpact()); | 106 return processMetadata(const ResolutionImpact()); |
| 122 } else if (element.isTypedef) { | 107 } else if (element.isTypedef) { |
| 123 TypedefElement typdef = element; | 108 TypedefElement typdef = element; |
| 124 return processMetadata(resolveTypedef(typdef)); | 109 return processMetadata(resolveTypedef(typdef)); |
| 125 } | 110 } |
| 126 | 111 |
| 127 compiler.unimplemented(element, "resolve($element)"); | 112 compiler.unimplemented(element, "resolve($element)"); |
| 128 }); | 113 }); |
| 129 } | 114 } |
| 130 | 115 |
| 131 void resolveRedirectingConstructor(InitializerResolver resolver, | 116 void resolveRedirectingConstructor(InitializerResolver resolver, Node node, |
| 132 Node node, | 117 FunctionElement constructor, FunctionElement redirection) { |
| 133 FunctionElement constructor, | |
| 134 FunctionElement redirection) { | |
| 135 assert(invariant(node, constructor.isImplementation, | 118 assert(invariant(node, constructor.isImplementation, |
| 136 message: 'Redirecting constructors must be resolved on implementation ' | 119 message: 'Redirecting constructors must be resolved on implementation ' |
| 137 'elements.')); | 120 'elements.')); |
| 138 Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); | 121 Setlet<FunctionElement> seen = new Setlet<FunctionElement>(); |
| 139 seen.add(constructor); | 122 seen.add(constructor); |
| 140 while (redirection != null) { | 123 while (redirection != null) { |
| 141 // Ensure that we follow redirections through implementation elements. | 124 // Ensure that we follow redirections through implementation elements. |
| 142 redirection = redirection.implementation; | 125 redirection = redirection.implementation; |
| 143 if (redirection.isError) { | 126 if (redirection.isError) { |
| 144 break; | 127 break; |
| 145 } | 128 } |
| 146 if (seen.contains(redirection)) { | 129 if (seen.contains(redirection)) { |
| 147 reporter.reportErrorMessage( | 130 reporter.reportErrorMessage( |
| 148 node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); | 131 node, MessageKind.REDIRECTING_CONSTRUCTOR_CYCLE); |
| 149 return; | 132 return; |
| 150 } | 133 } |
| 151 seen.add(redirection); | 134 seen.add(redirection); |
| 152 redirection = resolver.visitor.resolveConstructorRedirection(redirection); | 135 redirection = resolver.visitor.resolveConstructorRedirection(redirection); |
| 153 } | 136 } |
| 154 } | 137 } |
| 155 | 138 |
| 156 static void processAsyncMarker(Compiler compiler, | 139 static void processAsyncMarker(Compiler compiler, |
| 157 BaseFunctionElementX element, | 140 BaseFunctionElementX element, ResolutionRegistry registry) { |
| 158 ResolutionRegistry registry) { | |
| 159 DiagnosticReporter reporter = compiler.reporter; | 141 DiagnosticReporter reporter = compiler.reporter; |
| 160 Resolution resolution = compiler.resolution; | 142 Resolution resolution = compiler.resolution; |
| 161 CoreClasses coreClasses = compiler.coreClasses; | 143 CoreClasses coreClasses = compiler.coreClasses; |
| 162 FunctionExpression functionExpression = element.node; | 144 FunctionExpression functionExpression = element.node; |
| 163 AsyncModifier asyncModifier = functionExpression.asyncModifier; | 145 AsyncModifier asyncModifier = functionExpression.asyncModifier; |
| 164 if (asyncModifier != null) { | 146 if (asyncModifier != null) { |
| 165 | |
| 166 if (asyncModifier.isAsynchronous) { | 147 if (asyncModifier.isAsynchronous) { |
| 167 element.asyncMarker = asyncModifier.isYielding | 148 element.asyncMarker = asyncModifier.isYielding |
| 168 ? AsyncMarker.ASYNC_STAR : AsyncMarker.ASYNC; | 149 ? AsyncMarker.ASYNC_STAR |
| 150 : AsyncMarker.ASYNC; |
| 169 } else { | 151 } else { |
| 170 element.asyncMarker = AsyncMarker.SYNC_STAR; | 152 element.asyncMarker = AsyncMarker.SYNC_STAR; |
| 171 } | 153 } |
| 172 if (element.isAbstract) { | 154 if (element.isAbstract) { |
| 173 reporter.reportErrorMessage( | 155 reporter.reportErrorMessage( |
| 174 asyncModifier, | 156 asyncModifier, |
| 175 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD, | 157 MessageKind.ASYNC_MODIFIER_ON_ABSTRACT_METHOD, |
| 176 {'modifier': element.asyncMarker}); | 158 {'modifier': element.asyncMarker}); |
| 177 } else if (element.isConstructor) { | 159 } else if (element.isConstructor) { |
| 178 reporter.reportErrorMessage( | 160 reporter.reportErrorMessage( |
| 179 asyncModifier, | 161 asyncModifier, |
| 180 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR, | 162 MessageKind.ASYNC_MODIFIER_ON_CONSTRUCTOR, |
| 181 {'modifier': element.asyncMarker}); | 163 {'modifier': element.asyncMarker}); |
| 182 } else { | 164 } else { |
| 183 if (element.isSetter) { | 165 if (element.isSetter) { |
| 184 reporter.reportErrorMessage( | 166 reporter.reportErrorMessage( |
| 185 asyncModifier, | 167 asyncModifier, |
| 186 MessageKind.ASYNC_MODIFIER_ON_SETTER, | 168 MessageKind.ASYNC_MODIFIER_ON_SETTER, |
| 187 {'modifier': element.asyncMarker}); | 169 {'modifier': element.asyncMarker}); |
| 188 | |
| 189 } | 170 } |
| 190 if (functionExpression.body.asReturn() != null && | 171 if (functionExpression.body.asReturn() != null && |
| 191 element.asyncMarker.isYielding) { | 172 element.asyncMarker.isYielding) { |
| 192 reporter.reportErrorMessage( | 173 reporter.reportErrorMessage( |
| 193 asyncModifier, | 174 asyncModifier, |
| 194 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, | 175 MessageKind.YIELDING_MODIFIER_ON_ARROW_BODY, |
| 195 {'modifier': element.asyncMarker}); | 176 {'modifier': element.asyncMarker}); |
| 196 } | 177 } |
| 197 } | 178 } |
| 198 switch (element.asyncMarker) { | 179 switch (element.asyncMarker) { |
| 199 case AsyncMarker.ASYNC: | 180 case AsyncMarker.ASYNC: |
| 200 registry.registerFeature(Feature.ASYNC); | 181 registry.registerFeature(Feature.ASYNC); |
| 201 coreClasses.futureClass.ensureResolved(resolution); | 182 coreClasses.futureClass.ensureResolved(resolution); |
| 202 break; | 183 break; |
| 203 case AsyncMarker.ASYNC_STAR: | 184 case AsyncMarker.ASYNC_STAR: |
| 204 registry.registerFeature(Feature.ASYNC_STAR); | 185 registry.registerFeature(Feature.ASYNC_STAR); |
| 205 coreClasses.streamClass.ensureResolved(resolution); | 186 coreClasses.streamClass.ensureResolved(resolution); |
| 206 break; | 187 break; |
| 207 case AsyncMarker.SYNC_STAR: | 188 case AsyncMarker.SYNC_STAR: |
| 208 registry.registerFeature(Feature.SYNC_STAR); | 189 registry.registerFeature(Feature.SYNC_STAR); |
| 209 coreClasses.iterableClass.ensureResolved(resolution); | 190 coreClasses.iterableClass.ensureResolved(resolution); |
| 210 break; | 191 break; |
| 211 } | 192 } |
| 212 } | 193 } |
| 213 } | 194 } |
| 214 | 195 |
| 215 bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) { | 196 bool _isNativeClassOrExtendsNativeClass(ClassElement classElement) { |
| 216 assert(classElement != null); | 197 assert(classElement != null); |
| 217 while (classElement != null) { | 198 while (classElement != null) { |
| 218 if (compiler.backend.isNative(classElement)) return true; | 199 if (compiler.backend.isNative(classElement)) return true; |
| 219 classElement = classElement.superclass; | 200 classElement = classElement.superclass; |
| 220 } | 201 } |
| 221 return false; | 202 return false; |
| 222 } | 203 } |
| 223 | 204 |
| 224 WorldImpact resolveMethodElementImplementation( | 205 WorldImpact resolveMethodElementImplementation( |
| 225 FunctionElement element, FunctionExpression tree) { | 206 FunctionElement element, FunctionExpression tree) { |
| 226 return reporter.withCurrentElement(element, () { | 207 return reporter.withCurrentElement(element, () { |
| 227 if (element.isExternal && tree.hasBody) { | 208 if (element.isExternal && tree.hasBody) { |
| 228 reporter.reportErrorMessage( | 209 reporter.reportErrorMessage(element, MessageKind.EXTERNAL_WITH_BODY, |
| 229 element, | |
| 230 MessageKind.EXTERNAL_WITH_BODY, | |
| 231 {'functionName': element.name}); | 210 {'functionName': element.name}); |
| 232 } | 211 } |
| 233 if (element.isConstructor) { | 212 if (element.isConstructor) { |
| 234 if (tree.returnType != null) { | 213 if (tree.returnType != null) { |
| 235 reporter.reportErrorMessage( | 214 reporter.reportErrorMessage( |
| 236 tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); | 215 tree, MessageKind.CONSTRUCTOR_WITH_RETURN_TYPE); |
| 237 } | 216 } |
| 238 if (tree.hasBody && element.isConst) { | 217 if (tree.hasBody && element.isConst) { |
| 239 if (element.isGenerativeConstructor) { | 218 if (element.isGenerativeConstructor) { |
| 240 reporter.reportErrorMessage( | 219 reporter.reportErrorMessage( |
| 241 tree, MessageKind.CONST_CONSTRUCTOR_WITH_BODY); | 220 tree, MessageKind.CONST_CONSTRUCTOR_WITH_BODY); |
| 242 } else if (!tree.isRedirectingFactory) { | 221 } else if (!tree.isRedirectingFactory) { |
| 243 reporter.reportErrorMessage( | 222 reporter.reportErrorMessage(tree, MessageKind.CONST_FACTORY); |
| 244 tree, MessageKind.CONST_FACTORY); | |
| 245 } | 223 } |
| 246 } | 224 } |
| 247 } | 225 } |
| 248 | 226 |
| 249 ResolverVisitor visitor = visitorFor(element); | 227 ResolverVisitor visitor = visitorFor(element); |
| 250 ResolutionRegistry registry = visitor.registry; | 228 ResolutionRegistry registry = visitor.registry; |
| 251 registry.defineFunction(tree, element); | 229 registry.defineFunction(tree, element); |
| 252 visitor.setupFunction(tree, element); | 230 visitor.setupFunction(tree, element); |
| 253 processAsyncMarker(compiler, element, registry); | 231 processAsyncMarker(compiler, element, registry); |
| 254 | 232 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 for (MixinApplicationElement mixinApplication in mixinUses) { | 266 for (MixinApplicationElement mixinApplication in mixinUses) { |
| 289 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); | 267 checkMixinSuperUses(resolutionTree, mixinApplication, mixin); |
| 290 } | 268 } |
| 291 } | 269 } |
| 292 | 270 |
| 293 // TODO(9631): support noSuchMethod on native classes. | 271 // TODO(9631): support noSuchMethod on native classes. |
| 294 if (element.isFunction && | 272 if (element.isFunction && |
| 295 element.isInstanceMember && | 273 element.isInstanceMember && |
| 296 element.name == Identifiers.noSuchMethod_ && | 274 element.name == Identifiers.noSuchMethod_ && |
| 297 _isNativeClassOrExtendsNativeClass(enclosingClass)) { | 275 _isNativeClassOrExtendsNativeClass(enclosingClass)) { |
| 298 reporter.reportErrorMessage( | 276 reporter.reportErrorMessage(tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); |
| 299 tree, MessageKind.NO_SUCH_METHOD_IN_NATIVE); | |
| 300 } | 277 } |
| 301 | 278 |
| 302 return registry.worldImpact; | 279 return registry.worldImpact; |
| 303 }); | 280 }); |
| 304 | |
| 305 } | 281 } |
| 306 | 282 |
| 307 WorldImpact resolveMethodElement(FunctionElementX element) { | 283 WorldImpact resolveMethodElement(FunctionElementX element) { |
| 308 assert(invariant(element, element.isDeclaration)); | 284 assert(invariant(element, element.isDeclaration)); |
| 309 return reporter.withCurrentElement(element, () { | 285 return reporter.withCurrentElement(element, () { |
| 310 if (compiler.enqueuer.resolution.hasBeenProcessed(element)) { | 286 if (compiler.enqueuer.resolution.hasBeenProcessed(element)) { |
| 311 // TODO(karlklose): Remove the check for [isConstructor]. [elememts] | 287 // TODO(karlklose): Remove the check for [isConstructor]. [elememts] |
| 312 // should never be non-null, not even for constructors. | 288 // should never be non-null, not even for constructors. |
| 313 assert(invariant(element, element.isConstructor, | 289 assert(invariant(element, element.isConstructor, |
| 314 message: 'Non-constructor element $element ' | 290 message: 'Non-constructor element $element ' |
| 315 'has already been analyzed.')); | 291 'has already been analyzed.')); |
| 316 return const ResolutionImpact(); | 292 return const ResolutionImpact(); |
| 317 } | 293 } |
| 318 if (element.isSynthesized) { | 294 if (element.isSynthesized) { |
| 319 if (element.isGenerativeConstructor) { | 295 if (element.isGenerativeConstructor) { |
| 320 ResolutionRegistry registry = | 296 ResolutionRegistry registry = |
| 321 new ResolutionRegistry(compiler, _ensureTreeElements(element)); | 297 new ResolutionRegistry(compiler, _ensureTreeElements(element)); |
| 322 ConstructorElement constructor = element.asFunctionElement(); | 298 ConstructorElement constructor = element.asFunctionElement(); |
| 323 ConstructorElement target = constructor.definingConstructor; | 299 ConstructorElement target = constructor.definingConstructor; |
| 324 // Ensure the signature of the synthesized element is | 300 // Ensure the signature of the synthesized element is |
| 325 // resolved. This is the only place where the resolver is | 301 // resolved. This is the only place where the resolver is |
| 326 // seeing this element. | 302 // seeing this element. |
| 327 element.computeType(resolution); | 303 element.computeType(resolution); |
| 328 if (!target.isMalformed) { | 304 if (!target.isMalformed) { |
| 329 registry.registerStaticUse( | 305 registry.registerStaticUse(new StaticUse.superConstructorInvoke( |
| 330 new StaticUse.superConstructorInvoke( | 306 target, CallStructure.NO_ARGS)); |
| 331 target, CallStructure.NO_ARGS)); | |
| 332 } | 307 } |
| 333 return registry.worldImpact; | 308 return registry.worldImpact; |
| 334 } else { | 309 } else { |
| 335 assert(element.isDeferredLoaderGetter || element.isMalformed); | 310 assert(element.isDeferredLoaderGetter || element.isMalformed); |
| 336 _ensureTreeElements(element); | 311 _ensureTreeElements(element); |
| 337 return const ResolutionImpact(); | 312 return const ResolutionImpact(); |
| 338 } | 313 } |
| 339 } else { | 314 } else { |
| 340 element.parseNode(resolution.parsing); | 315 element.parseNode(resolution.parsing); |
| 341 element.computeType(resolution); | 316 element.computeType(resolution); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 356 /// This method should only be used by this library (or tests of | 331 /// This method should only be used by this library (or tests of |
| 357 /// this library). | 332 /// this library). |
| 358 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { | 333 ResolverVisitor visitorFor(Element element, {bool useEnclosingScope: false}) { |
| 359 return new ResolverVisitor(compiler, element, | 334 return new ResolverVisitor(compiler, element, |
| 360 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 335 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
| 361 useEnclosingScope: useEnclosingScope); | 336 useEnclosingScope: useEnclosingScope); |
| 362 } | 337 } |
| 363 | 338 |
| 364 WorldImpact resolveField(FieldElementX element) { | 339 WorldImpact resolveField(FieldElementX element) { |
| 365 VariableDefinitions tree = element.parseNode(parsing); | 340 VariableDefinitions tree = element.parseNode(parsing); |
| 366 if(element.modifiers.isStatic && element.isTopLevel) { | 341 if (element.modifiers.isStatic && element.isTopLevel) { |
| 367 reporter.reportErrorMessage( | 342 reporter.reportErrorMessage(element.modifiers.getStatic(), |
| 368 element.modifiers.getStatic(), | |
| 369 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 343 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
| 370 } | 344 } |
| 371 ResolverVisitor visitor = visitorFor(element); | 345 ResolverVisitor visitor = visitorFor(element); |
| 372 ResolutionRegistry registry = visitor.registry; | 346 ResolutionRegistry registry = visitor.registry; |
| 373 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates | 347 // TODO(johnniwinther): Maybe remove this when placeholderCollector migrates |
| 374 // to the backend ast. | 348 // to the backend ast. |
| 375 registry.defineElement(tree.definitions.nodes.head, element); | 349 registry.defineElement(tree.definitions.nodes.head, element); |
| 376 // TODO(johnniwinther): Share the resolved type between all variables | 350 // TODO(johnniwinther): Share the resolved type between all variables |
| 377 // declared in the same declaration. | 351 // declared in the same declaration. |
| 378 if (tree.type != null) { | 352 if (tree.type != null) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 | 391 |
| 418 // Perform various checks as side effect of "computing" the type. | 392 // Perform various checks as side effect of "computing" the type. |
| 419 element.computeType(resolution); | 393 element.computeType(resolution); |
| 420 | 394 |
| 421 return registry.worldImpact; | 395 return registry.worldImpact; |
| 422 } | 396 } |
| 423 | 397 |
| 424 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { | 398 DartType resolveTypeAnnotation(Element element, TypeAnnotation annotation) { |
| 425 DartType type = resolveReturnType(element, annotation); | 399 DartType type = resolveReturnType(element, annotation); |
| 426 if (type.isVoid) { | 400 if (type.isVoid) { |
| 427 reporter.reportErrorMessage( | 401 reporter.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED); |
| 428 annotation, MessageKind.VOID_NOT_ALLOWED); | |
| 429 } | 402 } |
| 430 return type; | 403 return type; |
| 431 } | 404 } |
| 432 | 405 |
| 433 DartType resolveReturnType(Element element, TypeAnnotation annotation) { | 406 DartType resolveReturnType(Element element, TypeAnnotation annotation) { |
| 434 if (annotation == null) return const DynamicType(); | 407 if (annotation == null) return const DynamicType(); |
| 435 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); | 408 DartType result = visitorFor(element).resolveTypeAnnotation(annotation); |
| 436 if (result == null) { | 409 if (result == null) { |
| 437 // TODO(karklose): warning. | 410 // TODO(karklose): warning. |
| 438 return const DynamicType(); | 411 return const DynamicType(); |
| 439 } | 412 } |
| 440 return result; | 413 return result; |
| 441 } | 414 } |
| 442 | 415 |
| 443 void resolveRedirectionChain(ConstructorElementX constructor, | 416 void resolveRedirectionChain( |
| 444 Spannable node) { | 417 ConstructorElementX constructor, Spannable node) { |
| 445 ConstructorElementX target = constructor; | 418 ConstructorElementX target = constructor; |
| 446 InterfaceType targetType; | 419 InterfaceType targetType; |
| 447 List<Element> seen = new List<Element>(); | 420 List<Element> seen = new List<Element>(); |
| 448 bool isMalformed = false; | 421 bool isMalformed = false; |
| 449 // Follow the chain of redirections and check for cycles. | 422 // Follow the chain of redirections and check for cycles. |
| 450 while (target.isRedirectingFactory || target.isPatched) { | 423 while (target.isRedirectingFactory || target.isPatched) { |
| 451 if (target.effectiveTargetInternal != null) { | 424 if (target.effectiveTargetInternal != null) { |
| 452 // We found a constructor that already has been processed. | 425 // We found a constructor that already has been processed. |
| 453 targetType = target.effectiveTargetType; | 426 targetType = target.effectiveTargetType; |
| 454 assert(invariant(target, targetType != null, | 427 assert(invariant(target, targetType != null, |
| 455 message: 'Redirection target type has not been computed for ' | 428 message: 'Redirection target type has not been computed for ' |
| 456 '$target')); | 429 '$target')); |
| 457 target = target.effectiveTargetInternal; | 430 target = target.effectiveTargetInternal; |
| 458 break; | 431 break; |
| 459 } | 432 } |
| 460 | 433 |
| 461 Element nextTarget; | 434 Element nextTarget; |
| 462 if (target.isPatched) { | 435 if (target.isPatched) { |
| 463 nextTarget = target.patch; | 436 nextTarget = target.patch; |
| 464 } else { | 437 } else { |
| 465 nextTarget = target.immediateRedirectionTarget; | 438 nextTarget = target.immediateRedirectionTarget; |
| 466 } | 439 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 * Load and resolve the supertypes of [cls]. | 487 * Load and resolve the supertypes of [cls]. |
| 515 * | 488 * |
| 516 * Warning: do not call this method directly. It should only be | 489 * Warning: do not call this method directly. It should only be |
| 517 * called by [resolveClass] and [ClassSupertypeResolver]. | 490 * called by [resolveClass] and [ClassSupertypeResolver]. |
| 518 */ | 491 */ |
| 519 void loadSupertypes(BaseClassElementX cls, Spannable from) { | 492 void loadSupertypes(BaseClassElementX cls, Spannable from) { |
| 520 measure(() { | 493 measure(() { |
| 521 if (cls.supertypeLoadState == STATE_DONE) return; | 494 if (cls.supertypeLoadState == STATE_DONE) return; |
| 522 if (cls.supertypeLoadState == STATE_STARTED) { | 495 if (cls.supertypeLoadState == STATE_STARTED) { |
| 523 reporter.reportErrorMessage( | 496 reporter.reportErrorMessage( |
| 524 from, | 497 from, MessageKind.CYCLIC_CLASS_HIERARCHY, {'className': cls.name}); |
| 525 MessageKind.CYCLIC_CLASS_HIERARCHY, | |
| 526 {'className': cls.name}); | |
| 527 cls.supertypeLoadState = STATE_DONE; | 498 cls.supertypeLoadState = STATE_DONE; |
| 528 cls.hasIncompleteHierarchy = true; | 499 cls.hasIncompleteHierarchy = true; |
| 529 cls.allSupertypesAndSelf = | 500 cls.allSupertypesAndSelf = coreClasses.objectClass.allSupertypesAndSelf |
| 530 coreClasses.objectClass.allSupertypesAndSelf.extendClass( | 501 .extendClass(cls.computeType(resolution)); |
| 531 cls.computeType(resolution)); | |
| 532 cls.supertype = cls.allSupertypes.head; | 502 cls.supertype = cls.allSupertypes.head; |
| 533 assert(invariant(from, cls.supertype != null, | 503 assert(invariant(from, cls.supertype != null, |
| 534 message: 'Missing supertype on cyclic class $cls.')); | 504 message: 'Missing supertype on cyclic class $cls.')); |
| 535 cls.interfaces = const Link<DartType>(); | 505 cls.interfaces = const Link<DartType>(); |
| 536 return; | 506 return; |
| 537 } | 507 } |
| 538 cls.supertypeLoadState = STATE_STARTED; | 508 cls.supertypeLoadState = STATE_STARTED; |
| 539 reporter.withCurrentElement(cls, () { | 509 reporter.withCurrentElement(cls, () { |
| 540 // TODO(ahe): Cache the node in cls. | 510 // TODO(ahe): Cache the node in cls. |
| 541 cls.parseNode(parsing).accept( | 511 cls |
| 542 new ClassSupertypeResolver(compiler, cls)); | 512 .parseNode(parsing) |
| 513 .accept(new ClassSupertypeResolver(compiler, cls)); |
| 543 if (cls.supertypeLoadState != STATE_DONE) { | 514 if (cls.supertypeLoadState != STATE_DONE) { |
| 544 cls.supertypeLoadState = STATE_DONE; | 515 cls.supertypeLoadState = STATE_DONE; |
| 545 } | 516 } |
| 546 }); | 517 }); |
| 547 }); | 518 }); |
| 548 } | 519 } |
| 549 | 520 |
| 550 // TODO(johnniwinther): Remove this queue when resolution has been split into | 521 // TODO(johnniwinther): Remove this queue when resolution has been split into |
| 551 // syntax and semantic resolution. | 522 // syntax and semantic resolution. |
| 552 TypeDeclarationElement currentlyResolvedTypeDeclaration; | 523 TypeDeclarationElement currentlyResolvedTypeDeclaration; |
| 553 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); | 524 Queue<ClassElement> pendingClassesToBeResolved = new Queue<ClassElement>(); |
| 554 Queue<ClassElement> pendingClassesToBePostProcessed = | 525 Queue<ClassElement> pendingClassesToBePostProcessed = |
| 555 new Queue<ClassElement>(); | 526 new Queue<ClassElement>(); |
| 556 | 527 |
| 557 /// Resolve [element] using [resolveTypeDeclaration]. | 528 /// Resolve [element] using [resolveTypeDeclaration]. |
| 558 /// | 529 /// |
| 559 /// This methods ensure that class declarations encountered through type | 530 /// This methods ensure that class declarations encountered through type |
| 560 /// annotations during the resolution of [element] are resolved after | 531 /// annotations during the resolution of [element] are resolved after |
| 561 /// [element] has been resolved. | 532 /// [element] has been resolved. |
| 562 // TODO(johnniwinther): Encapsulate this functionality in a | 533 // TODO(johnniwinther): Encapsulate this functionality in a |
| 563 // 'TypeDeclarationResolver'. | 534 // 'TypeDeclarationResolver'. |
| 564 _resolveTypeDeclaration(TypeDeclarationElement element, | 535 _resolveTypeDeclaration( |
| 565 resolveTypeDeclaration()) { | 536 TypeDeclarationElement element, resolveTypeDeclaration()) { |
| 566 return reporter.withCurrentElement(element, () { | 537 return reporter.withCurrentElement(element, () { |
| 567 return measure(() { | 538 return measure(() { |
| 568 TypeDeclarationElement previousResolvedTypeDeclaration = | 539 TypeDeclarationElement previousResolvedTypeDeclaration = |
| 569 currentlyResolvedTypeDeclaration; | 540 currentlyResolvedTypeDeclaration; |
| 570 currentlyResolvedTypeDeclaration = element; | 541 currentlyResolvedTypeDeclaration = element; |
| 571 var result = resolveTypeDeclaration(); | 542 var result = resolveTypeDeclaration(); |
| 572 if (previousResolvedTypeDeclaration == null) { | 543 if (previousResolvedTypeDeclaration == null) { |
| 573 do { | 544 do { |
| 574 while (!pendingClassesToBeResolved.isEmpty) { | 545 while (!pendingClassesToBeResolved.isEmpty) { |
| 575 pendingClassesToBeResolved.removeFirst() | 546 pendingClassesToBeResolved |
| 547 .removeFirst() |
| 576 .ensureResolved(resolution); | 548 .ensureResolved(resolution); |
| 577 } | 549 } |
| 578 while (!pendingClassesToBePostProcessed.isEmpty) { | 550 while (!pendingClassesToBePostProcessed.isEmpty) { |
| 579 _postProcessClassElement( | 551 _postProcessClassElement( |
| 580 pendingClassesToBePostProcessed.removeFirst()); | 552 pendingClassesToBePostProcessed.removeFirst()); |
| 581 } | 553 } |
| 582 } while (!pendingClassesToBeResolved.isEmpty); | 554 } while (!pendingClassesToBeResolved.isEmpty); |
| 583 assert(pendingClassesToBeResolved.isEmpty); | 555 assert(pendingClassesToBeResolved.isEmpty); |
| 584 assert(pendingClassesToBePostProcessed.isEmpty); | 556 assert(pendingClassesToBePostProcessed.isEmpty); |
| 585 } | 557 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 611 } | 583 } |
| 612 | 584 |
| 613 void ensureClassWillBeResolvedInternal(ClassElement element) { | 585 void ensureClassWillBeResolvedInternal(ClassElement element) { |
| 614 if (currentlyResolvedTypeDeclaration == null) { | 586 if (currentlyResolvedTypeDeclaration == null) { |
| 615 element.ensureResolved(resolution); | 587 element.ensureResolved(resolution); |
| 616 } else { | 588 } else { |
| 617 pendingClassesToBeResolved.add(element); | 589 pendingClassesToBeResolved.add(element); |
| 618 } | 590 } |
| 619 } | 591 } |
| 620 | 592 |
| 621 void resolveClassInternal(BaseClassElementX element, | 593 void resolveClassInternal( |
| 622 ResolutionRegistry registry) { | 594 BaseClassElementX element, ResolutionRegistry registry) { |
| 623 if (!element.isPatch) { | 595 if (!element.isPatch) { |
| 624 reporter.withCurrentElement(element, () => measure(() { | 596 reporter.withCurrentElement( |
| 625 assert(element.resolutionState == STATE_NOT_STARTED); | 597 element, |
| 626 element.resolutionState = STATE_STARTED; | 598 () => measure(() { |
| 627 Node tree = element.parseNode(parsing); | 599 assert(element.resolutionState == STATE_NOT_STARTED); |
| 628 loadSupertypes(element, tree); | 600 element.resolutionState = STATE_STARTED; |
| 601 Node tree = element.parseNode(parsing); |
| 602 loadSupertypes(element, tree); |
| 629 | 603 |
| 630 ClassResolverVisitor visitor = | 604 ClassResolverVisitor visitor = |
| 631 new ClassResolverVisitor(compiler, element, registry); | 605 new ClassResolverVisitor(compiler, element, registry); |
| 632 visitor.visit(tree); | 606 visitor.visit(tree); |
| 633 element.resolutionState = STATE_DONE; | 607 element.resolutionState = STATE_DONE; |
| 634 compiler.onClassResolved(element); | 608 compiler.onClassResolved(element); |
| 635 pendingClassesToBePostProcessed.add(element); | 609 pendingClassesToBePostProcessed.add(element); |
| 636 })); | 610 })); |
| 637 if (element.isPatched) { | 611 if (element.isPatched) { |
| 638 // Ensure handling patch after origin. | 612 // Ensure handling patch after origin. |
| 639 element.patch.ensureResolved(resolution); | 613 element.patch.ensureResolved(resolution); |
| 640 } | 614 } |
| 641 } else { // Handle patch classes: | 615 } else { |
| 616 // Handle patch classes: |
| 642 element.resolutionState = STATE_STARTED; | 617 element.resolutionState = STATE_STARTED; |
| 643 // Ensure handling origin before patch. | 618 // Ensure handling origin before patch. |
| 644 element.origin.ensureResolved(resolution); | 619 element.origin.ensureResolved(resolution); |
| 645 // Ensure that the type is computed. | 620 // Ensure that the type is computed. |
| 646 element.computeType(resolution); | 621 element.computeType(resolution); |
| 647 // Copy class hierarchy from origin. | 622 // Copy class hierarchy from origin. |
| 648 element.supertype = element.origin.supertype; | 623 element.supertype = element.origin.supertype; |
| 649 element.interfaces = element.origin.interfaces; | 624 element.interfaces = element.origin.interfaces; |
| 650 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf; | 625 element.allSupertypesAndSelf = element.origin.allSupertypesAndSelf; |
| 651 // Stepwise assignment to ensure invariant. | 626 // Stepwise assignment to ensure invariant. |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 | 690 |
| 716 // In case of cyclic mixin applications, the mixin chain will have | 691 // In case of cyclic mixin applications, the mixin chain will have |
| 717 // been cut. If so, we have already reported the error to the | 692 // been cut. If so, we have already reported the error to the |
| 718 // user so we just return from here. | 693 // user so we just return from here. |
| 719 ClassElement mixin = mixinApplication.mixin; | 694 ClassElement mixin = mixinApplication.mixin; |
| 720 if (mixin == null) return; | 695 if (mixin == null) return; |
| 721 | 696 |
| 722 // Check that we're not trying to use Object as a mixin. | 697 // Check that we're not trying to use Object as a mixin. |
| 723 if (mixin.superclass == null) { | 698 if (mixin.superclass == null) { |
| 724 reporter.reportErrorMessage( | 699 reporter.reportErrorMessage( |
| 725 mixinApplication, | 700 mixinApplication, MessageKind.ILLEGAL_MIXIN_OBJECT); |
| 726 MessageKind.ILLEGAL_MIXIN_OBJECT); | |
| 727 // Avoid reporting additional errors for the Object class. | 701 // Avoid reporting additional errors for the Object class. |
| 728 return; | 702 return; |
| 729 } | 703 } |
| 730 | 704 |
| 731 if (mixin.isEnumClass) { | 705 if (mixin.isEnumClass) { |
| 732 // Mixing in an enum has already caused a compile-time error. | 706 // Mixing in an enum has already caused a compile-time error. |
| 733 return; | 707 return; |
| 734 } | 708 } |
| 735 | 709 |
| 736 // Check that the mixed in class has Object as its superclass. | 710 // Check that the mixed in class has Object as its superclass. |
| 737 if (!mixin.superclass.isObject) { | 711 if (!mixin.superclass.isObject) { |
| 738 reporter.reportErrorMessage( | 712 reporter.reportErrorMessage(mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); |
| 739 mixin, MessageKind.ILLEGAL_MIXIN_SUPERCLASS); | |
| 740 } | 713 } |
| 741 | 714 |
| 742 // Check that the mixed in class doesn't have any constructors and | 715 // Check that the mixed in class doesn't have any constructors and |
| 743 // make sure we aren't mixing in methods that use 'super'. | 716 // make sure we aren't mixing in methods that use 'super'. |
| 744 mixin.forEachLocalMember((AstElement member) { | 717 mixin.forEachLocalMember((AstElement member) { |
| 745 if (member.isGenerativeConstructor && !member.isSynthesized) { | 718 if (member.isGenerativeConstructor && !member.isSynthesized) { |
| 746 reporter.reportErrorMessage( | 719 reporter.reportErrorMessage( |
| 747 member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); | 720 member, MessageKind.ILLEGAL_MIXIN_CONSTRUCTOR); |
| 748 } else { | 721 } else { |
| 749 // Get the resolution tree and check that the resolved member | 722 // Get the resolution tree and check that the resolved member |
| 750 // doesn't use 'super'. This is the part of the 'super' mixin | 723 // doesn't use 'super'. This is the part of the 'super' mixin |
| 751 // check that happens when a function is resolved before the | 724 // check that happens when a function is resolved before the |
| 752 // mixin application has been performed. | 725 // mixin application has been performed. |
| 753 // TODO(johnniwinther): Obtain the [TreeElements] for [member] | 726 // TODO(johnniwinther): Obtain the [TreeElements] for [member] |
| 754 // differently. | 727 // differently. |
| 755 if (compiler.enqueuer.resolution.hasBeenProcessed(member)) { | 728 if (compiler.enqueuer.resolution.hasBeenProcessed(member)) { |
| 756 checkMixinSuperUses( | 729 checkMixinSuperUses( |
| 757 member.resolvedAst.elements, | 730 member.resolvedAst.elements, mixinApplication, mixin); |
| 758 mixinApplication, | |
| 759 mixin); | |
| 760 } | 731 } |
| 761 } | 732 } |
| 762 }); | 733 }); |
| 763 } | 734 } |
| 764 | 735 |
| 765 void checkMixinSuperUses(TreeElements resolutionTree, | 736 void checkMixinSuperUses(TreeElements resolutionTree, |
| 766 MixinApplicationElement mixinApplication, | 737 MixinApplicationElement mixinApplication, ClassElement mixin) { |
| 767 ClassElement mixin) { | |
| 768 // TODO(johnniwinther): Avoid the use of [TreeElements] here. | 738 // TODO(johnniwinther): Avoid the use of [TreeElements] here. |
| 769 if (resolutionTree == null) return; | 739 if (resolutionTree == null) return; |
| 770 Iterable<SourceSpan> superUses = resolutionTree.superUses; | 740 Iterable<SourceSpan> superUses = resolutionTree.superUses; |
| 771 if (superUses.isEmpty) return; | 741 if (superUses.isEmpty) return; |
| 772 DiagnosticMessage error = reporter.createMessage( | 742 DiagnosticMessage error = reporter.createMessage(mixinApplication, |
| 773 mixinApplication, | 743 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, {'className': mixin.name}); |
| 774 MessageKind.ILLEGAL_MIXIN_WITH_SUPER, | |
| 775 {'className': mixin.name}); | |
| 776 // Show the user the problematic uses of 'super' in the mixin. | 744 // Show the user the problematic uses of 'super' in the mixin. |
| 777 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 745 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 778 for (SourceSpan use in superUses) { | 746 for (SourceSpan use in superUses) { |
| 779 infos.add(reporter.createMessage( | 747 infos.add( |
| 780 use, | 748 reporter.createMessage(use, MessageKind.ILLEGAL_MIXIN_SUPER_USE)); |
| 781 MessageKind.ILLEGAL_MIXIN_SUPER_USE)); | |
| 782 } | 749 } |
| 783 reporter.reportError(error, infos); | 750 reporter.reportError(error, infos); |
| 784 } | 751 } |
| 785 | 752 |
| 786 void checkClassMembers(ClassElement cls) { | 753 void checkClassMembers(ClassElement cls) { |
| 787 assert(invariant(cls, cls.isDeclaration)); | 754 assert(invariant(cls, cls.isDeclaration)); |
| 788 if (cls.isObject) return; | 755 if (cls.isObject) return; |
| 789 // TODO(johnniwinther): Should this be done on the implementation element as | 756 // TODO(johnniwinther): Should this be done on the implementation element as |
| 790 // well? | 757 // well? |
| 791 List<Element> constConstructors = <Element>[]; | 758 List<Element> constConstructors = <Element>[]; |
| 792 List<Element> nonFinalInstanceFields = <Element>[]; | 759 List<Element> nonFinalInstanceFields = <Element>[]; |
| 793 cls.forEachMember((holder, member) { | 760 cls.forEachMember((holder, member) { |
| 794 reporter.withCurrentElement(member, () { | 761 reporter.withCurrentElement(member, () { |
| 795 // Perform various checks as side effect of "computing" the type. | 762 // Perform various checks as side effect of "computing" the type. |
| 796 member.computeType(resolution); | 763 member.computeType(resolution); |
| 797 | 764 |
| 798 // Check modifiers. | 765 // Check modifiers. |
| 799 if (member.isFunction && member.modifiers.isFinal) { | 766 if (member.isFunction && member.modifiers.isFinal) { |
| 800 reporter.reportErrorMessage( | 767 reporter.reportErrorMessage( |
| 801 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); | 768 member, MessageKind.ILLEGAL_FINAL_METHOD_MODIFIER); |
| 802 } | 769 } |
| 803 if (member.isConstructor) { | 770 if (member.isConstructor) { |
| 804 final mismatchedFlagsBits = | 771 final mismatchedFlagsBits = member.modifiers.flags & |
| 805 member.modifiers.flags & | |
| 806 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); | 772 (Modifiers.FLAG_STATIC | Modifiers.FLAG_ABSTRACT); |
| 807 if (mismatchedFlagsBits != 0) { | 773 if (mismatchedFlagsBits != 0) { |
| 808 final mismatchedFlags = | 774 final mismatchedFlags = |
| 809 new Modifiers.withFlags(null, mismatchedFlagsBits); | 775 new Modifiers.withFlags(null, mismatchedFlagsBits); |
| 810 reporter.reportErrorMessage( | 776 reporter.reportErrorMessage( |
| 811 member, | 777 member, |
| 812 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, | 778 MessageKind.ILLEGAL_CONSTRUCTOR_MODIFIERS, |
| 813 {'modifiers': mismatchedFlags}); | 779 {'modifiers': mismatchedFlags}); |
| 814 } | 780 } |
| 815 if (member.modifiers.isConst) { | 781 if (member.modifiers.isConst) { |
| 816 constConstructors.add(member); | 782 constConstructors.add(member); |
| 817 } | 783 } |
| 818 } | 784 } |
| 819 if (member.isField) { | 785 if (member.isField) { |
| 820 if (member.modifiers.isConst && !member.modifiers.isStatic) { | 786 if (member.modifiers.isConst && !member.modifiers.isStatic) { |
| 821 reporter.reportErrorMessage( | 787 reporter.reportErrorMessage( |
| 822 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER); | 788 member, MessageKind.ILLEGAL_CONST_FIELD_MODIFIER); |
| 823 } | 789 } |
| 824 if (!member.modifiers.isStatic && !member.modifiers.isFinal) { | 790 if (!member.modifiers.isStatic && !member.modifiers.isFinal) { |
| 825 nonFinalInstanceFields.add(member); | 791 nonFinalInstanceFields.add(member); |
| 826 } | 792 } |
| 827 } | 793 } |
| 828 checkAbstractField(member); | 794 checkAbstractField(member); |
| 829 checkUserDefinableOperator(member); | 795 checkUserDefinableOperator(member); |
| 830 }); | 796 }); |
| 831 }); | 797 }); |
| 832 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { | 798 if (!constConstructors.isEmpty && !nonFinalInstanceFields.isEmpty) { |
| 833 Spannable span = constConstructors.length > 1 | 799 Spannable span = |
| 834 ? cls : constConstructors[0]; | 800 constConstructors.length > 1 ? cls : constConstructors[0]; |
| 835 DiagnosticMessage error = reporter.createMessage( | 801 DiagnosticMessage error = reporter.createMessage( |
| 836 span, | 802 span, |
| 837 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, | 803 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS, |
| 838 {'className': cls.name}); | 804 {'className': cls.name}); |
| 839 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 805 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 840 if (constConstructors.length > 1) { | 806 if (constConstructors.length > 1) { |
| 841 for (Element constructor in constConstructors) { | 807 for (Element constructor in constConstructors) { |
| 842 infos.add(reporter.createMessage( | 808 infos.add(reporter.createMessage(constructor, |
| 843 constructor, | |
| 844 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR)); | 809 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_CONSTRUCTOR)); |
| 845 } | 810 } |
| 846 } | 811 } |
| 847 for (Element field in nonFinalInstanceFields) { | 812 for (Element field in nonFinalInstanceFields) { |
| 848 infos.add(reporter.createMessage( | 813 infos.add(reporter.createMessage( |
| 849 field, | 814 field, MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD)); |
| 850 MessageKind.CONST_CONSTRUCTOR_WITH_NONFINAL_FIELDS_FIELD)); | |
| 851 } | 815 } |
| 852 reporter.reportError(error, infos); | 816 reporter.reportError(error, infos); |
| 853 } | 817 } |
| 854 } | 818 } |
| 855 | 819 |
| 856 void checkAbstractField(Element member) { | 820 void checkAbstractField(Element member) { |
| 857 // Only check for getters. The test can only fail if there is both a setter | 821 // Only check for getters. The test can only fail if there is both a setter |
| 858 // and a getter with the same name, and we only need to check each abstract | 822 // and a getter with the same name, and we only need to check each abstract |
| 859 // field once, so we just ignore setters. | 823 // field once, so we just ignore setters. |
| 860 if (!member.isGetter) return; | 824 if (!member.isGetter) return; |
| 861 | 825 |
| 862 // Find the associated abstract field. | 826 // Find the associated abstract field. |
| 863 ClassElement classElement = member.enclosingClass; | 827 ClassElement classElement = member.enclosingClass; |
| 864 Element lookupElement = classElement.lookupLocalMember(member.name); | 828 Element lookupElement = classElement.lookupLocalMember(member.name); |
| 865 if (lookupElement == null) { | 829 if (lookupElement == null) { |
| 866 reporter.internalError(member, | 830 reporter.internalError(member, "No abstract field for accessor"); |
| 867 "No abstract field for accessor"); | |
| 868 } else if (!lookupElement.isAbstractField) { | 831 } else if (!lookupElement.isAbstractField) { |
| 869 if (lookupElement.isMalformed || lookupElement.isAmbiguous) return; | 832 if (lookupElement.isMalformed || lookupElement.isAmbiguous) return; |
| 870 reporter.internalError(member, | 833 reporter.internalError( |
| 871 "Inaccessible abstract field for accessor"); | 834 member, "Inaccessible abstract field for accessor"); |
| 872 } | 835 } |
| 873 AbstractFieldElement field = lookupElement; | 836 AbstractFieldElement field = lookupElement; |
| 874 | 837 |
| 875 GetterElementX getter = field.getter; | 838 GetterElementX getter = field.getter; |
| 876 if (getter == null) return; | 839 if (getter == null) return; |
| 877 SetterElementX setter = field.setter; | 840 SetterElementX setter = field.setter; |
| 878 if (setter == null) return; | 841 if (setter == null) return; |
| 879 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 842 int getterFlags = getter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
| 880 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; | 843 int setterFlags = setter.modifiers.flags | Modifiers.FLAG_ABSTRACT; |
| 881 if (getterFlags != setterFlags) { | 844 if (getterFlags != setterFlags) { |
| 882 final mismatchedFlags = | 845 final mismatchedFlags = |
| 883 new Modifiers.withFlags(null, getterFlags ^ setterFlags); | 846 new Modifiers.withFlags(null, getterFlags ^ setterFlags); |
| 884 reporter.reportWarningMessage( | 847 reporter.reportWarningMessage(field.getter, MessageKind.GETTER_MISMATCH, |
| 885 field.getter, | |
| 886 MessageKind.GETTER_MISMATCH, | |
| 887 {'modifiers': mismatchedFlags}); | 848 {'modifiers': mismatchedFlags}); |
| 888 reporter.reportWarningMessage( | 849 reporter.reportWarningMessage(field.setter, MessageKind.SETTER_MISMATCH, |
| 889 field.setter, | |
| 890 MessageKind.SETTER_MISMATCH, | |
| 891 {'modifiers': mismatchedFlags}); | 850 {'modifiers': mismatchedFlags}); |
| 892 } | 851 } |
| 893 } | 852 } |
| 894 | 853 |
| 895 void checkUserDefinableOperator(Element member) { | 854 void checkUserDefinableOperator(Element member) { |
| 896 FunctionElement function = member.asFunctionElement(); | 855 FunctionElement function = member.asFunctionElement(); |
| 897 if (function == null) return; | 856 if (function == null) return; |
| 898 String value = member.name; | 857 String value = member.name; |
| 899 if (value == null) return; | 858 if (value == null) return; |
| 900 if (!(isUserDefinableOperator(value) || identical(value, 'unary-'))) return; | 859 if (!(isUserDefinableOperator(value) || identical(value, 'unary-'))) return; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 914 messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY; | 873 messageKind = MessageKind.UNARY_OPERATOR_BAD_ARITY; |
| 915 requiredParameterCount = 0; | 874 requiredParameterCount = 0; |
| 916 } else if (isBinaryOperator(value)) { | 875 } else if (isBinaryOperator(value)) { |
| 917 messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY; | 876 messageKind = MessageKind.BINARY_OPERATOR_BAD_ARITY; |
| 918 requiredParameterCount = 1; | 877 requiredParameterCount = 1; |
| 919 if (identical(value, '==')) checkOverrideHashCode(member); | 878 if (identical(value, '==')) checkOverrideHashCode(member); |
| 920 } else if (isTernaryOperator(value)) { | 879 } else if (isTernaryOperator(value)) { |
| 921 messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY; | 880 messageKind = MessageKind.TERNARY_OPERATOR_BAD_ARITY; |
| 922 requiredParameterCount = 2; | 881 requiredParameterCount = 2; |
| 923 } else { | 882 } else { |
| 924 reporter.internalError(function, | 883 reporter.internalError( |
| 925 'Unexpected user defined operator $value'); | 884 function, 'Unexpected user defined operator $value'); |
| 926 } | 885 } |
| 927 checkArity(function, requiredParameterCount, messageKind, isMinus); | 886 checkArity(function, requiredParameterCount, messageKind, isMinus); |
| 928 } | 887 } |
| 929 | 888 |
| 930 void checkOverrideHashCode(FunctionElement operatorEquals) { | 889 void checkOverrideHashCode(FunctionElement operatorEquals) { |
| 931 if (operatorEquals.isAbstract) return; | 890 if (operatorEquals.isAbstract) return; |
| 932 ClassElement cls = operatorEquals.enclosingClass; | 891 ClassElement cls = operatorEquals.enclosingClass; |
| 933 Element hashCodeImplementation = | 892 Element hashCodeImplementation = cls.lookupLocalMember('hashCode'); |
| 934 cls.lookupLocalMember('hashCode'); | |
| 935 if (hashCodeImplementation != null) return; | 893 if (hashCodeImplementation != null) return; |
| 936 reporter.reportHintMessage( | 894 reporter.reportHintMessage(operatorEquals, |
| 937 operatorEquals, MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, | 895 MessageKind.OVERRIDE_EQUALS_NOT_HASH_CODE, {'class': cls.name}); |
| 938 {'class': cls.name}); | |
| 939 } | 896 } |
| 940 | 897 |
| 941 void checkArity(FunctionElement function, | 898 void checkArity(FunctionElement function, int requiredParameterCount, |
| 942 int requiredParameterCount, MessageKind messageKind, | 899 MessageKind messageKind, bool isMinus) { |
| 943 bool isMinus) { | |
| 944 FunctionExpression node = function.node; | 900 FunctionExpression node = function.node; |
| 945 FunctionSignature signature = function.functionSignature; | 901 FunctionSignature signature = function.functionSignature; |
| 946 if (signature.requiredParameterCount != requiredParameterCount) { | 902 if (signature.requiredParameterCount != requiredParameterCount) { |
| 947 Node errorNode = node; | 903 Node errorNode = node; |
| 948 if (node.parameters != null) { | 904 if (node.parameters != null) { |
| 949 if (isMinus || | 905 if (isMinus || |
| 950 signature.requiredParameterCount < requiredParameterCount) { | 906 signature.requiredParameterCount < requiredParameterCount) { |
| 951 // If there are too few parameters, point to the whole parameter list. | 907 // If there are too few parameters, point to the whole parameter list. |
| 952 // For instance | 908 // For instance |
| 953 // | 909 // |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 {'operatorName': function.name}); | 943 {'operatorName': function.name}); |
| 988 } else { | 944 } else { |
| 989 reporter.reportErrorMessage( | 945 reporter.reportErrorMessage( |
| 990 errorNode, | 946 errorNode, |
| 991 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, | 947 MessageKind.OPERATOR_OPTIONAL_PARAMETERS, |
| 992 {'operatorName': function.name}); | 948 {'operatorName': function.name}); |
| 993 } | 949 } |
| 994 } | 950 } |
| 995 } | 951 } |
| 996 | 952 |
| 997 reportErrorWithContext(Element errorneousElement, | 953 reportErrorWithContext(Element errorneousElement, MessageKind errorMessage, |
| 998 MessageKind errorMessage, | 954 Element contextElement, MessageKind contextMessage) { |
| 999 Element contextElement, | |
| 1000 MessageKind contextMessage) { | |
| 1001 reporter.reportError( | 955 reporter.reportError( |
| 1002 reporter.createMessage( | 956 reporter.createMessage(errorneousElement, errorMessage, { |
| 1003 errorneousElement, | 957 'memberName': contextElement.name, |
| 1004 errorMessage, | 958 'className': contextElement.enclosingClass.name |
| 1005 {'memberName': contextElement.name, | 959 }), |
| 1006 'className': contextElement.enclosingClass.name}), | |
| 1007 <DiagnosticMessage>[ | 960 <DiagnosticMessage>[ |
| 1008 reporter.createMessage(contextElement, contextMessage), | 961 reporter.createMessage(contextElement, contextMessage), |
| 1009 ]); | 962 ]); |
| 1010 } | 963 } |
| 1011 | 964 |
| 1012 | |
| 1013 FunctionSignature resolveSignature(FunctionElementX element) { | 965 FunctionSignature resolveSignature(FunctionElementX element) { |
| 1014 MessageKind defaultValuesError = null; | 966 MessageKind defaultValuesError = null; |
| 1015 if (element.isFactoryConstructor) { | 967 if (element.isFactoryConstructor) { |
| 1016 FunctionExpression body = element.parseNode(parsing); | 968 FunctionExpression body = element.parseNode(parsing); |
| 1017 if (body.isRedirectingFactory) { | 969 if (body.isRedirectingFactory) { |
| 1018 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; | 970 defaultValuesError = MessageKind.REDIRECTING_FACTORY_WITH_DEFAULT; |
| 1019 } | 971 } |
| 1020 } | 972 } |
| 1021 return reporter.withCurrentElement(element, () { | 973 return reporter.withCurrentElement(element, () { |
| 1022 FunctionExpression node = element.parseNode(parsing); | 974 FunctionExpression node = element.parseNode(parsing); |
| 1023 return measure(() => SignatureResolver.analyze( | 975 return measure(() => SignatureResolver.analyze( |
| 1024 compiler, node.parameters, node.returnType, element, | 976 compiler, |
| 977 node.parameters, |
| 978 node.returnType, |
| 979 element, |
| 1025 new ResolutionRegistry(compiler, _ensureTreeElements(element)), | 980 new ResolutionRegistry(compiler, _ensureTreeElements(element)), |
| 1026 defaultValuesError: defaultValuesError, | 981 defaultValuesError: defaultValuesError, |
| 1027 createRealParameters: true)); | 982 createRealParameters: true)); |
| 1028 }); | 983 }); |
| 1029 } | 984 } |
| 1030 | 985 |
| 1031 WorldImpact resolveTypedef(TypedefElementX element) { | 986 WorldImpact resolveTypedef(TypedefElementX element) { |
| 1032 if (element.isResolved) return const ResolutionImpact(); | 987 if (element.isResolved) return const ResolutionImpact(); |
| 1033 compiler.world.allTypedefs.add(element); | 988 compiler.world.allTypedefs.add(element); |
| 1034 return _resolveTypeDeclaration(element, () { | 989 return _resolveTypeDeclaration(element, () { |
| 1035 ResolutionRegistry registry = new ResolutionRegistry( | 990 ResolutionRegistry registry = |
| 1036 compiler, _ensureTreeElements(element)); | 991 new ResolutionRegistry(compiler, _ensureTreeElements(element)); |
| 1037 return reporter.withCurrentElement(element, () { | 992 return reporter.withCurrentElement(element, () { |
| 1038 return measure(() { | 993 return measure(() { |
| 1039 assert(element.resolutionState == STATE_NOT_STARTED); | 994 assert(element.resolutionState == STATE_NOT_STARTED); |
| 1040 element.resolutionState = STATE_STARTED; | 995 element.resolutionState = STATE_STARTED; |
| 1041 Typedef node = element.parseNode(parsing); | 996 Typedef node = element.parseNode(parsing); |
| 1042 TypedefResolverVisitor visitor = | 997 TypedefResolverVisitor visitor = |
| 1043 new TypedefResolverVisitor(compiler, element, registry); | 998 new TypedefResolverVisitor(compiler, element, registry); |
| 1044 visitor.visit(node); | 999 visitor.visit(node); |
| 1045 element.resolutionState = STATE_DONE; | 1000 element.resolutionState = STATE_DONE; |
| 1046 return registry.worldImpact; | 1001 return registry.worldImpact; |
| 1047 }); | 1002 }); |
| 1048 }); | 1003 }); |
| 1049 }); | 1004 }); |
| 1050 } | 1005 } |
| 1051 | 1006 |
| 1052 void resolveMetadataAnnotation(MetadataAnnotationX annotation) { | 1007 void resolveMetadataAnnotation(MetadataAnnotationX annotation) { |
| 1053 reporter.withCurrentElement(annotation.annotatedElement, () => measure(() { | 1008 reporter.withCurrentElement( |
| 1054 assert(annotation.resolutionState == STATE_NOT_STARTED); | 1009 annotation.annotatedElement, |
| 1055 annotation.resolutionState = STATE_STARTED; | 1010 () => measure(() { |
| 1011 assert(annotation.resolutionState == STATE_NOT_STARTED); |
| 1012 annotation.resolutionState = STATE_STARTED; |
| 1056 | 1013 |
| 1057 Node node = annotation.parseNode(parsing); | 1014 Node node = annotation.parseNode(parsing); |
| 1058 Element annotatedElement = annotation.annotatedElement; | 1015 Element annotatedElement = annotation.annotatedElement; |
| 1059 AnalyzableElement context = annotatedElement.analyzableElement; | 1016 AnalyzableElement context = annotatedElement.analyzableElement; |
| 1060 ClassElement classElement = annotatedElement.enclosingClass; | 1017 ClassElement classElement = annotatedElement.enclosingClass; |
| 1061 if (classElement != null) { | 1018 if (classElement != null) { |
| 1062 // The annotation is resolved in the scope of [classElement]. | 1019 // The annotation is resolved in the scope of [classElement]. |
| 1063 classElement.ensureResolved(resolution); | 1020 classElement.ensureResolved(resolution); |
| 1064 } | 1021 } |
| 1065 assert(invariant(node, context != null, | 1022 assert(invariant(node, context != null, |
| 1066 message: "No context found for metadata annotation " | 1023 message: "No context found for metadata annotation " |
| 1067 "on $annotatedElement.")); | 1024 "on $annotatedElement.")); |
| 1068 ResolverVisitor visitor = visitorFor(context, useEnclosingScope: true); | 1025 ResolverVisitor visitor = |
| 1069 ResolutionRegistry registry = visitor.registry; | 1026 visitorFor(context, useEnclosingScope: true); |
| 1070 node.accept(visitor); | 1027 ResolutionRegistry registry = visitor.registry; |
| 1071 // TODO(johnniwinther): Avoid passing the [TreeElements] to | 1028 node.accept(visitor); |
| 1072 // [compileMetadata]. | 1029 // TODO(johnniwinther): Avoid passing the [TreeElements] to |
| 1073 ConstantExpression constant = constantCompiler.compileMetadata( | 1030 // [compileMetadata]. |
| 1074 annotation, node, registry.mapping); | 1031 ConstantExpression constant = constantCompiler.compileMetadata( |
| 1075 switch (constant.kind) { | 1032 annotation, node, registry.mapping); |
| 1076 case ConstantExpressionKind.CONSTRUCTED: | 1033 switch (constant.kind) { |
| 1077 ConstructedConstantExpression constructedConstant = constant; | 1034 case ConstantExpressionKind.CONSTRUCTED: |
| 1078 if (constructedConstant.type.isGeneric) { | 1035 ConstructedConstantExpression constructedConstant = constant; |
| 1079 // Const constructor calls cannot have type arguments. | 1036 if (constructedConstant.type.isGeneric) { |
| 1080 // TODO(24312): Remove this. | 1037 // Const constructor calls cannot have type arguments. |
| 1081 reporter.reportErrorMessage( | 1038 // TODO(24312): Remove this. |
| 1082 node, MessageKind.INVALID_METADATA_GENERIC); | 1039 reporter.reportErrorMessage( |
| 1083 constant = new ErroneousConstantExpression(); | 1040 node, MessageKind.INVALID_METADATA_GENERIC); |
| 1084 } | 1041 constant = new ErroneousConstantExpression(); |
| 1085 break; | 1042 } |
| 1086 case ConstantExpressionKind.VARIABLE: | 1043 break; |
| 1087 case ConstantExpressionKind.ERRONEOUS: | 1044 case ConstantExpressionKind.VARIABLE: |
| 1088 break; | 1045 case ConstantExpressionKind.ERRONEOUS: |
| 1089 default: | 1046 break; |
| 1090 reporter.reportErrorMessage(node, MessageKind.INVALID_METADATA); | 1047 default: |
| 1091 constant = new ErroneousConstantExpression(); | 1048 reporter.reportErrorMessage( |
| 1092 break; | 1049 node, MessageKind.INVALID_METADATA); |
| 1093 } | 1050 constant = new ErroneousConstantExpression(); |
| 1094 annotation.constant = constant; | 1051 break; |
| 1052 } |
| 1053 annotation.constant = constant; |
| 1095 | 1054 |
| 1096 constantCompiler.evaluate(annotation.constant); | 1055 constantCompiler.evaluate(annotation.constant); |
| 1097 // TODO(johnniwinther): Register the relation between the annotation | 1056 // TODO(johnniwinther): Register the relation between the annotati
on |
| 1098 // and the annotated element instead. This will allow the backend to | 1057 // and the annotated element instead. This will allow the backend
to |
| 1099 // retrieve the backend constant and only register metadata on the | 1058 // retrieve the backend constant and only register metadata on the |
| 1100 // elements for which it is needed. (Issue 17732). | 1059 // elements for which it is needed. (Issue 17732). |
| 1101 registry.registerMetadataConstant(annotation); | 1060 registry.registerMetadataConstant(annotation); |
| 1102 annotation.resolutionState = STATE_DONE; | 1061 annotation.resolutionState = STATE_DONE; |
| 1103 })); | 1062 })); |
| 1104 } | 1063 } |
| 1105 | 1064 |
| 1106 List<MetadataAnnotation> resolveMetadata(Element element, | 1065 List<MetadataAnnotation> resolveMetadata( |
| 1107 VariableDefinitions node) { | 1066 Element element, VariableDefinitions node) { |
| 1108 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; | 1067 List<MetadataAnnotation> metadata = <MetadataAnnotation>[]; |
| 1109 for (Metadata annotation in node.metadata.nodes) { | 1068 for (Metadata annotation in node.metadata.nodes) { |
| 1110 ParameterMetadataAnnotation metadataAnnotation = | 1069 ParameterMetadataAnnotation metadataAnnotation = |
| 1111 new ParameterMetadataAnnotation(annotation); | 1070 new ParameterMetadataAnnotation(annotation); |
| 1112 metadataAnnotation.annotatedElement = element; | 1071 metadataAnnotation.annotatedElement = element; |
| 1113 metadata.add(metadataAnnotation.ensureResolved(resolution)); | 1072 metadata.add(metadataAnnotation.ensureResolved(resolution)); |
| 1114 } | 1073 } |
| 1115 return metadata; | 1074 return metadata; |
| 1116 } | 1075 } |
| 1117 } | 1076 } |
| 1118 | 1077 |
| 1119 TreeElements _ensureTreeElements(AnalyzableElementX element) { | 1078 TreeElements _ensureTreeElements(AnalyzableElementX element) { |
| 1120 if (element._treeElements == null) { | 1079 if (element._treeElements == null) { |
| 1121 element._treeElements = new TreeElementMapping(element); | 1080 element._treeElements = new TreeElementMapping(element); |
| 1122 } | 1081 } |
| 1123 return element._treeElements; | 1082 return element._treeElements; |
| 1124 } | 1083 } |
| 1125 | 1084 |
| 1126 abstract class AnalyzableElementX implements AnalyzableElement { | 1085 abstract class AnalyzableElementX implements AnalyzableElement { |
| 1127 TreeElements _treeElements; | 1086 TreeElements _treeElements; |
| 1128 | 1087 |
| 1129 bool get hasTreeElements => _treeElements != null; | 1088 bool get hasTreeElements => _treeElements != null; |
| 1130 | 1089 |
| 1131 TreeElements get treeElements { | 1090 TreeElements get treeElements { |
| 1132 assert(invariant(this, _treeElements !=null, | 1091 assert(invariant(this, _treeElements != null, |
| 1133 message: "TreeElements have not been computed for $this.")); | 1092 message: "TreeElements have not been computed for $this.")); |
| 1134 return _treeElements; | 1093 return _treeElements; |
| 1135 } | 1094 } |
| 1136 | 1095 |
| 1137 void reuseElement() { | 1096 void reuseElement() { |
| 1138 _treeElements = null; | 1097 _treeElements = null; |
| 1139 } | 1098 } |
| 1140 } | 1099 } |
| OLD | NEW |