OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.js_backend.patch_resolver; | 5 library dart2js.js_backend.patch_resolver; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/resolution.dart' show | 8 import '../common/resolution.dart' show Resolution; |
9 Resolution; | 9 import '../common/tasks.dart' show CompilerTask; |
10 import '../common/tasks.dart' show | 10 import '../compiler.dart' show Compiler; |
11 CompilerTask; | |
12 import '../compiler.dart' show | |
13 Compiler; | |
14 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
15 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
16 import '../elements/modelx.dart'; | 13 import '../elements/modelx.dart'; |
17 import '../tree/tree.dart'; | 14 import '../tree/tree.dart'; |
18 | 15 |
19 class PatchResolverTask extends CompilerTask { | 16 class PatchResolverTask extends CompilerTask { |
20 PatchResolverTask(Compiler compiler) : super(compiler); | 17 PatchResolverTask(Compiler compiler) : super(compiler); |
21 | 18 |
22 Resolution get resolution => compiler.resolution; | 19 Resolution get resolution => compiler.resolution; |
23 | 20 |
24 String get name => 'JavaScript patch resolver'; | 21 String get name => 'JavaScript patch resolver'; |
25 | 22 |
26 FunctionElement resolveExternalFunction(FunctionElementX element) { | 23 FunctionElement resolveExternalFunction(FunctionElementX element) { |
27 if (element.isPatched) { | 24 if (element.isPatched) { |
28 FunctionElementX patch = element.patch; | 25 FunctionElementX patch = element.patch; |
29 reporter.withCurrentElement(patch, () { | 26 reporter.withCurrentElement(patch, () { |
30 patch.computeType(resolution); | 27 patch.computeType(resolution); |
31 }); | 28 }); |
32 checkMatchingPatchSignatures(element, patch); | 29 checkMatchingPatchSignatures(element, patch); |
33 element = patch; | 30 element = patch; |
34 } else if (!compiler.backend.isJsInterop(element)) { | 31 } else if (!compiler.backend.isJsInterop(element)) { |
35 reporter.reportErrorMessage( | 32 reporter.reportErrorMessage( |
36 element, MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION); | 33 element, MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION); |
37 } | 34 } |
38 return element; | 35 return element; |
39 } | 36 } |
40 | 37 |
41 void checkMatchingPatchParameters(FunctionElement origin, | 38 void checkMatchingPatchParameters(FunctionElement origin, |
42 List<Element> originParameters, | 39 List<Element> originParameters, List<Element> patchParameters) { |
43 List<Element> patchParameters) { | |
44 | |
45 assert(originParameters.length == patchParameters.length); | 40 assert(originParameters.length == patchParameters.length); |
46 for (int index = 0; index < originParameters.length; index++) { | 41 for (int index = 0; index < originParameters.length; index++) { |
47 ParameterElementX originParameter = originParameters[index]; | 42 ParameterElementX originParameter = originParameters[index]; |
48 ParameterElementX patchParameter = patchParameters[index]; | 43 ParameterElementX patchParameter = patchParameters[index]; |
49 // TODO(johnniwinther): Remove the conditional patching when we never | 44 // TODO(johnniwinther): Remove the conditional patching when we never |
50 // resolve the same method twice. | 45 // resolve the same method twice. |
51 if (!originParameter.isPatched) { | 46 if (!originParameter.isPatched) { |
52 originParameter.applyPatch(patchParameter); | 47 originParameter.applyPatch(patchParameter); |
53 } else { | 48 } else { |
54 assert(invariant(origin, originParameter.patch == patchParameter, | 49 assert(invariant(origin, originParameter.patch == patchParameter, |
55 message: "Inconsistent repatch of $originParameter.")); | 50 message: "Inconsistent repatch of $originParameter.")); |
56 } | 51 } |
57 DartType originParameterType = originParameter.computeType(resolution); | 52 DartType originParameterType = originParameter.computeType(resolution); |
58 DartType patchParameterType = patchParameter.computeType(resolution); | 53 DartType patchParameterType = patchParameter.computeType(resolution); |
59 if (originParameterType != patchParameterType) { | 54 if (originParameterType != patchParameterType) { |
60 reporter.reportError( | 55 reporter.reportError( |
61 reporter.createMessage( | 56 reporter.createMessage( |
62 originParameter, | 57 originParameter, MessageKind.PATCH_PARAMETER_TYPE_MISMATCH, { |
63 MessageKind.PATCH_PARAMETER_TYPE_MISMATCH, | 58 'methodName': origin.name, |
64 {'methodName': origin.name, | 59 'parameterName': originParameter.name, |
65 'parameterName': originParameter.name, | 60 'originParameterType': originParameterType, |
66 'originParameterType': originParameterType, | 61 'patchParameterType': patchParameterType |
67 'patchParameterType': patchParameterType}), | 62 }), |
68 <DiagnosticMessage>[ | 63 <DiagnosticMessage>[ |
69 reporter.createMessage( | 64 reporter.createMessage( |
70 patchParameter, | 65 patchParameter, |
71 MessageKind.PATCH_POINT_TO_PARAMETER, | 66 MessageKind.PATCH_POINT_TO_PARAMETER, |
72 {'parameterName': patchParameter.name}), | 67 {'parameterName': patchParameter.name}), |
73 ]); | 68 ]); |
74 } else { | 69 } else { |
75 // Hack: Use unparser to test parameter equality. This only works | 70 // Hack: Use unparser to test parameter equality. This only works |
76 // because we are restricting patch uses and the approach cannot be used | 71 // because we are restricting patch uses and the approach cannot be used |
77 // elsewhere. | 72 // elsewhere. |
78 | 73 |
79 // The node contains the type, so there is a potential overlap. | 74 // The node contains the type, so there is a potential overlap. |
80 // Therefore we only check the text if the types are identical. | 75 // Therefore we only check the text if the types are identical. |
81 String originParameterText = originParameter.node.toString(); | 76 String originParameterText = originParameter.node.toString(); |
82 String patchParameterText = patchParameter.node.toString(); | 77 String patchParameterText = patchParameter.node.toString(); |
83 if (originParameterText != patchParameterText | 78 if (originParameterText != patchParameterText |
84 // We special case the list constructor because of the | 79 // We special case the list constructor because of the |
85 // optional parameter. | 80 // optional parameter. |
86 && origin != compiler.unnamedListConstructor) { | 81 && |
| 82 origin != compiler.unnamedListConstructor) { |
87 reporter.reportError( | 83 reporter.reportError( |
88 reporter.createMessage( | 84 reporter.createMessage( |
89 originParameter, | 85 originParameter, MessageKind.PATCH_PARAMETER_MISMATCH, { |
90 MessageKind.PATCH_PARAMETER_MISMATCH, | 86 'methodName': origin.name, |
91 {'methodName': origin.name, | 87 'originParameter': originParameterText, |
92 'originParameter': originParameterText, | 88 'patchParameter': patchParameterText |
93 'patchParameter': patchParameterText}), | 89 }), |
94 <DiagnosticMessage>[ | 90 <DiagnosticMessage>[ |
95 reporter.createMessage( | 91 reporter.createMessage( |
96 patchParameter, | 92 patchParameter, |
97 MessageKind.PATCH_POINT_TO_PARAMETER, | 93 MessageKind.PATCH_POINT_TO_PARAMETER, |
98 {'parameterName': patchParameter.name}), | 94 {'parameterName': patchParameter.name}), |
99 ]); | 95 ]); |
100 | |
101 } | 96 } |
102 } | 97 } |
103 } | 98 } |
104 } | 99 } |
105 | 100 |
106 void checkMatchingPatchSignatures(FunctionElement origin, | 101 void checkMatchingPatchSignatures( |
107 FunctionElement patch) { | 102 FunctionElement origin, FunctionElement patch) { |
108 // TODO(johnniwinther): Show both origin and patch locations on errors. | 103 // TODO(johnniwinther): Show both origin and patch locations on errors. |
109 FunctionSignature originSignature = origin.functionSignature; | 104 FunctionSignature originSignature = origin.functionSignature; |
110 FunctionExpression patchTree = patch.node; | 105 FunctionExpression patchTree = patch.node; |
111 FunctionSignature patchSignature = patch.functionSignature; | 106 FunctionSignature patchSignature = patch.functionSignature; |
112 | 107 |
113 if (originSignature.type.returnType != patchSignature.type.returnType) { | 108 if (originSignature.type.returnType != patchSignature.type.returnType) { |
114 reporter.withCurrentElement(patch, () { | 109 reporter.withCurrentElement(patch, () { |
115 Node errorNode = | 110 Node errorNode = |
116 patchTree.returnType != null ? patchTree.returnType : patchTree; | 111 patchTree.returnType != null ? patchTree.returnType : patchTree; |
117 reporter.reportErrorMessage( | 112 reporter.reportErrorMessage( |
118 errorNode, MessageKind.PATCH_RETURN_TYPE_MISMATCH, | 113 errorNode, MessageKind.PATCH_RETURN_TYPE_MISMATCH, { |
119 {'methodName': origin.name, | 114 'methodName': origin.name, |
120 'originReturnType': originSignature.type.returnType, | 115 'originReturnType': originSignature.type.returnType, |
121 'patchReturnType': patchSignature.type.returnType}); | 116 'patchReturnType': patchSignature.type.returnType |
| 117 }); |
122 }); | 118 }); |
123 } | 119 } |
124 if (originSignature.requiredParameterCount != | 120 if (originSignature.requiredParameterCount != |
125 patchSignature.requiredParameterCount) { | 121 patchSignature.requiredParameterCount) { |
126 reporter.withCurrentElement(patch, () { | 122 reporter.withCurrentElement(patch, () { |
127 reporter.reportErrorMessage( | 123 reporter.reportErrorMessage( |
128 patchTree, | 124 patchTree, MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH, { |
129 MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH, | 125 'methodName': origin.name, |
130 {'methodName': origin.name, | 126 'originParameterCount': originSignature.requiredParameterCount, |
131 'originParameterCount': originSignature.requiredParameterCount, | 127 'patchParameterCount': patchSignature.requiredParameterCount |
132 'patchParameterCount': patchSignature.requiredParameterCount}); | 128 }); |
133 }); | 129 }); |
134 } else { | 130 } else { |
135 checkMatchingPatchParameters(origin, | 131 checkMatchingPatchParameters(origin, originSignature.requiredParameters, |
136 originSignature.requiredParameters, | 132 patchSignature.requiredParameters); |
137 patchSignature.requiredParameters); | |
138 } | 133 } |
139 if (originSignature.optionalParameterCount != 0 && | 134 if (originSignature.optionalParameterCount != 0 && |
140 patchSignature.optionalParameterCount != 0) { | 135 patchSignature.optionalParameterCount != 0) { |
141 if (originSignature.optionalParametersAreNamed != | 136 if (originSignature.optionalParametersAreNamed != |
142 patchSignature.optionalParametersAreNamed) { | 137 patchSignature.optionalParametersAreNamed) { |
143 reporter.withCurrentElement(patch, () { | 138 reporter.withCurrentElement(patch, () { |
144 reporter.reportErrorMessage( | 139 reporter.reportErrorMessage( |
145 patchTree, | 140 patchTree, |
146 MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH, | 141 MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH, |
147 {'methodName': origin.name}); | 142 {'methodName': origin.name}); |
148 }); | 143 }); |
149 } | 144 } |
150 } | 145 } |
151 if (originSignature.optionalParameterCount != | 146 if (originSignature.optionalParameterCount != |
152 patchSignature.optionalParameterCount) { | 147 patchSignature.optionalParameterCount) { |
153 reporter.withCurrentElement(patch, () { | 148 reporter.withCurrentElement(patch, () { |
154 reporter.reportErrorMessage( | 149 reporter.reportErrorMessage( |
155 patchTree, | 150 patchTree, MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH, { |
156 MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH, | 151 'methodName': origin.name, |
157 {'methodName': origin.name, | 152 'originParameterCount': originSignature.optionalParameterCount, |
158 'originParameterCount': originSignature.optionalParameterCount, | 153 'patchParameterCount': patchSignature.optionalParameterCount |
159 'patchParameterCount': patchSignature.optionalParameterCount}); | 154 }); |
160 }); | 155 }); |
161 } else { | 156 } else { |
162 checkMatchingPatchParameters(origin, | 157 checkMatchingPatchParameters(origin, originSignature.optionalParameters, |
163 originSignature.optionalParameters, | 158 patchSignature.optionalParameters); |
164 patchSignature.optionalParameters); | |
165 } | 159 } |
166 } | 160 } |
167 | |
168 } | 161 } |
OLD | NEW |