| 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.typechecker; | 5 library dart2js.typechecker; | 
| 6 | 6 | 
| 7 import 'common/names.dart' show | 7 import 'common/names.dart' show | 
| 8     Identifiers; | 8     Identifiers; | 
| 9 import 'common/resolution.dart' show | 9 import 'common/resolution.dart' show | 
| 10     Resolution; | 10     Resolution; | 
| 11 import 'common/tasks.dart' show | 11 import 'common/tasks.dart' show | 
| 12     CompilerTask; | 12     CompilerTask; | 
| 13 import 'compiler.dart' show | 13 import 'compiler.dart' show | 
| 14     Compiler; | 14     Compiler; | 
| 15 import 'constants/expressions.dart'; | 15 import 'constants/expressions.dart'; | 
| 16 import 'constants/values.dart'; | 16 import 'constants/values.dart'; | 
| 17 import 'core_types.dart'; | 17 import 'core_types.dart'; | 
| 18 import 'dart_types.dart'; | 18 import 'dart_types.dart'; | 
| 19 import 'diagnostics/diagnostic_listener.dart' show | 19 import 'diagnostics/diagnostic_listener.dart' show | 
| 20     DiagnosticMessage; | 20     DiagnosticMessage, | 
|  | 21     DiagnosticReporter; | 
| 21 import 'diagnostics/invariant.dart' show | 22 import 'diagnostics/invariant.dart' show | 
| 22     invariant; | 23     invariant; | 
| 23 import 'diagnostics/messages.dart'; | 24 import 'diagnostics/messages.dart'; | 
| 24 import 'diagnostics/spannable.dart' show | 25 import 'diagnostics/spannable.dart' show | 
| 25     Spannable; | 26     Spannable; | 
| 26 import 'elements/elements.dart' show | 27 import 'elements/elements.dart' show | 
| 27     AbstractFieldElement, | 28     AbstractFieldElement, | 
| 28     AstElement, | 29     AstElement, | 
| 29     AsyncMarker, | 30     AsyncMarker, | 
| 30     ClassElement, | 31     ClassElement, | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
| 61 import '../compiler_new.dart' as api; | 62 import '../compiler_new.dart' as api; | 
| 62 | 63 | 
| 63 class TypeCheckerTask extends CompilerTask { | 64 class TypeCheckerTask extends CompilerTask { | 
| 64   TypeCheckerTask(Compiler compiler) : super(compiler); | 65   TypeCheckerTask(Compiler compiler) : super(compiler); | 
| 65   String get name => "Type checker"; | 66   String get name => "Type checker"; | 
| 66 | 67 | 
| 67   void check(AstElement element) { | 68   void check(AstElement element) { | 
| 68     if (element.isClass) return; | 69     if (element.isClass) return; | 
| 69     if (element.isTypedef) return; | 70     if (element.isTypedef) return; | 
| 70     ResolvedAst resolvedAst = element.resolvedAst; | 71     ResolvedAst resolvedAst = element.resolvedAst; | 
| 71     compiler.withCurrentElement(element.implementation, () { | 72     reporter.withCurrentElement(element.implementation, () { | 
| 72       measure(() { | 73       measure(() { | 
| 73         TypeCheckerVisitor visitor = new TypeCheckerVisitor( | 74         TypeCheckerVisitor visitor = new TypeCheckerVisitor( | 
| 74             compiler, resolvedAst.elements, compiler.types); | 75             compiler, resolvedAst.elements, compiler.types); | 
| 75         if (element.isField) { | 76         if (element.isField) { | 
| 76           visitor.analyzingInitializer = true; | 77           visitor.analyzingInitializer = true; | 
| 77         } | 78         } | 
| 78         resolvedAst.node.accept(visitor); | 79         resolvedAst.node.accept(visitor); | 
| 79       }); | 80       }); | 
| 80     }); | 81     }); | 
| 81   } | 82   } | 
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 299   Node lastSeenNode; | 300   Node lastSeenNode; | 
| 300   DartType expectedReturnType; | 301   DartType expectedReturnType; | 
| 301   AsyncMarker currentAsyncMarker = AsyncMarker.SYNC; | 302   AsyncMarker currentAsyncMarker = AsyncMarker.SYNC; | 
| 302 | 303 | 
| 303   final ClassElement currentClass; | 304   final ClassElement currentClass; | 
| 304 | 305 | 
| 305   /// The immediately enclosing field, method or constructor being analyzed. | 306   /// The immediately enclosing field, method or constructor being analyzed. | 
| 306   ExecutableElement executableContext; | 307   ExecutableElement executableContext; | 
| 307 | 308 | 
| 308   CoreTypes get coreTypes => compiler.coreTypes; | 309   CoreTypes get coreTypes => compiler.coreTypes; | 
|  | 310 | 
|  | 311   DiagnosticReporter get reporter => compiler.reporter; | 
|  | 312 | 
| 309   Resolution get resolution => compiler.resolution; | 313   Resolution get resolution => compiler.resolution; | 
| 310 | 314 | 
| 311   InterfaceType get intType => coreTypes.intType; | 315   InterfaceType get intType => coreTypes.intType; | 
| 312   InterfaceType get doubleType => coreTypes.doubleType; | 316   InterfaceType get doubleType => coreTypes.doubleType; | 
| 313   InterfaceType get boolType => coreTypes.boolType; | 317   InterfaceType get boolType => coreTypes.boolType; | 
| 314   InterfaceType get stringType => coreTypes.stringType; | 318   InterfaceType get stringType => coreTypes.stringType; | 
| 315 | 319 | 
| 316   DartType thisType; | 320   DartType thisType; | 
| 317   DartType superType; | 321   DartType superType; | 
| 318 | 322 | 
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 390       // If these are used, an error should have been reported by the resolver. | 394       // If these are used, an error should have been reported by the resolver. | 
| 391       thisType = const DynamicType(); | 395       thisType = const DynamicType(); | 
| 392       superType = const DynamicType(); | 396       superType = const DynamicType(); | 
| 393     } | 397     } | 
| 394   } | 398   } | 
| 395 | 399 | 
| 396   LibraryElement get currentLibrary => elements.analyzedElement.library; | 400   LibraryElement get currentLibrary => elements.analyzedElement.library; | 
| 397 | 401 | 
| 398   reportTypeWarning(Spannable spannable, MessageKind kind, | 402   reportTypeWarning(Spannable spannable, MessageKind kind, | 
| 399                     [Map arguments = const {}]) { | 403                     [Map arguments = const {}]) { | 
| 400     compiler.reportWarningMessage(spannable, kind, arguments); | 404     reporter.reportWarningMessage(spannable, kind, arguments); | 
| 401   } | 405   } | 
| 402 | 406 | 
| 403   reportMessage(Spannable spannable, MessageKind kind, | 407   reportMessage(Spannable spannable, MessageKind kind, | 
| 404                 Map arguments, | 408                 Map arguments, | 
| 405                 {bool isHint: false}) { | 409                 {bool isHint: false}) { | 
| 406     if (isHint) { | 410     if (isHint) { | 
| 407       compiler.reportHintMessage(spannable, kind, arguments); | 411       reporter.reportHintMessage(spannable, kind, arguments); | 
| 408     } else { | 412     } else { | 
| 409       compiler.reportWarningMessage(spannable, kind, arguments); | 413       reporter.reportWarningMessage(spannable, kind, arguments); | 
| 410     } | 414     } | 
| 411   } | 415   } | 
| 412 | 416 | 
| 413   reportTypePromotionHint(TypePromotion typePromotion) { | 417   reportTypePromotionHint(TypePromotion typePromotion) { | 
| 414     if (!reportedTypePromotions.contains(typePromotion)) { | 418     if (!reportedTypePromotions.contains(typePromotion)) { | 
| 415       reportedTypePromotions.add(typePromotion); | 419       reportedTypePromotions.add(typePromotion); | 
| 416       for (TypePromotionMessage message in typePromotion.messages) { | 420       for (TypePromotionMessage message in typePromotion.messages) { | 
| 417         compiler.reportHint(message.hint, message.infos); | 421         reporter.reportHint(message.hint, message.infos); | 
| 418       } | 422       } | 
| 419     } | 423     } | 
| 420   } | 424   } | 
| 421 | 425 | 
| 422   // TODO(karlklose): remove these functions. | 426   // TODO(karlklose): remove these functions. | 
| 423   DartType unhandledExpression() => const DynamicType(); | 427   DartType unhandledExpression() => const DynamicType(); | 
| 424 | 428 | 
| 425   DartType analyzeNonVoid(Node node) { | 429   DartType analyzeNonVoid(Node node) { | 
| 426     DartType type = analyze(node); | 430     DartType type = analyze(node); | 
| 427     if (type.isVoid) { | 431     if (type.isVoid) { | 
| 428       reportTypeWarning(node, MessageKind.VOID_EXPRESSION); | 432       reportTypeWarning(node, MessageKind.VOID_EXPRESSION); | 
| 429     } | 433     } | 
| 430     return type; | 434     return type; | 
| 431   } | 435   } | 
| 432 | 436 | 
| 433   DartType analyzeWithDefault(Node node, DartType defaultValue) { | 437   DartType analyzeWithDefault(Node node, DartType defaultValue) { | 
| 434     return node != null ? analyze(node) : defaultValue; | 438     return node != null ? analyze(node) : defaultValue; | 
| 435   } | 439   } | 
| 436 | 440 | 
| 437   /// If [inInitializer] is true, assignment should be interpreted as write to | 441   /// If [inInitializer] is true, assignment should be interpreted as write to | 
| 438   /// a field and not to a setter. | 442   /// a field and not to a setter. | 
| 439   DartType analyze(Node node, {bool inInitializer: false}) { | 443   DartType analyze(Node node, {bool inInitializer: false}) { | 
| 440     if (node == null) { | 444     if (node == null) { | 
| 441       final String error = 'Unexpected node: null'; | 445       final String error = 'Unexpected node: null'; | 
| 442       if (lastSeenNode != null) { | 446       if (lastSeenNode != null) { | 
| 443         compiler.internalError(lastSeenNode, error); | 447         reporter.internalError(lastSeenNode, error); | 
| 444       } else { | 448       } else { | 
| 445         compiler.internalError(executableContext, error); | 449         reporter.internalError(executableContext, error); | 
| 446       } | 450       } | 
| 447     } else { | 451     } else { | 
| 448       lastSeenNode = node; | 452       lastSeenNode = node; | 
| 449     } | 453     } | 
| 450     bool previouslyInitializer = analyzingInitializer; | 454     bool previouslyInitializer = analyzingInitializer; | 
| 451     analyzingInitializer = inInitializer; | 455     analyzingInitializer = inInitializer; | 
| 452     DartType result = node.accept(this); | 456     DartType result = node.accept(this); | 
| 453     analyzingInitializer = previouslyInitializer; | 457     analyzingInitializer = previouslyInitializer; | 
| 454     if (result == null) { | 458     if (result == null) { | 
| 455       compiler.internalError(node, 'Type is null.'); | 459       reporter.internalError(node, 'Type is null.'); | 
| 456     } | 460     } | 
| 457     return _record(node, result); | 461     return _record(node, result); | 
| 458   } | 462   } | 
| 459 | 463 | 
| 460   void checkTypePromotion(Node node, TypePromotion typePromotion, | 464   void checkTypePromotion(Node node, TypePromotion typePromotion, | 
| 461                           {bool checkAccesses: false}) { | 465                           {bool checkAccesses: false}) { | 
| 462     VariableElement variable = typePromotion.variable; | 466     VariableElement variable = typePromotion.variable; | 
| 463     String variableName = variable.name; | 467     String variableName = variable.name; | 
| 464     List<Node> potentialMutationsIn = | 468     List<Node> potentialMutationsIn = | 
| 465         elements.getPotentialMutationsIn(node, variable); | 469         elements.getPotentialMutationsIn(node, variable); | 
| 466     if (!potentialMutationsIn.isEmpty) { | 470     if (!potentialMutationsIn.isEmpty) { | 
| 467       DiagnosticMessage hint = compiler.createMessage( | 471       DiagnosticMessage hint = reporter.createMessage( | 
| 468           typePromotion.node, | 472           typePromotion.node, | 
| 469           MessageKind.POTENTIAL_MUTATION, | 473           MessageKind.POTENTIAL_MUTATION, | 
| 470           {'variableName': variableName, 'shownType': typePromotion.type}); | 474           {'variableName': variableName, 'shownType': typePromotion.type}); | 
| 471       List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 475       List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 
| 472       for (Node mutation in potentialMutationsIn) { | 476       for (Node mutation in potentialMutationsIn) { | 
| 473         infos.add(compiler.createMessage(mutation, | 477         infos.add(reporter.createMessage(mutation, | 
| 474             MessageKind.POTENTIAL_MUTATION_HERE, | 478             MessageKind.POTENTIAL_MUTATION_HERE, | 
| 475             {'variableName': variableName})); | 479             {'variableName': variableName})); | 
| 476       } | 480       } | 
| 477       typePromotion.addHint(hint, infos); | 481       typePromotion.addHint(hint, infos); | 
| 478     } | 482     } | 
| 479     List<Node> potentialMutationsInClosures = | 483     List<Node> potentialMutationsInClosures = | 
| 480         elements.getPotentialMutationsInClosure(variable); | 484         elements.getPotentialMutationsInClosure(variable); | 
| 481     if (!potentialMutationsInClosures.isEmpty) { | 485     if (!potentialMutationsInClosures.isEmpty) { | 
| 482       DiagnosticMessage hint = compiler.createMessage( | 486       DiagnosticMessage hint = reporter.createMessage( | 
| 483           typePromotion.node, | 487           typePromotion.node, | 
| 484           MessageKind.POTENTIAL_MUTATION_IN_CLOSURE, | 488           MessageKind.POTENTIAL_MUTATION_IN_CLOSURE, | 
| 485           {'variableName': variableName, 'shownType': typePromotion.type}); | 489           {'variableName': variableName, 'shownType': typePromotion.type}); | 
| 486       List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 490       List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 
| 487       for (Node mutation in potentialMutationsInClosures) { | 491       for (Node mutation in potentialMutationsInClosures) { | 
| 488         infos.add(compiler.createMessage( | 492         infos.add(reporter.createMessage( | 
| 489             mutation, | 493             mutation, | 
| 490             MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE, | 494             MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE, | 
| 491             {'variableName': variableName})); | 495             {'variableName': variableName})); | 
| 492       } | 496       } | 
| 493       typePromotion.addHint(hint, infos); | 497       typePromotion.addHint(hint, infos); | 
| 494     } | 498     } | 
| 495     if (checkAccesses) { | 499     if (checkAccesses) { | 
| 496       List<Node> accesses = elements.getAccessesByClosureIn(node, variable); | 500       List<Node> accesses = elements.getAccessesByClosureIn(node, variable); | 
| 497       List<Node> mutations = elements.getPotentialMutations(variable); | 501       List<Node> mutations = elements.getPotentialMutations(variable); | 
| 498       if (!accesses.isEmpty && !mutations.isEmpty) { | 502       if (!accesses.isEmpty && !mutations.isEmpty) { | 
| 499         DiagnosticMessage hint = compiler.createMessage( | 503         DiagnosticMessage hint = reporter.createMessage( | 
| 500             typePromotion.node, | 504             typePromotion.node, | 
| 501             MessageKind.ACCESSED_IN_CLOSURE, | 505             MessageKind.ACCESSED_IN_CLOSURE, | 
| 502             {'variableName': variableName, 'shownType': typePromotion.type}); | 506             {'variableName': variableName, 'shownType': typePromotion.type}); | 
| 503         List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 507         List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 
| 504         for (Node access in accesses) { | 508         for (Node access in accesses) { | 
| 505           infos.add(compiler.createMessage( | 509           infos.add(reporter.createMessage( | 
| 506               access, | 510               access, | 
| 507               MessageKind.ACCESSED_IN_CLOSURE_HERE, | 511               MessageKind.ACCESSED_IN_CLOSURE_HERE, | 
| 508               {'variableName': variableName})); | 512               {'variableName': variableName})); | 
| 509         } | 513         } | 
| 510         for (Node mutation in mutations) { | 514         for (Node mutation in mutations) { | 
| 511           infos.add(compiler.createMessage( | 515           infos.add(reporter.createMessage( | 
| 512               mutation, | 516               mutation, | 
| 513               MessageKind.POTENTIAL_MUTATION_HERE, | 517               MessageKind.POTENTIAL_MUTATION_HERE, | 
| 514               {'variableName': variableName})); | 518               {'variableName': variableName})); | 
| 515         } | 519         } | 
| 516         typePromotion.addHint(hint, infos); | 520         typePromotion.addHint(hint, infos); | 
| 517       } | 521       } | 
| 518     } | 522     } | 
| 519   } | 523   } | 
| 520 | 524 | 
| 521   /// Show type promotions from [left] and [right] in [node] given that the | 525   /// Show type promotions from [left] and [right] in [node] given that the | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 556 | 560 | 
| 557   /** | 561   /** | 
| 558    * Check if a value of type [from] can be assigned to a variable, parameter or | 562    * Check if a value of type [from] can be assigned to a variable, parameter or | 
| 559    * return value of type [to].  If `isConst == true`, an error is emitted in | 563    * return value of type [to].  If `isConst == true`, an error is emitted in | 
| 560    * checked mode, otherwise a warning is issued. | 564    * checked mode, otherwise a warning is issued. | 
| 561    */ | 565    */ | 
| 562   bool checkAssignable(Spannable spannable, DartType from, DartType to, | 566   bool checkAssignable(Spannable spannable, DartType from, DartType to, | 
| 563                        {bool isConst: false}) { | 567                        {bool isConst: false}) { | 
| 564     if (!types.isAssignable(from, to)) { | 568     if (!types.isAssignable(from, to)) { | 
| 565       if (compiler.enableTypeAssertions && isConst) { | 569       if (compiler.enableTypeAssertions && isConst) { | 
| 566         compiler.reportErrorMessage( | 570         reporter.reportErrorMessage( | 
| 567             spannable, | 571             spannable, | 
| 568             MessageKind.NOT_ASSIGNABLE, | 572             MessageKind.NOT_ASSIGNABLE, | 
| 569             {'fromType': from, 'toType': to}); | 573             {'fromType': from, 'toType': to}); | 
| 570       } else { | 574       } else { | 
| 571         compiler.reportWarningMessage( | 575         reporter.reportWarningMessage( | 
| 572             spannable, | 576             spannable, | 
| 573             MessageKind.NOT_ASSIGNABLE, | 577             MessageKind.NOT_ASSIGNABLE, | 
| 574             {'fromType': from, 'toType': to}); | 578             {'fromType': from, 'toType': to}); | 
| 575       } | 579       } | 
| 576       return false; | 580       return false; | 
| 577     } | 581     } | 
| 578     return true; | 582     return true; | 
| 579   } | 583   } | 
| 580 | 584 | 
| 581   checkCondition(Expression condition) { | 585   checkCondition(Expression condition) { | 
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 893       /// Report [warning] including info(s) about the declaration of [element] | 897       /// Report [warning] including info(s) about the declaration of [element] | 
| 894       /// or [type]. | 898       /// or [type]. | 
| 895       void reportWarning(DiagnosticMessage warning) { | 899       void reportWarning(DiagnosticMessage warning) { | 
| 896         // TODO(johnniwinther): Support pointing to individual parameters on | 900         // TODO(johnniwinther): Support pointing to individual parameters on | 
| 897         // assignability warnings. | 901         // assignability warnings. | 
| 898         List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 902         List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 
| 899         Element declaration = element; | 903         Element declaration = element; | 
| 900         if (declaration == null) { | 904         if (declaration == null) { | 
| 901           declaration = type.element; | 905           declaration = type.element; | 
| 902         } else if (type.isTypedef) { | 906         } else if (type.isTypedef) { | 
| 903           infos.add(compiler.createMessage( | 907           infos.add(reporter.createMessage( | 
| 904               declaration, | 908               declaration, | 
| 905               MessageKind.THIS_IS_THE_DECLARATION, | 909               MessageKind.THIS_IS_THE_DECLARATION, | 
| 906               {'name': element.name})); | 910               {'name': element.name})); | 
| 907           declaration = type.element; | 911           declaration = type.element; | 
| 908         } | 912         } | 
| 909         if (declaration != null) { | 913         if (declaration != null) { | 
| 910           infos.add(compiler.createMessage( | 914           infos.add(reporter.createMessage( | 
| 911               declaration, MessageKind.THIS_IS_THE_METHOD)); | 915               declaration, MessageKind.THIS_IS_THE_METHOD)); | 
| 912         } | 916         } | 
| 913         compiler.reportWarning(warning, infos); | 917         reporter.reportWarning(warning, infos); | 
| 914       } | 918       } | 
| 915 | 919 | 
| 916       /// Report a warning on [node] if [argumentType] is not assignable to | 920       /// Report a warning on [node] if [argumentType] is not assignable to | 
| 917       /// [parameterType]. | 921       /// [parameterType]. | 
| 918       void checkAssignable(Spannable node, | 922       void checkAssignable(Spannable node, | 
| 919                            DartType argumentType, | 923                            DartType argumentType, | 
| 920                            DartType parameterType) { | 924                            DartType parameterType) { | 
| 921         if (!types.isAssignable(argumentType, parameterType)) { | 925         if (!types.isAssignable(argumentType, parameterType)) { | 
| 922           reportWarning(compiler.createMessage( | 926           reportWarning(reporter.createMessage( | 
| 923               node, | 927               node, | 
| 924               MessageKind.NOT_ASSIGNABLE, | 928               MessageKind.NOT_ASSIGNABLE, | 
| 925               {'fromType': argumentType, 'toType': parameterType})); | 929               {'fromType': argumentType, 'toType': parameterType})); | 
| 926         } | 930         } | 
| 927       } | 931       } | 
| 928 | 932 | 
| 929       FunctionType funType = unaliasedType; | 933       FunctionType funType = unaliasedType; | 
| 930       Iterator<DartType> parameterTypes = funType.parameterTypes.iterator; | 934       Iterator<DartType> parameterTypes = funType.parameterTypes.iterator; | 
| 931       Iterator<DartType> optionalParameterTypes = | 935       Iterator<DartType> optionalParameterTypes = | 
| 932           funType.optionalParameterTypes.iterator; | 936           funType.optionalParameterTypes.iterator; | 
| 933       while (!arguments.isEmpty) { | 937       while (!arguments.isEmpty) { | 
| 934         Node argument = arguments.head; | 938         Node argument = arguments.head; | 
| 935         NamedArgument namedArgument = argument.asNamedArgument(); | 939         NamedArgument namedArgument = argument.asNamedArgument(); | 
| 936         if (namedArgument != null) { | 940         if (namedArgument != null) { | 
| 937           argument = namedArgument.expression; | 941           argument = namedArgument.expression; | 
| 938           String argumentName = namedArgument.name.source; | 942           String argumentName = namedArgument.name.source; | 
| 939           DartType namedParameterType = | 943           DartType namedParameterType = | 
| 940               funType.getNamedParameterType(argumentName); | 944               funType.getNamedParameterType(argumentName); | 
| 941           if (namedParameterType == null) { | 945           if (namedParameterType == null) { | 
| 942             // TODO(johnniwinther): Provide better information on the called | 946             // TODO(johnniwinther): Provide better information on the called | 
| 943             // function. | 947             // function. | 
| 944             reportWarning(compiler.createMessage( | 948             reportWarning(reporter.createMessage( | 
| 945                 argument, | 949                 argument, | 
| 946                 MessageKind.NAMED_ARGUMENT_NOT_FOUND, | 950                 MessageKind.NAMED_ARGUMENT_NOT_FOUND, | 
| 947                 {'argumentName': argumentName})); | 951                 {'argumentName': argumentName})); | 
| 948 | 952 | 
| 949             DartType argumentType = analyze(argument); | 953             DartType argumentType = analyze(argument); | 
| 950             if (argumentTypes != null) argumentTypes.addLast(argumentType); | 954             if (argumentTypes != null) argumentTypes.addLast(argumentType); | 
| 951           } else { | 955           } else { | 
| 952             DartType argumentType = analyze(argument); | 956             DartType argumentType = analyze(argument); | 
| 953             if (argumentTypes != null) argumentTypes.addLast(argumentType); | 957             if (argumentTypes != null) argumentTypes.addLast(argumentType); | 
| 954             checkAssignable(argument, argumentType, namedParameterType); | 958             checkAssignable(argument, argumentType, namedParameterType); | 
| 955           } | 959           } | 
| 956         } else { | 960         } else { | 
| 957           if (!parameterTypes.moveNext()) { | 961           if (!parameterTypes.moveNext()) { | 
| 958             if (!optionalParameterTypes.moveNext()) { | 962             if (!optionalParameterTypes.moveNext()) { | 
| 959 | 963 | 
| 960               // TODO(johnniwinther): Provide better information on the | 964               // TODO(johnniwinther): Provide better information on the | 
| 961               // called function. | 965               // called function. | 
| 962               reportWarning(compiler.createMessage( | 966               reportWarning(reporter.createMessage( | 
| 963                   argument, MessageKind.ADDITIONAL_ARGUMENT)); | 967                   argument, MessageKind.ADDITIONAL_ARGUMENT)); | 
| 964 | 968 | 
| 965               DartType argumentType = analyze(argument); | 969               DartType argumentType = analyze(argument); | 
| 966               if (argumentTypes != null) argumentTypes.addLast(argumentType); | 970               if (argumentTypes != null) argumentTypes.addLast(argumentType); | 
| 967             } else { | 971             } else { | 
| 968               DartType argumentType = analyze(argument); | 972               DartType argumentType = analyze(argument); | 
| 969               if (argumentTypes != null) argumentTypes.addLast(argumentType); | 973               if (argumentTypes != null) argumentTypes.addLast(argumentType); | 
| 970               checkAssignable( | 974               checkAssignable( | 
| 971                   argument, argumentType, optionalParameterTypes.current); | 975                   argument, argumentType, optionalParameterTypes.current); | 
| 972             } | 976             } | 
| 973           } else { | 977           } else { | 
| 974             DartType argumentType = analyze(argument); | 978             DartType argumentType = analyze(argument); | 
| 975             if (argumentTypes != null) argumentTypes.addLast(argumentType); | 979             if (argumentTypes != null) argumentTypes.addLast(argumentType); | 
| 976             checkAssignable(argument, argumentType, parameterTypes.current); | 980             checkAssignable(argument, argumentType, parameterTypes.current); | 
| 977           } | 981           } | 
| 978         } | 982         } | 
| 979         arguments = arguments.tail; | 983         arguments = arguments.tail; | 
| 980       } | 984       } | 
| 981       if (parameterTypes.moveNext()) { | 985       if (parameterTypes.moveNext()) { | 
| 982         // TODO(johnniwinther): Provide better information on the called | 986         // TODO(johnniwinther): Provide better information on the called | 
| 983         // function. | 987         // function. | 
| 984         reportWarning(compiler.createMessage( | 988         reportWarning(reporter.createMessage( | 
| 985             send, MessageKind.MISSING_ARGUMENT, | 989             send, MessageKind.MISSING_ARGUMENT, | 
| 986             {'argumentType': parameterTypes.current})); | 990             {'argumentType': parameterTypes.current})); | 
| 987       } | 991       } | 
| 988     } else { | 992     } else { | 
| 989       while(!arguments.isEmpty) { | 993       while(!arguments.isEmpty) { | 
| 990         DartType argumentType = analyze(arguments.head); | 994         DartType argumentType = analyze(arguments.head); | 
| 991         if (argumentTypes != null) argumentTypes.addLast(argumentType); | 995         if (argumentTypes != null) argumentTypes.addLast(argumentType); | 
| 992         arguments = arguments.tail; | 996         arguments = arguments.tail; | 
| 993       } | 997       } | 
| 994     } | 998     } | 
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1082       // foo() where foo is a method in the same class. | 1086       // foo() where foo is a method in the same class. | 
| 1083       return createResolvedAccess(node, name, element); | 1087       return createResolvedAccess(node, name, element); | 
| 1084     } else if (element.isVariable || | 1088     } else if (element.isVariable || | 
| 1085         element.isParameter || | 1089         element.isParameter || | 
| 1086         element.isField) { | 1090         element.isField) { | 
| 1087       // foo() where foo is a field in the same class. | 1091       // foo() where foo is a field in the same class. | 
| 1088       return createResolvedAccess(node, name, element); | 1092       return createResolvedAccess(node, name, element); | 
| 1089     } else if (element.isGetter || element.isSetter) { | 1093     } else if (element.isGetter || element.isSetter) { | 
| 1090       return createResolvedAccess(node, name, element); | 1094       return createResolvedAccess(node, name, element); | 
| 1091     } else { | 1095     } else { | 
| 1092       compiler.internalError(element, | 1096       reporter.internalError(element, | 
| 1093           'Unexpected element kind ${element.kind}.'); | 1097           'Unexpected element kind ${element.kind}.'); | 
| 1094       return null; | 1098       return null; | 
| 1095     } | 1099     } | 
| 1096   } | 1100   } | 
| 1097 | 1101 | 
| 1098   ElementAccess createResolvedAccess(Send node, String name, | 1102   ElementAccess createResolvedAccess(Send node, String name, | 
| 1099                                      Element element) { | 1103                                      Element element) { | 
| 1100     checkPrivateAccess(node, element, name); | 1104     checkPrivateAccess(node, element, name); | 
| 1101     return createPromotedAccess(element); | 1105     return createPromotedAccess(element); | 
| 1102   } | 1106   } | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 1115    * Computes the type of the access of [name] on the [node] possibly using the | 1119    * Computes the type of the access of [name] on the [node] possibly using the | 
| 1116    * [element] provided for [node] by the resolver. | 1120    * [element] provided for [node] by the resolver. | 
| 1117    */ | 1121    */ | 
| 1118   DartType computeAccessType(Send node, String name, Element element, | 1122   DartType computeAccessType(Send node, String name, Element element, | 
| 1119                              MemberKind memberKind, | 1123                              MemberKind memberKind, | 
| 1120                              {bool lookupClassMember: false}) { | 1124                              {bool lookupClassMember: false}) { | 
| 1121     DartType type = | 1125     DartType type = | 
| 1122         computeAccess(node, name, element, memberKind, | 1126         computeAccess(node, name, element, memberKind, | 
| 1123             lookupClassMember: lookupClassMember).computeType(resolution); | 1127             lookupClassMember: lookupClassMember).computeType(resolution); | 
| 1124     if (type == null) { | 1128     if (type == null) { | 
| 1125       compiler.internalError(node, 'Type is null on access of $name on $node.'); | 1129       reporter.internalError(node, 'Type is null on access of $name on $node.'); | 
| 1126     } | 1130     } | 
| 1127     return type; | 1131     return type; | 
| 1128   } | 1132   } | 
| 1129 | 1133 | 
| 1130   /// Compute a version of [shownType] that is more specific that [knownType]. | 1134   /// Compute a version of [shownType] that is more specific that [knownType]. | 
| 1131   /// This is used to provided better hints when trying to promote a supertype | 1135   /// This is used to provided better hints when trying to promote a supertype | 
| 1132   /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List` | 1136   /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List` | 
| 1133   /// we suggest the use of `List<int>`, which would make promotion valid. | 1137   /// we suggest the use of `List<int>`, which would make promotion valid. | 
| 1134   DartType computeMoreSpecificType(DartType shownType, | 1138   DartType computeMoreSpecificType(DartType shownType, | 
| 1135                                    DartType knownType) { | 1139                                    DartType knownType) { | 
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1234         if (variable != null && | 1238         if (variable != null && | 
| 1235             (variable.isVariable || variable.isParameter)) { | 1239             (variable.isVariable || variable.isParameter)) { | 
| 1236           DartType knownType = getKnownType(variable); | 1240           DartType knownType = getKnownType(variable); | 
| 1237           if (!knownType.isDynamic) { | 1241           if (!knownType.isDynamic) { | 
| 1238             DartType shownType = elements.getType(node.arguments.head); | 1242             DartType shownType = elements.getType(node.arguments.head); | 
| 1239             TypePromotion typePromotion = | 1243             TypePromotion typePromotion = | 
| 1240                 new TypePromotion(node, variable, shownType); | 1244                 new TypePromotion(node, variable, shownType); | 
| 1241             if (!types.isMoreSpecific(shownType, knownType)) { | 1245             if (!types.isMoreSpecific(shownType, knownType)) { | 
| 1242               String variableName = variable.name; | 1246               String variableName = variable.name; | 
| 1243               if (!types.isSubtype(shownType, knownType)) { | 1247               if (!types.isSubtype(shownType, knownType)) { | 
| 1244                 typePromotion.addHint(compiler.createMessage( | 1248                 typePromotion.addHint(reporter.createMessage( | 
| 1245                     node, | 1249                     node, | 
| 1246                     MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, | 1250                     MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, | 
| 1247                     {'variableName': variableName, | 1251                     {'variableName': variableName, | 
| 1248                      'shownType': shownType, | 1252                      'shownType': shownType, | 
| 1249                      'knownType': knownType})); | 1253                      'knownType': knownType})); | 
| 1250               } else { | 1254               } else { | 
| 1251                 DartType shownTypeSuggestion = | 1255                 DartType shownTypeSuggestion = | 
| 1252                     computeMoreSpecificType(shownType, knownType); | 1256                     computeMoreSpecificType(shownType, knownType); | 
| 1253                 if (shownTypeSuggestion != null) { | 1257                 if (shownTypeSuggestion != null) { | 
| 1254                   typePromotion.addHint(compiler.createMessage( | 1258                   typePromotion.addHint(reporter.createMessage( | 
| 1255                       node, | 1259                       node, | 
| 1256                       MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, | 1260                       MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, | 
| 1257                       {'variableName': variableName, | 1261                       {'variableName': variableName, | 
| 1258                        'shownType': shownType, | 1262                        'shownType': shownType, | 
| 1259                        'shownTypeSuggestion': shownTypeSuggestion, | 1263                        'shownTypeSuggestion': shownTypeSuggestion, | 
| 1260                        'knownType': knownType})); | 1264                        'knownType': knownType})); | 
| 1261                 } else { | 1265                 } else { | 
| 1262                   typePromotion.addHint(compiler.createMessage( | 1266                   typePromotion.addHint(reporter.createMessage( | 
| 1263                       node, | 1267                       node, | 
| 1264                       MessageKind.NOT_MORE_SPECIFIC, | 1268                       MessageKind.NOT_MORE_SPECIFIC, | 
| 1265                       {'variableName': variableName, | 1269                       {'variableName': variableName, | 
| 1266                        'shownType': shownType, | 1270                        'shownType': shownType, | 
| 1267                        'knownType': knownType})); | 1271                        'knownType': knownType})); | 
| 1268                 } | 1272                 } | 
| 1269               } | 1273               } | 
| 1270             } | 1274             } | 
| 1271             showTypePromotion(node, typePromotion); | 1275             showTypePromotion(node, typePromotion); | 
| 1272           } | 1276           } | 
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1541         case '*=': operatorName = '*'; break; | 1545         case '*=': operatorName = '*'; break; | 
| 1542         case '/=': operatorName = '/'; break; | 1546         case '/=': operatorName = '/'; break; | 
| 1543         case '%=': operatorName = '%'; break; | 1547         case '%=': operatorName = '%'; break; | 
| 1544         case '~/=': operatorName = '~/'; break; | 1548         case '~/=': operatorName = '~/'; break; | 
| 1545         case '&=': operatorName = '&'; break; | 1549         case '&=': operatorName = '&'; break; | 
| 1546         case '|=': operatorName = '|'; break; | 1550         case '|=': operatorName = '|'; break; | 
| 1547         case '^=': operatorName = '^'; break; | 1551         case '^=': operatorName = '^'; break; | 
| 1548         case '<<=': operatorName = '<<'; break; | 1552         case '<<=': operatorName = '<<'; break; | 
| 1549         case '>>=': operatorName = '>>'; break; | 1553         case '>>=': operatorName = '>>'; break; | 
| 1550         default: | 1554         default: | 
| 1551           compiler.internalError(node, 'Unexpected assignment operator $name.'); | 1555           reporter.internalError(node, 'Unexpected assignment operator $name.'); | 
| 1552       } | 1556       } | 
| 1553       if (node.isIndex) { | 1557       if (node.isIndex) { | 
| 1554         // base[key] o= value for some operator o. | 1558         // base[key] o= value for some operator o. | 
| 1555         final Node valueNode = node.arguments.tail.head; | 1559         final Node valueNode = node.arguments.tail.head; | 
| 1556         final DartType value = analyze(valueNode); | 1560         final DartType value = analyze(valueNode); | 
| 1557         return checkIndexAssignmentOperator( | 1561         return checkIndexAssignmentOperator( | 
| 1558             node, operatorName, valueNode, value); | 1562             node, operatorName, valueNode, value); | 
| 1559       } else { | 1563       } else { | 
| 1560         // target o= value for some operator o. | 1564         // target o= value for some operator o. | 
| 1561         final Node valueNode = node.arguments.head; | 1565         final Node valueNode = node.arguments.head; | 
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1960               ConstantExpression caseConstant = | 1964               ConstantExpression caseConstant = | 
| 1961                   compiler.resolver.constantCompiler.compileNode( | 1965                   compiler.resolver.constantCompiler.compileNode( | 
| 1962                       caseMatch.expression, elements); | 1966                       caseMatch.expression, elements); | 
| 1963               enumValues.remove( | 1967               enumValues.remove( | 
| 1964                   compiler.constants.getConstantValue(caseConstant)); | 1968                   compiler.constants.getConstantValue(caseConstant)); | 
| 1965             } | 1969             } | 
| 1966           } | 1970           } | 
| 1967         } | 1971         } | 
| 1968         unreferencedFields.addAll(enumValues.values); | 1972         unreferencedFields.addAll(enumValues.values); | 
| 1969         if (!unreferencedFields.isEmpty) { | 1973         if (!unreferencedFields.isEmpty) { | 
| 1970           compiler.reportWarningMessage( | 1974           reporter.reportWarningMessage( | 
| 1971               node, MessageKind.MISSING_ENUM_CASES, | 1975               node, MessageKind.MISSING_ENUM_CASES, | 
| 1972               {'enumType': expressionType, | 1976               {'enumType': expressionType, | 
| 1973                'enumValues': unreferencedFields.map( | 1977                'enumValues': unreferencedFields.map( | 
| 1974                    (e) => e.name).join(', ')}); | 1978                    (e) => e.name).join(', ')}); | 
| 1975         } | 1979         } | 
| 1976       }); | 1980       }); | 
| 1977     } | 1981     } | 
| 1978 | 1982 | 
| 1979     return const StatementType(); | 1983     return const StatementType(); | 
| 1980   } | 1984   } | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 1997 | 2001 | 
| 1998   visitCatchBlock(CatchBlock node) { | 2002   visitCatchBlock(CatchBlock node) { | 
| 1999     return analyze(node.block); | 2003     return analyze(node.block); | 
| 2000   } | 2004   } | 
| 2001 | 2005 | 
| 2002   visitTypedef(Typedef node) { | 2006   visitTypedef(Typedef node) { | 
| 2003     // Do not typecheck [Typedef] nodes. | 2007     // Do not typecheck [Typedef] nodes. | 
| 2004   } | 2008   } | 
| 2005 | 2009 | 
| 2006   visitNode(Node node) { | 2010   visitNode(Node node) { | 
| 2007     compiler.internalError(node, | 2011     reporter.internalError(node, | 
| 2008         'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 2012         'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 
| 2009   } | 2013   } | 
| 2010 } | 2014 } | 
| OLD | NEW | 
|---|