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 result; | 461 return 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1217 if (variable != null && | 1221 if (variable != null && |
1218 (variable.isVariable || variable.isParameter)) { | 1222 (variable.isVariable || variable.isParameter)) { |
1219 DartType knownType = getKnownType(variable); | 1223 DartType knownType = getKnownType(variable); |
1220 if (!knownType.isDynamic) { | 1224 if (!knownType.isDynamic) { |
1221 DartType shownType = elements.getType(node.arguments.head); | 1225 DartType shownType = elements.getType(node.arguments.head); |
1222 TypePromotion typePromotion = | 1226 TypePromotion typePromotion = |
1223 new TypePromotion(node, variable, shownType); | 1227 new TypePromotion(node, variable, shownType); |
1224 if (!types.isMoreSpecific(shownType, knownType)) { | 1228 if (!types.isMoreSpecific(shownType, knownType)) { |
1225 String variableName = variable.name; | 1229 String variableName = variable.name; |
1226 if (!types.isSubtype(shownType, knownType)) { | 1230 if (!types.isSubtype(shownType, knownType)) { |
1227 typePromotion.addHint(compiler.createMessage( | 1231 typePromotion.addHint(reporter.createMessage( |
1228 node, | 1232 node, |
1229 MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, | 1233 MessageKind.NOT_MORE_SPECIFIC_SUBTYPE, |
1230 {'variableName': variableName, | 1234 {'variableName': variableName, |
1231 'shownType': shownType, | 1235 'shownType': shownType, |
1232 'knownType': knownType})); | 1236 'knownType': knownType})); |
1233 } else { | 1237 } else { |
1234 DartType shownTypeSuggestion = | 1238 DartType shownTypeSuggestion = |
1235 computeMoreSpecificType(shownType, knownType); | 1239 computeMoreSpecificType(shownType, knownType); |
1236 if (shownTypeSuggestion != null) { | 1240 if (shownTypeSuggestion != null) { |
1237 typePromotion.addHint(compiler.createMessage( | 1241 typePromotion.addHint(reporter.createMessage( |
1238 node, | 1242 node, |
1239 MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, | 1243 MessageKind.NOT_MORE_SPECIFIC_SUGGESTION, |
1240 {'variableName': variableName, | 1244 {'variableName': variableName, |
1241 'shownType': shownType, | 1245 'shownType': shownType, |
1242 'shownTypeSuggestion': shownTypeSuggestion, | 1246 'shownTypeSuggestion': shownTypeSuggestion, |
1243 'knownType': knownType})); | 1247 'knownType': knownType})); |
1244 } else { | 1248 } else { |
1245 typePromotion.addHint(compiler.createMessage( | 1249 typePromotion.addHint(reporter.createMessage( |
1246 node, | 1250 node, |
1247 MessageKind.NOT_MORE_SPECIFIC, | 1251 MessageKind.NOT_MORE_SPECIFIC, |
1248 {'variableName': variableName, | 1252 {'variableName': variableName, |
1249 'shownType': shownType, | 1253 'shownType': shownType, |
1250 'knownType': knownType})); | 1254 'knownType': knownType})); |
1251 } | 1255 } |
1252 } | 1256 } |
1253 } | 1257 } |
1254 showTypePromotion(node, typePromotion); | 1258 showTypePromotion(node, typePromotion); |
1255 } | 1259 } |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1524 case '*=': operatorName = '*'; break; | 1528 case '*=': operatorName = '*'; break; |
1525 case '/=': operatorName = '/'; break; | 1529 case '/=': operatorName = '/'; break; |
1526 case '%=': operatorName = '%'; break; | 1530 case '%=': operatorName = '%'; break; |
1527 case '~/=': operatorName = '~/'; break; | 1531 case '~/=': operatorName = '~/'; break; |
1528 case '&=': operatorName = '&'; break; | 1532 case '&=': operatorName = '&'; break; |
1529 case '|=': operatorName = '|'; break; | 1533 case '|=': operatorName = '|'; break; |
1530 case '^=': operatorName = '^'; break; | 1534 case '^=': operatorName = '^'; break; |
1531 case '<<=': operatorName = '<<'; break; | 1535 case '<<=': operatorName = '<<'; break; |
1532 case '>>=': operatorName = '>>'; break; | 1536 case '>>=': operatorName = '>>'; break; |
1533 default: | 1537 default: |
1534 compiler.internalError(node, 'Unexpected assignment operator $name.'); | 1538 reporter.internalError(node, 'Unexpected assignment operator $name.'); |
1535 } | 1539 } |
1536 if (node.isIndex) { | 1540 if (node.isIndex) { |
1537 // base[key] o= value for some operator o. | 1541 // base[key] o= value for some operator o. |
1538 final Node valueNode = node.arguments.tail.head; | 1542 final Node valueNode = node.arguments.tail.head; |
1539 final DartType value = analyze(valueNode); | 1543 final DartType value = analyze(valueNode); |
1540 return checkIndexAssignmentOperator( | 1544 return checkIndexAssignmentOperator( |
1541 node, operatorName, valueNode, value); | 1545 node, operatorName, valueNode, value); |
1542 } else { | 1546 } else { |
1543 // target o= value for some operator o. | 1547 // target o= value for some operator o. |
1544 final Node valueNode = node.arguments.head; | 1548 final Node valueNode = node.arguments.head; |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1932 ConstantExpression caseConstant = | 1936 ConstantExpression caseConstant = |
1933 compiler.resolver.constantCompiler.compileNode( | 1937 compiler.resolver.constantCompiler.compileNode( |
1934 caseMatch.expression, elements); | 1938 caseMatch.expression, elements); |
1935 enumValues.remove( | 1939 enumValues.remove( |
1936 compiler.constants.getConstantValue(caseConstant)); | 1940 compiler.constants.getConstantValue(caseConstant)); |
1937 } | 1941 } |
1938 } | 1942 } |
1939 } | 1943 } |
1940 unreferencedFields.addAll(enumValues.values); | 1944 unreferencedFields.addAll(enumValues.values); |
1941 if (!unreferencedFields.isEmpty) { | 1945 if (!unreferencedFields.isEmpty) { |
1942 compiler.reportWarningMessage( | 1946 reporter.reportWarningMessage( |
1943 node, MessageKind.MISSING_ENUM_CASES, | 1947 node, MessageKind.MISSING_ENUM_CASES, |
1944 {'enumType': expressionType, | 1948 {'enumType': expressionType, |
1945 'enumValues': unreferencedFields.map( | 1949 'enumValues': unreferencedFields.map( |
1946 (e) => e.name).join(', ')}); | 1950 (e) => e.name).join(', ')}); |
1947 } | 1951 } |
1948 }); | 1952 }); |
1949 } | 1953 } |
1950 | 1954 |
1951 return const StatementType(); | 1955 return const StatementType(); |
1952 } | 1956 } |
(...skipping 16 matching lines...) Expand all Loading... |
1969 | 1973 |
1970 visitCatchBlock(CatchBlock node) { | 1974 visitCatchBlock(CatchBlock node) { |
1971 return analyze(node.block); | 1975 return analyze(node.block); |
1972 } | 1976 } |
1973 | 1977 |
1974 visitTypedef(Typedef node) { | 1978 visitTypedef(Typedef node) { |
1975 // Do not typecheck [Typedef] nodes. | 1979 // Do not typecheck [Typedef] nodes. |
1976 } | 1980 } |
1977 | 1981 |
1978 visitNode(Node node) { | 1982 visitNode(Node node) { |
1979 compiler.internalError(node, | 1983 reporter.internalError(node, |
1980 'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 1984 'Unexpected node ${node.getObjectDescription()} in the type checker.'); |
1981 } | 1985 } |
1982 } | 1986 } |
OLD | NEW |