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

Side by Side Diff: pkg/compiler/lib/src/resolution/constructors.dart

Issue 1423623008: Improve messages and static use for super/this-calls. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Updated cf. comment. Created 5 years, 1 month 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.resolution.constructors; 5 library dart2js.resolution.constructors;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../compiler.dart' show 8 import '../compiler.dart' show
9 Compiler; 9 Compiler;
10 import '../constants/constructors.dart' show 10 import '../constants/constructors.dart' show
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 selector, MessageKind.INIT_STATIC_FIELD, {'fieldName': name}); 120 selector, MessageKind.INIT_STATIC_FIELD, {'fieldName': name});
121 } else { 121 } else {
122 field = target; 122 field = target;
123 } 123 }
124 } else { 124 } else {
125 reporter.reportErrorMessage( 125 reporter.reportErrorMessage(
126 init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); 126 init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
127 } 127 }
128 if (target != null) { 128 if (target != null) {
129 registry.useElement(init, target); 129 registry.useElement(init, target);
130 if (!target.isMalformed) {
131 registry.registerStaticUse(new StaticUse.fieldInit(target));
132 }
133 checkForDuplicateInitializers(target, init); 130 checkForDuplicateInitializers(target, init);
134 } 131 }
132 if (field != null) {
133 registry.registerStaticUse(new StaticUse.fieldInit(field));
134 }
135 // Resolve initializing value. 135 // Resolve initializing value.
136 ResolutionResult result = visitor.visitInStaticContext( 136 ResolutionResult result = visitor.visitInStaticContext(
137 init.arguments.head, 137 init.arguments.head,
138 inConstantInitializer: isConst); 138 inConstantInitializer: isConst);
139 if (isConst) { 139 if (isConst) {
140 if (result.isConstant && field != null) { 140 if (result.isConstant && field != null) {
141 // TODO(johnniwinther): Report error if `result.constant` is `null`. 141 // TODO(johnniwinther): Report error if `result.constant` is `null`.
142 fieldInitializers[field] = result.constant; 142 fieldInitializers[field] = result.constant;
143 } else { 143 } else {
144 isValidAsConstant = false; 144 isValidAsConstant = false;
145 } 145 }
146 } 146 }
147 } 147 }
148 148
149 InterfaceType getSuperOrThisLookupTarget(Node diagnosticNode, 149 InterfaceType getSuperOrThisLookupTarget(Node diagnosticNode,
150 {bool isSuperCall}) { 150 {bool isSuperCall}) {
151 if (isSuperCall) { 151 if (isSuperCall) {
152 // Calculate correct lookup target and constructor name. 152 // Calculate correct lookup target and constructor name.
153 if (constructor.enclosingClass.isObject) { 153 if (constructor.enclosingClass.isObject) {
154 reporter.reportErrorMessage( 154 reporter.reportErrorMessage(
155 diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT); 155 diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
156 isValidAsConstant = false; 156 isValidAsConstant = false;
157 } else { 157 } else {
158 return constructor.enclosingClass.supertype; 158 return constructor.enclosingClass.supertype;
159 } 159 }
160 } 160 }
161 return constructor.enclosingClass.thisType; 161 return constructor.enclosingClass.thisType;
162 } 162 }
163 163
164 ResolutionResult resolveSuperOrThisForSend(Send call) { 164 ResolutionResult resolveSuperOrThisForSend(Send node) {
165 // Resolve the selector and the arguments. 165 // Resolve the selector and the arguments.
166 ArgumentsResult argumentsResult = visitor.inStaticContext(() { 166 ArgumentsResult argumentsResult = visitor.inStaticContext(() {
167 visitor.resolveSelector(call, null); 167 // TODO(johnniwinther): Remove this when [SendStructure] is used directly.
168 return visitor.resolveArguments(call.argumentsNode); 168 visitor.resolveSelector(node, null);
169 return visitor.resolveArguments(node.argumentsNode);
169 }, inConstantInitializer: isConst); 170 }, inConstantInitializer: isConst);
170 171
171 bool isSuperCall = Initializers.isSuperConstructorCall(call); 172 bool isSuperCall = Initializers.isSuperConstructorCall(node);
172 InterfaceType targetType = 173 InterfaceType targetType =
173 getSuperOrThisLookupTarget(call, isSuperCall: isSuperCall); 174 getSuperOrThisLookupTarget(node, isSuperCall: isSuperCall);
174 ClassElement lookupTarget = targetType.element; 175 ClassElement lookupTarget = targetType.element;
175 Selector constructorSelector = 176 String constructorName =
176 visitor.getRedirectingThisOrSuperConstructorSelector(call); 177 visitor.getRedirectingThisOrSuperConstructorName(node).text;
177 ConstructorElement calledConstructor = findConstructor( 178 ConstructorElement foundConstructor = findConstructor(
178 constructor.library, lookupTarget, constructorSelector.name); 179 constructor.library, lookupTarget, constructorName);
179 180
180 final bool isImplicitSuperCall = false; 181 final bool isImplicitSuperCall = false;
181 final String className = lookupTarget.name; 182 final String className = lookupTarget.name;
182 verifyThatConstructorMatchesCall(calledConstructor, 183 CallStructure callStructure = argumentsResult.callStructure;
183 argumentsResult.callStructure, 184 ConstructorElement calledConstructor = verifyThatConstructorMatchesCall(
184 isImplicitSuperCall, 185 node,
185 call, 186 foundConstructor,
186 className, 187 callStructure,
187 constructorSelector); 188 className,
188 if (calledConstructor != null) { 189 constructorName: constructorName,
189 registry.useElement(call, calledConstructor); 190 isThisCall: !isSuperCall,
191 isImplicitSuperCall: false);
192 // TODO(johnniwinther): Remove this when information is pulled from an
193 // [InitializerStructure].
194 registry.useElement(node, calledConstructor);
195 if (!calledConstructor.isError) {
190 registry.registerStaticUse( 196 registry.registerStaticUse(
191 new StaticUse.superConstructorInvoke( 197 new StaticUse.superConstructorInvoke(
192 calledConstructor, argumentsResult.callStructure)); 198 calledConstructor, callStructure));
193 } 199 }
194 if (isConst) { 200 if (isConst) {
195 if (isValidAsConstant && 201 if (isValidAsConstant &&
196 calledConstructor.isConst && 202 calledConstructor.isConst &&
197 argumentsResult.isValidAsConstant) { 203 argumentsResult.isValidAsConstant) {
198 CallStructure callStructure = argumentsResult.callStructure;
199 List<ConstantExpression> arguments = argumentsResult.constantArguments; 204 List<ConstantExpression> arguments = argumentsResult.constantArguments;
200 return new ConstantResult( 205 return new ConstantResult(
201 call, 206 node,
202 new ConstructedConstantExpression( 207 new ConstructedConstantExpression(
203 targetType, 208 targetType,
204 calledConstructor, 209 calledConstructor,
205 callStructure, 210 callStructure,
206 arguments), 211 arguments),
207 element: calledConstructor); 212 element: calledConstructor);
208 } else { 213 } else {
209 isValidAsConstant = false; 214 isValidAsConstant = false;
210 } 215 }
211 } 216 }
212 return new ResolutionResult.forElement(calledConstructor); 217 return new ResolutionResult.forElement(calledConstructor);
213 } 218 }
214 219
215 ConstructedConstantExpression resolveImplicitSuperConstructorSend() { 220 ConstructedConstantExpression resolveImplicitSuperConstructorSend() {
216 // If the class has a super resolve the implicit super call. 221 // If the class has a super resolve the implicit super call.
217 ClassElement classElement = constructor.enclosingClass; 222 ClassElement classElement = constructor.enclosingClass;
218 ClassElement superClass = classElement.superclass; 223 ClassElement superClass = classElement.superclass;
219 if (!classElement.isObject) { 224 if (!classElement.isObject) {
220 assert(superClass != null); 225 assert(superClass != null);
221 assert(superClass.isResolved); 226 assert(superClass.isResolved);
222 227
223 InterfaceType targetType = 228 InterfaceType targetType =
224 getSuperOrThisLookupTarget(functionNode, isSuperCall: true); 229 getSuperOrThisLookupTarget(functionNode, isSuperCall: true);
225 ClassElement lookupTarget = targetType.element; 230 ClassElement lookupTarget = targetType.element;
226 Selector constructorSelector = new Selector.callDefaultConstructor(); 231 ConstructorElement calledConstructor =
227 ConstructorElement calledConstructor = findConstructor( 232 findConstructor(constructor.library, lookupTarget, '');
228 constructor.library,
229 lookupTarget,
230 constructorSelector.name);
231 233
232 final String className = lookupTarget.name; 234 final String className = lookupTarget.name;
233 final bool isImplicitSuperCall = true; 235 CallStructure callStructure = CallStructure.NO_ARGS;
234 verifyThatConstructorMatchesCall(calledConstructor, 236 ConstructorElement result = verifyThatConstructorMatchesCall(
235 CallStructure.NO_ARGS, 237 functionNode,
236 isImplicitSuperCall, 238 calledConstructor,
237 functionNode, 239 callStructure,
238 className, 240 className,
239 constructorSelector); 241 isImplicitSuperCall: true);
240 if (calledConstructor != null) { 242 if (!result.isError) {
241 registry.registerStaticUse( 243 registry.registerStaticUse(
242 new StaticUse.constructorInvoke( 244 new StaticUse.constructorInvoke(calledConstructor, callStructure));
243 calledConstructor, constructorSelector.callStructure));
244 } 245 }
245 246
246 if (isConst && isValidAsConstant) { 247 if (isConst && isValidAsConstant) {
247 return new ConstructedConstantExpression( 248 return new ConstructedConstantExpression(
248 targetType, 249 targetType,
249 calledConstructor, 250 result,
250 CallStructure.NO_ARGS, 251 CallStructure.NO_ARGS,
251 const <ConstantExpression>[]); 252 const <ConstantExpression>[]);
252 } 253 }
253 } 254 }
254 return null; 255 return null;
255 } 256 }
256 257
257 void verifyThatConstructorMatchesCall( 258 ConstructorElement reportAndCreateErroneousConstructor(
259 Spannable diagnosticNode,
260 String name,
261 MessageKind kind,
262 Map arguments) {
263 isValidAsConstant = false;
264 reporter.reportErrorMessage(
265 diagnosticNode, kind, arguments);
266 return new ErroneousConstructorElementX(
267 kind, arguments, name, visitor.currentClass);
268 }
269
270 /// Checks that [lookedupConstructor] is valid as a target for the super/this
271 /// constructor call using with the given [callStructure].
272 ///
273 /// If [lookedupConstructor] is valid it is returned, otherwise an error is
274 /// reported and an [ErroneousConstructorElement] is returned.
275 ConstructorElement verifyThatConstructorMatchesCall(
276 Node node,
258 ConstructorElementX lookedupConstructor, 277 ConstructorElementX lookedupConstructor,
259 CallStructure call, 278 CallStructure callStructure,
260 bool isImplicitSuperCall,
261 Node diagnosticNode,
262 String className, 279 String className,
263 Selector constructorSelector) { 280 {String constructorName: '',
264 if (lookedupConstructor == null || 281 bool isImplicitSuperCall: false,
265 !lookedupConstructor.isGenerativeConstructor) { 282 bool isThisCall: false}) {
266 String fullConstructorName = Elements.constructorNameForDiagnostics( 283 Element result = lookedupConstructor;
267 className, 284 if (lookedupConstructor == null) {
268 constructorSelector.name); 285 String fullConstructorName =
286 Elements.constructorNameForDiagnostics(className, constructorName);
269 MessageKind kind = isImplicitSuperCall 287 MessageKind kind = isImplicitSuperCall
270 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT 288 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
271 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; 289 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
272 reporter.reportErrorMessage( 290 result = reportAndCreateErroneousConstructor(
273 diagnosticNode, kind, {'constructorName': fullConstructorName}); 291 node, constructorName,
274 isValidAsConstant = false; 292 kind, {'constructorName': fullConstructorName});
293 } else if (!lookedupConstructor.isGenerativeConstructor) {
294 MessageKind kind = isThisCall
295 ? MessageKind.THIS_CALL_TO_FACTORY
296 : MessageKind.SUPER_CALL_TO_FACTORY;
297 result = reportAndCreateErroneousConstructor(
298 node, constructorName, kind, {});
275 } else { 299 } else {
276 lookedupConstructor.computeType(visitor.resolution); 300 lookedupConstructor.computeType(visitor.resolution);
277 if (!call.signatureApplies(lookedupConstructor.functionSignature)) { 301 if (!callStructure.signatureApplies(
302 lookedupConstructor.functionSignature)) {
278 MessageKind kind = isImplicitSuperCall 303 MessageKind kind = isImplicitSuperCall
279 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT 304 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
280 : MessageKind.NO_MATCHING_CONSTRUCTOR; 305 : MessageKind.NO_MATCHING_CONSTRUCTOR;
281 reporter.reportErrorMessage(diagnosticNode, kind); 306 result = reportAndCreateErroneousConstructor(
282 isValidAsConstant = false; 307 node, constructorName, kind, {});
283 } else if (constructor.isConst 308 } else if (constructor.isConst && !lookedupConstructor.isConst) {
284 && !lookedupConstructor.isConst) {
285 MessageKind kind = isImplicitSuperCall 309 MessageKind kind = isImplicitSuperCall
286 ? MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT 310 ? MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT
287 : MessageKind.CONST_CALLS_NON_CONST; 311 : MessageKind.CONST_CALLS_NON_CONST;
288 reporter.reportErrorMessage(diagnosticNode, kind); 312 result = reportAndCreateErroneousConstructor(
289 isValidAsConstant = false; 313 node, constructorName, kind, {});
290 } 314 }
291 } 315 }
316 return result;
292 } 317 }
293 318
294 /** 319 /**
295 * Resolve all initializers of this constructor. In the case of a redirecting 320 * Resolve all initializers of this constructor. In the case of a redirecting
296 * constructor, the resolved constructor's function element is returned. 321 * constructor, the resolved constructor's function element is returned.
297 */ 322 */
298 ConstructorElement resolveInitializers() { 323 ConstructorElement resolveInitializers() {
299 Map<dynamic/*String|int*/, ConstantExpression> defaultValues = 324 Map<dynamic/*String|int*/, ConstantExpression> defaultValues =
300 <dynamic/*String|int*/, ConstantExpression>{}; 325 <dynamic/*String|int*/, ConstantExpression>{};
301 ConstructedConstantExpression constructorInvocation; 326 ConstructedConstantExpression constructorInvocation;
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 508
484 ConstructorResult resolveConstructor( 509 ConstructorResult resolveConstructor(
485 InterfaceType type, 510 InterfaceType type,
486 Node diagnosticNode, 511 Node diagnosticNode,
487 String constructorName) { 512 String constructorName) {
488 ClassElement cls = type.element; 513 ClassElement cls = type.element;
489 cls.ensureResolved(resolution); 514 cls.ensureResolved(resolution);
490 ConstructorElement constructor = findConstructor( 515 ConstructorElement constructor = findConstructor(
491 resolver.enclosingElement.library, cls, constructorName); 516 resolver.enclosingElement.library, cls, constructorName);
492 if (constructor == null) { 517 if (constructor == null) {
493 String fullConstructorName = 518 MessageKind kind = constructorName.isEmpty
494 Elements.constructorNameForDiagnostics(cls.name, constructorName); 519 ? MessageKind.CANNOT_FIND_UNNAMED_CONSTRUCTOR
520 : MessageKind.CANNOT_FIND_CONSTRUCTOR;
495 return reportAndCreateErroneousConstructorElement( 521 return reportAndCreateErroneousConstructorElement(
496 diagnosticNode, 522 diagnosticNode,
497 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type, 523 ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type,
498 cls, constructorName, 524 cls, constructorName, kind,
499 MessageKind.CANNOT_FIND_CONSTRUCTOR, 525 {'className': cls.name, 'constructorName': constructorName},
500 {'constructorName': fullConstructorName},
501 missingConstructor: true); 526 missingConstructor: true);
502 } else if (inConstContext && !constructor.isConst) { 527 } else if (inConstContext && !constructor.isConst) {
503 reporter.reportErrorMessage( 528 reporter.reportErrorMessage(
504 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST); 529 diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
505 return new ConstructorResult( 530 return new ConstructorResult(
506 ConstructorResultKind.NON_CONSTANT, constructor, type); 531 ConstructorResultKind.NON_CONSTANT, constructor, type);
507 } else { 532 } else {
508 if (constructor.isGenerativeConstructor) { 533 if (constructor.isGenerativeConstructor) {
509 if (cls.isAbstract) { 534 if (cls.isAbstract) {
510 reporter.reportWarningMessage( 535 reporter.reportWarningMessage(
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 // constructors. 786 // constructors.
762 return null; 787 return null;
763 } 788 }
764 // TODO(johnniwinther): Use [Name] for lookup. 789 // TODO(johnniwinther): Use [Name] for lookup.
765 ConstructorElement constructor = cls.lookupConstructor(constructorName); 790 ConstructorElement constructor = cls.lookupConstructor(constructorName);
766 if (constructor != null) { 791 if (constructor != null) {
767 constructor = constructor.declaration; 792 constructor = constructor.declaration;
768 } 793 }
769 return constructor; 794 return constructor;
770 } 795 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/resolution/class_hierarchy.dart ('k') | pkg/compiler/lib/src/resolution/members.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698