| 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 |