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