Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(410)

Side by Side Diff: pkg/compiler/lib/src/typechecker.dart

Issue 1334673002: Add warnings and hints to for-in. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/helpers/stats.dart ('k') | tests/compiler/dart2js/mock_compiler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
8 Identifiers;
7 import 'common/tasks.dart' show 9 import 'common/tasks.dart' show
8 CompilerTask; 10 CompilerTask;
9 import 'compiler.dart' show 11 import 'compiler.dart' show
10 Compiler; 12 Compiler;
11 import 'constants/expressions.dart'; 13 import 'constants/expressions.dart';
12 import 'constants/values.dart'; 14 import 'constants/values.dart';
13 import 'core_types.dart'; 15 import 'core_types.dart';
14 import 'dart_types.dart'; 16 import 'dart_types.dart';
15 import 'diagnostics/invariant.dart' show 17 import 'diagnostics/invariant.dart' show
16 invariant; 18 invariant;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 import '../compiler_new.dart' as api; 57 import '../compiler_new.dart' as api;
56 58
57 class TypeCheckerTask extends CompilerTask { 59 class TypeCheckerTask extends CompilerTask {
58 TypeCheckerTask(Compiler compiler) : super(compiler); 60 TypeCheckerTask(Compiler compiler) : super(compiler);
59 String get name => "Type checker"; 61 String get name => "Type checker";
60 62
61 void check(AstElement element) { 63 void check(AstElement element) {
62 if (element.isClass) return; 64 if (element.isClass) return;
63 if (element.isTypedef) return; 65 if (element.isTypedef) return;
64 ResolvedAst resolvedAst = element.resolvedAst; 66 ResolvedAst resolvedAst = element.resolvedAst;
65 compiler.withCurrentElement(element, () { 67 compiler.withCurrentElement(element.implementation, () {
66 measure(() { 68 measure(() {
67 TypeCheckerVisitor visitor = new TypeCheckerVisitor( 69 TypeCheckerVisitor visitor = new TypeCheckerVisitor(
68 compiler, resolvedAst.elements, compiler.types); 70 compiler, resolvedAst.elements, compiler.types);
69 if (element.isField) { 71 if (element.isField) {
70 visitor.analyzingInitializer = true; 72 visitor.analyzingInitializer = true;
71 } 73 }
72 resolvedAst.node.accept(visitor); 74 resolvedAst.node.accept(visitor);
73 }); 75 });
74 }); 76 });
75 } 77 }
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 } 415 }
414 } 416 }
415 417
416 LibraryElement get currentLibrary => elements.analyzedElement.library; 418 LibraryElement get currentLibrary => elements.analyzedElement.library;
417 419
418 reportTypeWarning(Spannable spannable, MessageKind kind, 420 reportTypeWarning(Spannable spannable, MessageKind kind,
419 [Map arguments = const {}]) { 421 [Map arguments = const {}]) {
420 compiler.reportWarning(spannable, kind, arguments); 422 compiler.reportWarning(spannable, kind, arguments);
421 } 423 }
422 424
425 reportMessage(Spannable spannable, MessageKind kind,
426 Map arguments,
427 {bool isHint: false}) {
428 if (isHint) {
429 compiler.reportHint(spannable, kind, arguments);
430 } else {
431 compiler.reportWarning(spannable, kind, arguments);
432 }
433 }
434
423 reportTypeInfo(Spannable spannable, MessageKind kind, 435 reportTypeInfo(Spannable spannable, MessageKind kind,
424 [Map arguments = const {}]) { 436 [Map arguments = const {}]) {
425 compiler.reportInfo(spannable, kind, arguments); 437 compiler.reportInfo(spannable, kind, arguments);
426 } 438 }
427 439
428 reportTypePromotionHint(TypePromotion typePromotion) { 440 reportTypePromotionHint(TypePromotion typePromotion) {
429 if (!reportedTypePromotions.contains(typePromotion)) { 441 if (!reportedTypePromotions.contains(typePromotion)) {
430 reportedTypePromotions.add(typePromotion); 442 reportedTypePromotions.add(typePromotion);
431 for (TypePromotionMessage message in typePromotion.messages) { 443 for (TypePromotionMessage message in typePromotion.messages) {
432 switch (message.diagnostic) { 444 switch (message.diagnostic) {
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 node, 738 node,
727 MessageKind.PRIVATE_ACCESS, 739 MessageKind.PRIVATE_ACCESS,
728 {'name': name, 740 {'name': name,
729 'libraryName': element.library.getLibraryOrScriptName()}); 741 'libraryName': element.library.getLibraryOrScriptName()});
730 } 742 }
731 743
732 } 744 }
733 745
734 ElementAccess lookupMember(Node node, DartType receiverType, String name, 746 ElementAccess lookupMember(Node node, DartType receiverType, String name,
735 MemberKind memberKind, Element receiverElement, 747 MemberKind memberKind, Element receiverElement,
736 {bool lookupClassMember: false}) { 748 {bool lookupClassMember: false,
749 bool isHint: false}) {
737 if (receiverType.treatAsDynamic) { 750 if (receiverType.treatAsDynamic) {
738 return const DynamicAccess(); 751 return const DynamicAccess();
739 } 752 }
740 753
741 Name memberName = new Name(name, currentLibrary, 754 Name memberName = new Name(name, currentLibrary,
742 isSetter: memberKind == MemberKind.SETTER); 755 isSetter: memberKind == MemberKind.SETTER);
743 756
744 // Compute the unaliased type of the first non type variable bound of 757 // Compute the unaliased type of the first non type variable bound of
745 // [type]. 758 // [type].
746 DartType computeUnaliasedBound(DartType type) { 759 DartType computeUnaliasedBound(DartType type) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 // We didn't find a member with the correct name. If this lookup is for a 846 // We didn't find a member with the correct name. If this lookup is for a
834 // super or redirecting initializer, the resolver has already emitted an 847 // super or redirecting initializer, the resolver has already emitted an
835 // error message. If the target is a proxy, no warning needs to be emitted. 848 // error message. If the target is a proxy, no warning needs to be emitted.
836 // Otherwise, try to emit the most precise warning. 849 // Otherwise, try to emit the most precise warning.
837 if (!interface.element.isProxy && !analyzingInitializer) { 850 if (!interface.element.isProxy && !analyzingInitializer) {
838 bool foundPrivateMember = false; 851 bool foundPrivateMember = false;
839 if (memberName.isPrivate) { 852 if (memberName.isPrivate) {
840 void findPrivateMember(MemberSignature member) { 853 void findPrivateMember(MemberSignature member) {
841 if (memberName.isSimilarTo(member.name)) { 854 if (memberName.isSimilarTo(member.name)) {
842 PrivateName privateName = member.name; 855 PrivateName privateName = member.name;
843 reportTypeWarning( 856 reportMessage(
844 node, 857 node,
845 MessageKind.PRIVATE_ACCESS, 858 MessageKind.PRIVATE_ACCESS,
846 {'name': name, 859 {'name': name,
847 'libraryName': privateName.library.getLibraryOrScriptName()}); 860 'libraryName': privateName.library.getLibraryOrScriptName()},
861 isHint: isHint);
848 foundPrivateMember = true; 862 foundPrivateMember = true;
849 } 863 }
850 } 864 }
851 // TODO(johnniwinther): Avoid computation of all class members. 865 // TODO(johnniwinther): Avoid computation of all class members.
852 MembersCreator.computeAllClassMembers(compiler, interface.element); 866 MembersCreator.computeAllClassMembers(compiler, interface.element);
853 if (lookupClassMember) { 867 if (lookupClassMember) {
854 interface.element.forEachClassMember(findPrivateMember); 868 interface.element.forEachClassMember(findPrivateMember);
855 } else { 869 } else {
856 interface.element.forEachInterfaceMember(findPrivateMember); 870 interface.element.forEachInterfaceMember(findPrivateMember);
857 } 871 }
858 872
859 } 873 }
860 if (!foundPrivateMember) { 874 if (!foundPrivateMember) {
861 switch (memberKind) { 875 switch (memberKind) {
862 case MemberKind.METHOD: 876 case MemberKind.METHOD:
863 reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND, 877 reportMessage(node, MessageKind.METHOD_NOT_FOUND,
864 {'className': receiverType.name, 'memberName': name}); 878 {'className': receiverType.name, 'memberName': name},
879 isHint: isHint);
865 break; 880 break;
866 case MemberKind.OPERATOR: 881 case MemberKind.OPERATOR:
867 reportTypeWarning(node, MessageKind.OPERATOR_NOT_FOUND, 882 reportMessage(node, MessageKind.OPERATOR_NOT_FOUND,
868 {'className': receiverType.name, 'memberName': name}); 883 {'className': receiverType.name, 'memberName': name},
884 isHint: isHint);
869 break; 885 break;
870 case MemberKind.GETTER: 886 case MemberKind.GETTER:
871 if (lookupMemberSignature(memberName.setter, interface) != null) { 887 if (lookupMemberSignature(memberName.setter, interface) != null) {
872 // A setter is present so warn explicitly about the missing 888 // A setter is present so warn explicitly about the missing
873 // getter. 889 // getter.
874 reportTypeWarning(node, MessageKind.GETTER_NOT_FOUND, 890 reportMessage(node, MessageKind.GETTER_NOT_FOUND,
875 {'className': receiverType.name, 'memberName': name}); 891 {'className': receiverType.name, 'memberName': name},
892 isHint: isHint);
876 } else if (name == 'await') { 893 } else if (name == 'await') {
877 Map arguments = {'className': receiverType.name}; 894 Map arguments = {'className': receiverType.name};
878 String functionName = executableContext.name; 895 String functionName = executableContext.name;
879 MessageKind kind; 896 MessageKind kind;
880 if (functionName == '') { 897 if (functionName == '') {
881 kind = MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE; 898 kind = MessageKind.AWAIT_MEMBER_NOT_FOUND_IN_CLOSURE;
882 } else { 899 } else {
883 kind = MessageKind.AWAIT_MEMBER_NOT_FOUND; 900 kind = MessageKind.AWAIT_MEMBER_NOT_FOUND;
884 arguments['functionName'] = functionName; 901 arguments['functionName'] = functionName;
885 } 902 }
886 reportTypeWarning(node, kind, arguments); 903 reportMessage(node, kind, arguments, isHint: isHint);
887 } else { 904 } else {
888 reportTypeWarning(node, MessageKind.MEMBER_NOT_FOUND, 905 reportMessage(node, MessageKind.MEMBER_NOT_FOUND,
889 {'className': receiverType.name, 'memberName': name}); 906 {'className': receiverType.name, 'memberName': name},
907 isHint: isHint);
890 } 908 }
891 break; 909 break;
892 case MemberKind.SETTER: 910 case MemberKind.SETTER:
893 reportTypeWarning(node, MessageKind.SETTER_NOT_FOUND, 911 reportMessage(node, MessageKind.SETTER_NOT_FOUND,
894 {'className': receiverType.name, 'memberName': name}); 912 {'className': receiverType.name, 'memberName': name},
913 isHint: isHint);
895 break; 914 break;
896 } 915 }
897 } 916 }
898 } 917 }
899 return const DynamicAccess(); 918 return const DynamicAccess();
900 } 919 }
901 920
902 DartType lookupMemberType(Node node, DartType type, String name, 921 DartType lookupMemberType(Node node, DartType type, String name,
903 MemberKind memberKind) { 922 MemberKind memberKind,
904 return lookupMember(node, type, name, memberKind, null) 923 {bool isHint: false}) {
924 return lookupMember(node, type, name, memberKind, null, isHint: isHint)
905 .computeType(compiler); 925 .computeType(compiler);
906 } 926 }
907 927
908 void analyzeArguments(Send send, Element element, DartType type, 928 void analyzeArguments(Send send, Element element, DartType type,
909 [LinkBuilder<DartType> argumentTypes]) { 929 [LinkBuilder<DartType> argumentTypes]) {
910 Link<Node> arguments = send.arguments; 930 Link<Node> arguments = send.arguments;
911 DartType unaliasedType = type.unalias(compiler); 931 DartType unaliasedType = type.unalias(compiler);
912 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) { 932 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) {
913 bool error = false; 933 bool error = false;
914 FunctionType funType = unaliasedType; 934 FunctionType funType = unaliasedType;
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after
1790 } 1810 }
1791 1811
1792 visitBreakStatement(BreakStatement node) { 1812 visitBreakStatement(BreakStatement node) {
1793 return const StatementType(); 1813 return const StatementType();
1794 } 1814 }
1795 1815
1796 visitContinueStatement(ContinueStatement node) { 1816 visitContinueStatement(ContinueStatement node) {
1797 return const StatementType(); 1817 return const StatementType();
1798 } 1818 }
1799 1819
1800 visitAsyncForIn(AsyncForIn node) { 1820 visitAsyncForIn(AsyncForIn node) {
sigurdm 2015/09/10 13:07:21 Could you do the same for async for-in?
Johnni Winther 2015/09/11 10:36:41 Will do in a follow-up (need helpers added in anot
1801 analyze(node.expression); 1821 analyze(node.expression);
1802 analyze(node.body); 1822 analyze(node.body);
1803 return const StatementType(); 1823 return const StatementType();
1804 } 1824 }
1805 1825
1806 visitSyncForIn(SyncForIn node) { 1826 visitSyncForIn(SyncForIn node) {
1807 analyze(node.expression); 1827 DartType elementType;
1828 VariableDefinitions declaredIdentifier =
1829 node.declaredIdentifier.asVariableDefinitions();
1830 if (declaredIdentifier != null) {
1831 elementType =
1832 analyzeWithDefault(declaredIdentifier.type, const DynamicType());
1833 } else {
1834 elementType = analyze(node.declaredIdentifier);
1835 }
1836 DartType expressionType = analyze(node.expression);
1837 DartType iteratorType = lookupMemberType(node.expression,
1838 expressionType, Identifiers.iterator, MemberKind.GETTER);
1839 DartType currentType = lookupMemberType(node.expression,
1840 iteratorType, Identifiers.current, MemberKind.GETTER,
1841 isHint: true);
1842 if (!types.isAssignable(currentType, elementType)) {
1843 reportMessage(node.expression,
1844 MessageKind.FORIN_NOT_ASSIGNABLE,
1845 {'currentType': currentType,
1846 'expressionType': expressionType,
1847 'elementType': elementType},
1848 isHint: true);
1849 }
1808 analyze(node.body); 1850 analyze(node.body);
1809 return const StatementType(); 1851 return const StatementType();
1810 } 1852 }
1811 1853
1812 visitLabeledStatement(LabeledStatement node) { 1854 visitLabeledStatement(LabeledStatement node) {
1813 return analyze(node.statement); 1855 return analyze(node.statement);
1814 } 1856 }
1815 1857
1816 visitLiteralMap(LiteralMap node) { 1858 visitLiteralMap(LiteralMap node) {
1817 InterfaceType mapType = elements.getType(node); 1859 InterfaceType mapType = elements.getType(node);
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1926 1968
1927 visitTypedef(Typedef node) { 1969 visitTypedef(Typedef node) {
1928 // Do not typecheck [Typedef] nodes. 1970 // Do not typecheck [Typedef] nodes.
1929 } 1971 }
1930 1972
1931 visitNode(Node node) { 1973 visitNode(Node node) {
1932 compiler.internalError(node, 1974 compiler.internalError(node,
1933 'Unexpected node ${node.getObjectDescription()} in the type checker.'); 1975 'Unexpected node ${node.getObjectDescription()} in the type checker.');
1934 } 1976 }
1935 } 1977 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/helpers/stats.dart ('k') | tests/compiler/dart2js/mock_compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698