| 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/tasks.dart' show | 9 import 'common/tasks.dart' show |
| 10 CompilerTask; | 10 CompilerTask; |
| 11 import 'compiler.dart' show | 11 import 'compiler.dart' show |
| 12 Compiler; | 12 Compiler; |
| 13 import 'constants/expressions.dart'; | 13 import 'constants/expressions.dart'; |
| 14 import 'constants/values.dart'; | 14 import 'constants/values.dart'; |
| 15 import 'core_types.dart'; | 15 import 'core_types.dart'; |
| 16 import 'dart_types.dart'; | 16 import 'dart_types.dart'; |
| 17 import 'diagnostics/diagnostic_listener.dart' show |
| 18 DiagnosticMessage; |
| 17 import 'diagnostics/invariant.dart' show | 19 import 'diagnostics/invariant.dart' show |
| 18 invariant; | 20 invariant; |
| 19 import 'diagnostics/messages.dart'; | 21 import 'diagnostics/messages.dart'; |
| 20 import 'diagnostics/spannable.dart' show | 22 import 'diagnostics/spannable.dart' show |
| 21 Spannable; | 23 Spannable; |
| 22 import 'elements/elements.dart' show | 24 import 'elements/elements.dart' show |
| 23 AbstractFieldElement, | 25 AbstractFieldElement, |
| 24 AstElement, | 26 AstElement, |
| 25 AsyncMarker, | 27 AsyncMarker, |
| 26 ClassElement, | 28 ClassElement, |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 final List<TypePromotionMessage> messages = <TypePromotionMessage>[]; | 264 final List<TypePromotionMessage> messages = <TypePromotionMessage>[]; |
| 263 | 265 |
| 264 TypePromotion(this.node, this.variable, this.type); | 266 TypePromotion(this.node, this.variable, this.type); |
| 265 | 267 |
| 266 bool get isValid => messages.isEmpty; | 268 bool get isValid => messages.isEmpty; |
| 267 | 269 |
| 268 TypePromotion copy() { | 270 TypePromotion copy() { |
| 269 return new TypePromotion(node, variable, type)..messages.addAll(messages); | 271 return new TypePromotion(node, variable, type)..messages.addAll(messages); |
| 270 } | 272 } |
| 271 | 273 |
| 272 void addHint(Spannable spannable, MessageKind kind, [Map arguments]) { | 274 void addHint(DiagnosticMessage hint, |
| 273 messages.add(new TypePromotionMessage(api.Diagnostic.HINT, | 275 [List<DiagnosticMessage> infos = const <DiagnosticMessage>[]]) { |
| 274 spannable, kind, arguments)); | 276 messages.add(new TypePromotionMessage(hint, infos)); |
| 275 } | |
| 276 | |
| 277 void addInfo(Spannable spannable, MessageKind kind, [Map arguments]) { | |
| 278 messages.add(new TypePromotionMessage(api.Diagnostic.INFO, | |
| 279 spannable, kind, arguments)); | |
| 280 } | 277 } |
| 281 | 278 |
| 282 String toString() { | 279 String toString() { |
| 283 return 'Promote ${variable} to ${type}${isValid ? '' : ' (invalid)'}'; | 280 return 'Promote ${variable} to ${type}${isValid ? '' : ' (invalid)'}'; |
| 284 } | 281 } |
| 285 } | 282 } |
| 286 | 283 |
| 287 /// A hint or info message attached to a type promotion. | 284 /// A hint or info message attached to a type promotion. |
| 288 class TypePromotionMessage { | 285 class TypePromotionMessage { |
| 289 api.Diagnostic diagnostic; | 286 DiagnosticMessage hint; |
| 290 Spannable spannable; | 287 List<DiagnosticMessage> infos; |
| 291 MessageKind messageKind; | |
| 292 Map messageArguments; | |
| 293 | 288 |
| 294 TypePromotionMessage(this.diagnostic, this.spannable, this.messageKind, | 289 TypePromotionMessage(this.hint, this.infos); |
| 295 [this.messageArguments]); | |
| 296 } | 290 } |
| 297 | 291 |
| 298 class TypeCheckerVisitor extends Visitor<DartType> { | 292 class TypeCheckerVisitor extends Visitor<DartType> { |
| 299 final Compiler compiler; | 293 final Compiler compiler; |
| 300 final TreeElements elements; | 294 final TreeElements elements; |
| 301 final Types types; | 295 final Types types; |
| 302 | 296 |
| 303 Node lastSeenNode; | 297 Node lastSeenNode; |
| 304 DartType expectedReturnType; | 298 DartType expectedReturnType; |
| 305 AsyncMarker currentAsyncMarker = AsyncMarker.SYNC; | 299 AsyncMarker currentAsyncMarker = AsyncMarker.SYNC; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 // If these are used, an error should have been reported by the resolver. | 387 // If these are used, an error should have been reported by the resolver. |
| 394 thisType = const DynamicType(); | 388 thisType = const DynamicType(); |
| 395 superType = const DynamicType(); | 389 superType = const DynamicType(); |
| 396 } | 390 } |
| 397 } | 391 } |
| 398 | 392 |
| 399 LibraryElement get currentLibrary => elements.analyzedElement.library; | 393 LibraryElement get currentLibrary => elements.analyzedElement.library; |
| 400 | 394 |
| 401 reportTypeWarning(Spannable spannable, MessageKind kind, | 395 reportTypeWarning(Spannable spannable, MessageKind kind, |
| 402 [Map arguments = const {}]) { | 396 [Map arguments = const {}]) { |
| 403 compiler.reportWarning(spannable, kind, arguments); | 397 compiler.reportWarningMessage(spannable, kind, arguments); |
| 404 } | 398 } |
| 405 | 399 |
| 406 reportMessage(Spannable spannable, MessageKind kind, | 400 reportMessage(Spannable spannable, MessageKind kind, |
| 407 Map arguments, | 401 Map arguments, |
| 408 {bool isHint: false}) { | 402 {bool isHint: false}) { |
| 409 if (isHint) { | 403 if (isHint) { |
| 410 compiler.reportHint(spannable, kind, arguments); | 404 compiler.reportHintMessage(spannable, kind, arguments); |
| 411 } else { | 405 } else { |
| 412 compiler.reportWarning(spannable, kind, arguments); | 406 compiler.reportWarningMessage(spannable, kind, arguments); |
| 413 } | 407 } |
| 414 } | 408 } |
| 415 | 409 |
| 416 reportTypeInfo(Spannable spannable, MessageKind kind, | |
| 417 [Map arguments = const {}]) { | |
| 418 compiler.reportInfo(spannable, kind, arguments); | |
| 419 } | |
| 420 | |
| 421 reportTypePromotionHint(TypePromotion typePromotion) { | 410 reportTypePromotionHint(TypePromotion typePromotion) { |
| 422 if (!reportedTypePromotions.contains(typePromotion)) { | 411 if (!reportedTypePromotions.contains(typePromotion)) { |
| 423 reportedTypePromotions.add(typePromotion); | 412 reportedTypePromotions.add(typePromotion); |
| 424 for (TypePromotionMessage message in typePromotion.messages) { | 413 for (TypePromotionMessage message in typePromotion.messages) { |
| 425 switch (message.diagnostic) { | 414 compiler.reportHint(message.hint, message.infos); |
| 426 case api.Diagnostic.HINT: | |
| 427 compiler.reportHint(message.spannable, | |
| 428 message.messageKind, | |
| 429 message.messageArguments); | |
| 430 break; | |
| 431 case api.Diagnostic.INFO: | |
| 432 compiler.reportInfo(message.spannable, | |
| 433 message.messageKind, | |
| 434 message.messageArguments); | |
| 435 break; | |
| 436 } | |
| 437 } | 415 } |
| 438 } | 416 } |
| 439 } | 417 } |
| 440 | 418 |
| 441 // TODO(karlklose): remove these functions. | 419 // TODO(karlklose): remove these functions. |
| 442 DartType unhandledExpression() => const DynamicType(); | 420 DartType unhandledExpression() => const DynamicType(); |
| 443 | 421 |
| 444 DartType analyzeNonVoid(Node node) { | 422 DartType analyzeNonVoid(Node node) { |
| 445 DartType type = analyze(node); | 423 DartType type = analyze(node); |
| 446 if (type.isVoid) { | 424 if (type.isVoid) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 476 return result; | 454 return result; |
| 477 } | 455 } |
| 478 | 456 |
| 479 void checkTypePromotion(Node node, TypePromotion typePromotion, | 457 void checkTypePromotion(Node node, TypePromotion typePromotion, |
| 480 {bool checkAccesses: false}) { | 458 {bool checkAccesses: false}) { |
| 481 VariableElement variable = typePromotion.variable; | 459 VariableElement variable = typePromotion.variable; |
| 482 String variableName = variable.name; | 460 String variableName = variable.name; |
| 483 List<Node> potentialMutationsIn = | 461 List<Node> potentialMutationsIn = |
| 484 elements.getPotentialMutationsIn(node, variable); | 462 elements.getPotentialMutationsIn(node, variable); |
| 485 if (!potentialMutationsIn.isEmpty) { | 463 if (!potentialMutationsIn.isEmpty) { |
| 486 typePromotion.addHint(typePromotion.node, | 464 DiagnosticMessage hint = compiler.createMessage( |
| 465 typePromotion.node, |
| 487 MessageKind.POTENTIAL_MUTATION, | 466 MessageKind.POTENTIAL_MUTATION, |
| 488 {'variableName': variableName, 'shownType': typePromotion.type}); | 467 {'variableName': variableName, 'shownType': typePromotion.type}); |
| 468 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 489 for (Node mutation in potentialMutationsIn) { | 469 for (Node mutation in potentialMutationsIn) { |
| 490 typePromotion.addInfo(mutation, | 470 infos.add(compiler.createMessage(mutation, |
| 491 MessageKind.POTENTIAL_MUTATION_HERE, | 471 MessageKind.POTENTIAL_MUTATION_HERE, |
| 492 {'variableName': variableName}); | 472 {'variableName': variableName})); |
| 493 } | 473 } |
| 474 typePromotion.addHint(hint, infos); |
| 494 } | 475 } |
| 495 List<Node> potentialMutationsInClosures = | 476 List<Node> potentialMutationsInClosures = |
| 496 elements.getPotentialMutationsInClosure(variable); | 477 elements.getPotentialMutationsInClosure(variable); |
| 497 if (!potentialMutationsInClosures.isEmpty) { | 478 if (!potentialMutationsInClosures.isEmpty) { |
| 498 typePromotion.addHint(typePromotion.node, | 479 DiagnosticMessage hint = compiler.createMessage( |
| 480 typePromotion.node, |
| 499 MessageKind.POTENTIAL_MUTATION_IN_CLOSURE, | 481 MessageKind.POTENTIAL_MUTATION_IN_CLOSURE, |
| 500 {'variableName': variableName, 'shownType': typePromotion.type}); | 482 {'variableName': variableName, 'shownType': typePromotion.type}); |
| 483 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 501 for (Node mutation in potentialMutationsInClosures) { | 484 for (Node mutation in potentialMutationsInClosures) { |
| 502 typePromotion.addInfo(mutation, | 485 infos.add(compiler.createMessage( |
| 486 mutation, |
| 503 MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE, | 487 MessageKind.POTENTIAL_MUTATION_IN_CLOSURE_HERE, |
| 504 {'variableName': variableName}); | 488 {'variableName': variableName})); |
| 505 } | 489 } |
| 490 typePromotion.addHint(hint, infos); |
| 506 } | 491 } |
| 507 if (checkAccesses) { | 492 if (checkAccesses) { |
| 508 List<Node> accesses = elements.getAccessesByClosureIn(node, variable); | 493 List<Node> accesses = elements.getAccessesByClosureIn(node, variable); |
| 509 List<Node> mutations = elements.getPotentialMutations(variable); | 494 List<Node> mutations = elements.getPotentialMutations(variable); |
| 510 if (!accesses.isEmpty && !mutations.isEmpty) { | 495 if (!accesses.isEmpty && !mutations.isEmpty) { |
| 511 typePromotion.addHint(typePromotion.node, | 496 DiagnosticMessage hint = compiler.createMessage( |
| 497 typePromotion.node, |
| 512 MessageKind.ACCESSED_IN_CLOSURE, | 498 MessageKind.ACCESSED_IN_CLOSURE, |
| 513 {'variableName': variableName, 'shownType': typePromotion.type}); | 499 {'variableName': variableName, 'shownType': typePromotion.type}); |
| 500 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 514 for (Node access in accesses) { | 501 for (Node access in accesses) { |
| 515 typePromotion.addInfo(access, | 502 infos.add(compiler.createMessage( |
| 503 access, |
| 516 MessageKind.ACCESSED_IN_CLOSURE_HERE, | 504 MessageKind.ACCESSED_IN_CLOSURE_HERE, |
| 517 {'variableName': variableName}); | 505 {'variableName': variableName})); |
| 518 } | 506 } |
| 519 for (Node mutation in mutations) { | 507 for (Node mutation in mutations) { |
| 520 typePromotion.addInfo(mutation, | 508 infos.add(compiler.createMessage( |
| 509 mutation, |
| 521 MessageKind.POTENTIAL_MUTATION_HERE, | 510 MessageKind.POTENTIAL_MUTATION_HERE, |
| 522 {'variableName': variableName}); | 511 {'variableName': variableName})); |
| 523 } | 512 } |
| 513 typePromotion.addHint(hint, infos); |
| 524 } | 514 } |
| 525 } | 515 } |
| 526 } | 516 } |
| 527 | 517 |
| 528 /// Show type promotions from [left] and [right] in [node] given that the | 518 /// Show type promotions from [left] and [right] in [node] given that the |
| 529 /// promoted variables are not potentially mutated in [right]. | 519 /// promoted variables are not potentially mutated in [right]. |
| 530 void reshowTypePromotions(Node node, Node left, Node right) { | 520 void reshowTypePromotions(Node node, Node left, Node right) { |
| 531 for (TypePromotion typePromotion in getShownTypePromotionsFor(left)) { | 521 for (TypePromotion typePromotion in getShownTypePromotionsFor(left)) { |
| 532 typePromotion = typePromotion.copy(); | 522 typePromotion = typePromotion.copy(); |
| 533 checkTypePromotion(right, typePromotion); | 523 checkTypePromotion(right, typePromotion); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 563 | 553 |
| 564 /** | 554 /** |
| 565 * Check if a value of type [from] can be assigned to a variable, parameter or | 555 * Check if a value of type [from] can be assigned to a variable, parameter or |
| 566 * return value of type [to]. If `isConst == true`, an error is emitted in | 556 * return value of type [to]. If `isConst == true`, an error is emitted in |
| 567 * checked mode, otherwise a warning is issued. | 557 * checked mode, otherwise a warning is issued. |
| 568 */ | 558 */ |
| 569 bool checkAssignable(Spannable spannable, DartType from, DartType to, | 559 bool checkAssignable(Spannable spannable, DartType from, DartType to, |
| 570 {bool isConst: false}) { | 560 {bool isConst: false}) { |
| 571 if (!types.isAssignable(from, to)) { | 561 if (!types.isAssignable(from, to)) { |
| 572 if (compiler.enableTypeAssertions && isConst) { | 562 if (compiler.enableTypeAssertions && isConst) { |
| 573 compiler.reportError(spannable, MessageKind.NOT_ASSIGNABLE, | 563 compiler.reportErrorMessage( |
| 574 {'fromType': from, 'toType': to}); | 564 spannable, |
| 565 MessageKind.NOT_ASSIGNABLE, |
| 566 {'fromType': from, 'toType': to}); |
| 575 } else { | 567 } else { |
| 576 reportTypeWarning(spannable, MessageKind.NOT_ASSIGNABLE, | 568 compiler.reportWarningMessage( |
| 577 {'fromType': from, 'toType': to}); | 569 spannable, |
| 570 MessageKind.NOT_ASSIGNABLE, |
| 571 {'fromType': from, 'toType': to}); |
| 578 } | 572 } |
| 579 return false; | 573 return false; |
| 580 } | 574 } |
| 581 return true; | 575 return true; |
| 582 } | 576 } |
| 583 | 577 |
| 584 checkCondition(Expression condition) { | 578 checkCondition(Expression condition) { |
| 585 checkAssignable(condition, analyze(condition), boolType); | 579 checkAssignable(condition, analyze(condition), boolType); |
| 586 } | 580 } |
| 587 | 581 |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 {bool isHint: false}) { | 879 {bool isHint: false}) { |
| 886 return lookupMember(node, type, name, memberKind, null, isHint: isHint) | 880 return lookupMember(node, type, name, memberKind, null, isHint: isHint) |
| 887 .computeType(compiler); | 881 .computeType(compiler); |
| 888 } | 882 } |
| 889 | 883 |
| 890 void analyzeArguments(Send send, Element element, DartType type, | 884 void analyzeArguments(Send send, Element element, DartType type, |
| 891 [LinkBuilder<DartType> argumentTypes]) { | 885 [LinkBuilder<DartType> argumentTypes]) { |
| 892 Link<Node> arguments = send.arguments; | 886 Link<Node> arguments = send.arguments; |
| 893 DartType unaliasedType = type.unalias(compiler); | 887 DartType unaliasedType = type.unalias(compiler); |
| 894 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) { | 888 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) { |
| 895 bool error = false; | 889 |
| 890 /// Report [warning] including info(s) about the declaration of [element] |
| 891 /// or [type]. |
| 892 void reportWarning(DiagnosticMessage warning) { |
| 893 // TODO(johnniwinther): Support pointing to individual parameters on |
| 894 // assignability warnings. |
| 895 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 896 Element declaration = element; |
| 897 if (declaration == null) { |
| 898 declaration = type.element; |
| 899 } else if (type.isTypedef) { |
| 900 infos.add(compiler.createMessage( |
| 901 declaration, |
| 902 MessageKind.THIS_IS_THE_DECLARATION, |
| 903 {'name': element.name})); |
| 904 declaration = type.element; |
| 905 } |
| 906 if (declaration != null) { |
| 907 infos.add(compiler.createMessage( |
| 908 declaration, MessageKind.THIS_IS_THE_METHOD)); |
| 909 } |
| 910 compiler.reportWarning(warning, infos); |
| 911 } |
| 912 |
| 913 /// Report a warning on [node] if [argumentType] is not assignable to |
| 914 /// [parameterType]. |
| 915 void checkAssignable(Spannable node, |
| 916 DartType argumentType, |
| 917 DartType parameterType) { |
| 918 if (!types.isAssignable(argumentType, parameterType)) { |
| 919 reportWarning(compiler.createMessage( |
| 920 node, |
| 921 MessageKind.NOT_ASSIGNABLE, |
| 922 {'fromType': argumentType, 'toType': parameterType})); |
| 923 } |
| 924 } |
| 925 |
| 896 FunctionType funType = unaliasedType; | 926 FunctionType funType = unaliasedType; |
| 897 Iterator<DartType> parameterTypes = funType.parameterTypes.iterator; | 927 Iterator<DartType> parameterTypes = funType.parameterTypes.iterator; |
| 898 Iterator<DartType> optionalParameterTypes = | 928 Iterator<DartType> optionalParameterTypes = |
| 899 funType.optionalParameterTypes.iterator; | 929 funType.optionalParameterTypes.iterator; |
| 900 while (!arguments.isEmpty) { | 930 while (!arguments.isEmpty) { |
| 901 Node argument = arguments.head; | 931 Node argument = arguments.head; |
| 902 NamedArgument namedArgument = argument.asNamedArgument(); | 932 NamedArgument namedArgument = argument.asNamedArgument(); |
| 903 if (namedArgument != null) { | 933 if (namedArgument != null) { |
| 904 argument = namedArgument.expression; | 934 argument = namedArgument.expression; |
| 905 String argumentName = namedArgument.name.source; | 935 String argumentName = namedArgument.name.source; |
| 906 DartType namedParameterType = | 936 DartType namedParameterType = |
| 907 funType.getNamedParameterType(argumentName); | 937 funType.getNamedParameterType(argumentName); |
| 908 if (namedParameterType == null) { | 938 if (namedParameterType == null) { |
| 909 error = true; | |
| 910 // TODO(johnniwinther): Provide better information on the called | 939 // TODO(johnniwinther): Provide better information on the called |
| 911 // function. | 940 // function. |
| 912 reportTypeWarning(argument, MessageKind.NAMED_ARGUMENT_NOT_FOUND, | 941 reportWarning(compiler.createMessage( |
| 913 {'argumentName': argumentName}); | 942 argument, |
| 943 MessageKind.NAMED_ARGUMENT_NOT_FOUND, |
| 944 {'argumentName': argumentName})); |
| 914 | 945 |
| 915 DartType argumentType = analyze(argument); | 946 DartType argumentType = analyze(argument); |
| 916 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 947 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 917 } else { | 948 } else { |
| 918 DartType argumentType = analyze(argument); | 949 DartType argumentType = analyze(argument); |
| 919 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 950 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 920 if (!checkAssignable(argument, argumentType, namedParameterType)) { | 951 checkAssignable(argument, argumentType, namedParameterType); |
| 921 error = true; | |
| 922 } | |
| 923 } | 952 } |
| 924 } else { | 953 } else { |
| 925 if (!parameterTypes.moveNext()) { | 954 if (!parameterTypes.moveNext()) { |
| 926 if (!optionalParameterTypes.moveNext()) { | 955 if (!optionalParameterTypes.moveNext()) { |
| 927 error = true; | 956 |
| 928 // TODO(johnniwinther): Provide better information on the | 957 // TODO(johnniwinther): Provide better information on the |
| 929 // called function. | 958 // called function. |
| 930 reportTypeWarning(argument, MessageKind.ADDITIONAL_ARGUMENT); | 959 reportWarning(compiler.createMessage( |
| 960 argument, MessageKind.ADDITIONAL_ARGUMENT)); |
| 931 | 961 |
| 932 DartType argumentType = analyze(argument); | 962 DartType argumentType = analyze(argument); |
| 933 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 963 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 934 } else { | 964 } else { |
| 935 DartType argumentType = analyze(argument); | 965 DartType argumentType = analyze(argument); |
| 936 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 966 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 937 if (!checkAssignable(argument, | 967 checkAssignable( |
| 938 argumentType, | 968 argument, argumentType, optionalParameterTypes.current); |
| 939 optionalParameterTypes.current)) { | |
| 940 error = true; | |
| 941 } | |
| 942 } | 969 } |
| 943 } else { | 970 } else { |
| 944 DartType argumentType = analyze(argument); | 971 DartType argumentType = analyze(argument); |
| 945 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 972 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 946 if (!checkAssignable(argument, argumentType, | 973 checkAssignable(argument, argumentType, parameterTypes.current); |
| 947 parameterTypes.current)) { | |
| 948 error = true; | |
| 949 } | |
| 950 } | 974 } |
| 951 } | 975 } |
| 952 arguments = arguments.tail; | 976 arguments = arguments.tail; |
| 953 } | 977 } |
| 954 if (parameterTypes.moveNext()) { | 978 if (parameterTypes.moveNext()) { |
| 955 error = true; | |
| 956 // TODO(johnniwinther): Provide better information on the called | 979 // TODO(johnniwinther): Provide better information on the called |
| 957 // function. | 980 // function. |
| 958 reportTypeWarning(send, MessageKind.MISSING_ARGUMENT, | 981 reportWarning(compiler.createMessage( |
| 959 {'argumentType': parameterTypes.current}); | 982 send, MessageKind.MISSING_ARGUMENT, |
| 960 } | 983 {'argumentType': parameterTypes.current})); |
| 961 if (error) { | |
| 962 // TODO(johnniwinther): Improve access to declaring element and handle | |
| 963 // synthesized member signatures. Currently function typed instance | |
| 964 // members provide no access to their own name. | |
| 965 if (element == null) { | |
| 966 element = type.element; | |
| 967 } else if (type.isTypedef) { | |
| 968 reportTypeInfo(element, | |
| 969 MessageKind.THIS_IS_THE_DECLARATION, | |
| 970 {'name': element.name}); | |
| 971 element = type.element; | |
| 972 } | |
| 973 if (element != null) { | |
| 974 reportTypeInfo(element, MessageKind.THIS_IS_THE_METHOD); | |
| 975 } | |
| 976 } | 984 } |
| 977 } else { | 985 } else { |
| 978 while(!arguments.isEmpty) { | 986 while(!arguments.isEmpty) { |
| 979 DartType argumentType = analyze(arguments.head); | 987 DartType argumentType = analyze(arguments.head); |
| 980 if (argumentTypes != null) argumentTypes.addLast(argumentType); | 988 if (argumentTypes != null) argumentTypes.addLast(argumentType); |
| 981 arguments = arguments.tail; | 989 arguments = arguments.tail; |
| 982 } | 990 } |
| 983 } | 991 } |
| 984 } | 992 } |
| 985 | 993 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1206 if (variable != null && | 1214 if (variable != null && |
| 1207 (variable.isVariable || variable.isParameter)) { | 1215 (variable.isVariable || variable.isParameter)) { |
| 1208 DartType knownType = getKnownType(variable); | 1216 DartType knownType = getKnownType(variable); |
| 1209 if (!knownType.isDynamic) { | 1217 if (!knownType.isDynamic) { |
| 1210 DartType shownType = elements.getType(node.arguments.head); | 1218 DartType shownType = elements.getType(node.arguments.head); |
| 1211 TypePromotion typePromotion = | 1219 TypePromotion typePromotion = |
| 1212 new TypePromotion(node, variable, shownType); | 1220 new TypePromotion(node, variable, shownType); |
| 1213 if (!types.isMoreSpecific(shownType, knownType)) { | 1221 if (!types.isMoreSpecific(shownType, knownType)) { |
| 1214 String variableName = variable.name; | 1222 String variableName = variable.name; |
| 1215 if (!types.isSubtype(shownType, knownType)) { | 1223 if (!types.isSubtype(shownType, knownType)) { |
| 1216 typePromotion.addHint(node, | 1224 typePromotion.addHint(compiler.createMessage( |
| 1225 node, |
| 1217 MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, | 1226 MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, |
| 1218 {'variableName': variableName, | 1227 {'variableName': variableName, |
| 1219 'shownType': shownType, | 1228 'shownType': shownType, |
| 1220 'knownType': knownType}); | 1229 'knownType': knownType})); |
| 1221 } else { | 1230 } else { |
| 1222 DartType shownTypeSuggestion = | 1231 DartType shownTypeSuggestion = |
| 1223 computeMoreSpecificType(shownType, knownType); | 1232 computeMoreSpecificType(shownType, knownType); |
| 1224 if (shownTypeSuggestion != null) { | 1233 if (shownTypeSuggestion != null) { |
| 1225 typePromotion.addHint(node, | 1234 typePromotion.addHint(compiler.createMessage( |
| 1235 node, |
| 1226 MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, | 1236 MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, |
| 1227 {'variableName': variableName, | 1237 {'variableName': variableName, |
| 1228 'shownType': shownType, | 1238 'shownType': shownType, |
| 1229 'shownTypeSuggestion': shownTypeSuggestion, | 1239 'shownTypeSuggestion': shownTypeSuggestion, |
| 1230 'knownType': knownType}); | 1240 'knownType': knownType})); |
| 1231 } else { | 1241 } else { |
| 1232 typePromotion.addHint(node, | 1242 typePromotion.addHint(compiler.createMessage( |
| 1243 node, |
| 1233 MessageKind.NOT_MORE_SPECIFIC, | 1244 MessageKind.NOT_MORE_SPECIFIC, |
| 1234 {'variableName': variableName, | 1245 {'variableName': variableName, |
| 1235 'shownType': shownType, | 1246 'shownType': shownType, |
| 1236 'knownType': knownType}); | 1247 'knownType': knownType})); |
| 1237 } | 1248 } |
| 1238 } | 1249 } |
| 1239 } | 1250 } |
| 1240 showTypePromotion(node, typePromotion); | 1251 showTypePromotion(node, typePromotion); |
| 1241 } | 1252 } |
| 1242 } | 1253 } |
| 1243 } | 1254 } |
| 1244 return boolType; | 1255 return boolType; |
| 1245 } if (node.isOperator && identical(name, 'as')) { | 1256 } if (node.isOperator && identical(name, 'as')) { |
| 1246 analyze(node.receiver); | 1257 analyze(node.receiver); |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1918 ConstantExpression caseConstant = | 1929 ConstantExpression caseConstant = |
| 1919 compiler.resolver.constantCompiler.compileNode( | 1930 compiler.resolver.constantCompiler.compileNode( |
| 1920 caseMatch.expression, elements); | 1931 caseMatch.expression, elements); |
| 1921 enumValues.remove( | 1932 enumValues.remove( |
| 1922 compiler.constants.getConstantValue(caseConstant)); | 1933 compiler.constants.getConstantValue(caseConstant)); |
| 1923 } | 1934 } |
| 1924 } | 1935 } |
| 1925 } | 1936 } |
| 1926 unreferencedFields.addAll(enumValues.values); | 1937 unreferencedFields.addAll(enumValues.values); |
| 1927 if (!unreferencedFields.isEmpty) { | 1938 if (!unreferencedFields.isEmpty) { |
| 1928 compiler.reportWarning(node, MessageKind.MISSING_ENUM_CASES, | 1939 compiler.reportWarningMessage( |
| 1940 node, MessageKind.MISSING_ENUM_CASES, |
| 1929 {'enumType': expressionType, | 1941 {'enumType': expressionType, |
| 1930 'enumValues': unreferencedFields.map((e) => e.name).join(', ')}); | 1942 'enumValues': unreferencedFields.map( |
| 1943 (e) => e.name).join(', ')}); |
| 1931 } | 1944 } |
| 1932 }); | 1945 }); |
| 1933 } | 1946 } |
| 1934 | 1947 |
| 1935 return const StatementType(); | 1948 return const StatementType(); |
| 1936 } | 1949 } |
| 1937 | 1950 |
| 1938 visitSwitchCase(SwitchCase node) { | 1951 visitSwitchCase(SwitchCase node) { |
| 1939 return analyze(node.statements); | 1952 return analyze(node.statements); |
| 1940 } | 1953 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1957 | 1970 |
| 1958 visitTypedef(Typedef node) { | 1971 visitTypedef(Typedef node) { |
| 1959 // Do not typecheck [Typedef] nodes. | 1972 // Do not typecheck [Typedef] nodes. |
| 1960 } | 1973 } |
| 1961 | 1974 |
| 1962 visitNode(Node node) { | 1975 visitNode(Node node) { |
| 1963 compiler.internalError(node, | 1976 compiler.internalError(node, |
| 1964 'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 1977 'Unexpected node ${node.getObjectDescription()} in the type checker.'); |
| 1965 } | 1978 } |
| 1966 } | 1979 } |
| OLD | NEW |