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 |