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

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

Issue 1218793002: Compute constant constructors in resolution. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Cleanup Created 5 years, 5 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
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 part of resolution; 5 part of resolution;
6 6
7 class InitializerResolver { 7 class InitializerResolver {
8 final ResolverVisitor visitor; 8 final ResolverVisitor visitor;
9 final Map<Element, Node> initialized; 9 final ConstructorElementX constructor;
10 final FunctionExpression functionNode;
11 final Map<FieldElement, Node> initialized = <FieldElement, Node>{};
12 final Map<FieldElement, ConstantExpression> fieldInitializers =
13 <FieldElement, ConstantExpression>{};
10 Link<Node> initializers; 14 Link<Node> initializers;
11 bool hasSuper; 15 bool hasSuper = false;
16 bool isValidAsConstant = true;
12 17
13 InitializerResolver(this.visitor) 18 bool get isConst => constructor.isConst;
14 : initialized = new Map<Element, Node>(), hasSuper = false; 19
20 InitializerResolver(this.visitor, this.constructor, this.functionNode);
15 21
16 ResolutionRegistry get registry => visitor.registry; 22 ResolutionRegistry get registry => visitor.registry;
17 23
18 error(Node node, MessageKind kind, [arguments = const {}]) { 24 error(Node node, MessageKind kind, [arguments = const {}]) {
19 visitor.error(node, kind, arguments); 25 visitor.error(node, kind, arguments);
20 } 26 }
21 27
22 warning(Node node, MessageKind kind, [arguments = const {}]) { 28 warning(Node node, MessageKind kind, [arguments = const {}]) {
23 visitor.warning(node, kind, arguments); 29 visitor.warning(node, kind, arguments);
24 } 30 }
25 31
26 bool isFieldInitializer(SendSet node) { 32 bool isFieldInitializer(SendSet node) {
27 if (node.selector.asIdentifier() == null) return false; 33 if (node.selector.asIdentifier() == null) return false;
28 if (node.receiver == null) return true; 34 if (node.receiver == null) return true;
29 if (node.receiver.asIdentifier() == null) return false; 35 if (node.receiver.asIdentifier() == null) return false;
30 return node.receiver.asIdentifier().isThis(); 36 return node.receiver.asIdentifier().isThis();
31 } 37 }
32 38
33 reportDuplicateInitializerError(Element field, Node init, Node existing) { 39 reportDuplicateInitializerError(Element field, Node init, Node existing) {
34 visitor.compiler.reportError( 40 visitor.compiler.reportError(
35 init, 41 init,
36 MessageKind.DUPLICATE_INITIALIZER, {'fieldName': field.name}); 42 MessageKind.DUPLICATE_INITIALIZER, {'fieldName': field.name});
37 visitor.compiler.reportInfo( 43 visitor.compiler.reportInfo(
38 existing, 44 existing,
39 MessageKind.ALREADY_INITIALIZED, {'fieldName': field.name}); 45 MessageKind.ALREADY_INITIALIZED, {'fieldName': field.name});
46 isValidAsConstant = false;
40 } 47 }
41 48
42 void checkForDuplicateInitializers(FieldElementX field, Node init) { 49 void checkForDuplicateInitializers(FieldElementX field, Node init) {
43 // [field] can be null if it could not be resolved. 50 // [field] can be null if it could not be resolved.
44 if (field == null) return; 51 if (field == null) return;
45 if (initialized.containsKey(field)) { 52 if (initialized.containsKey(field)) {
46 reportDuplicateInitializerError(field, init, initialized[field]); 53 reportDuplicateInitializerError(field, init, initialized[field]);
47 } else if (field.isFinal) { 54 } else if (field.isFinal) {
48 field.parseNode(visitor.compiler); 55 field.parseNode(visitor.compiler);
49 Expression initializer = field.initializer; 56 Expression initializer = field.initializer;
50 if (initializer != null) { 57 if (initializer != null) {
51 reportDuplicateInitializerError(field, init, initializer); 58 reportDuplicateInitializerError(field, init, initializer);
52 } 59 }
53 } 60 }
54 initialized[field] = init; 61 initialized[field] = init;
55 } 62 }
56 63
57 void resolveFieldInitializer(FunctionElement constructor, SendSet init) { 64 void resolveFieldInitializer(SendSet init) {
58 // init is of the form [this.]field = value. 65 // init is of the form [this.]field = value.
59 final Node selector = init.selector; 66 final Node selector = init.selector;
60 final String name = selector.asIdentifier().source; 67 final String name = selector.asIdentifier().source;
61 // Lookup target field. 68 // Lookup target field.
62 Element target; 69 Element target;
70 FieldElement field;
63 if (isFieldInitializer(init)) { 71 if (isFieldInitializer(init)) {
64 target = constructor.enclosingClass.lookupLocalMember(name); 72 target = constructor.enclosingClass.lookupLocalMember(name);
65 if (target == null) { 73 if (target == null) {
66 error(selector, MessageKind.CANNOT_RESOLVE, {'name': name}); 74 error(selector, MessageKind.CANNOT_RESOLVE, {'name': name});
67 target = new ErroneousFieldElementX( 75 target = new ErroneousFieldElementX(
68 selector.asIdentifier(), constructor.enclosingClass); 76 selector.asIdentifier(), constructor.enclosingClass);
69 } else if (target.kind != ElementKind.FIELD) { 77 } else if (target.kind != ElementKind.FIELD) {
70 error(selector, MessageKind.NOT_A_FIELD, {'fieldName': name}); 78 error(selector, MessageKind.NOT_A_FIELD, {'fieldName': name});
71 target = new ErroneousFieldElementX( 79 target = new ErroneousFieldElementX(
72 selector.asIdentifier(), constructor.enclosingClass); 80 selector.asIdentifier(), constructor.enclosingClass);
73 } else if (!target.isInstanceMember) { 81 } else if (!target.isInstanceMember) {
74 error(selector, MessageKind.INIT_STATIC_FIELD, {'fieldName': name}); 82 error(selector, MessageKind.INIT_STATIC_FIELD, {'fieldName': name});
83 } else {
84 field = target;
75 } 85 }
76 } else { 86 } else {
77 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER); 87 error(init, MessageKind.INVALID_RECEIVER_IN_INITIALIZER);
78 } 88 }
79 registry.useElement(init, target); 89 registry.useElement(init, target);
80 registry.registerStaticUse(target); 90 registry.registerStaticUse(target);
81 checkForDuplicateInitializers(target, init); 91 checkForDuplicateInitializers(target, init);
82 // Resolve initializing value. 92 // Resolve initializing value.
83 visitor.visitInStaticContext(init.arguments.head); 93 ResolutionResult result = visitor.visitInStaticContext(
94 init.arguments.head,
95 inConstantInitializer: isConst);
96 if (isConst) {
97 if (result.isConstant && field != null) {
98 // TODO(johnniwinther): Report error if `result.constant` is `null`.
99 fieldInitializers[field] = result.constant;
100 } else {
101 isValidAsConstant = false;
102 }
103 }
84 } 104 }
85 105
86 ClassElement getSuperOrThisLookupTarget(FunctionElement constructor, 106 InterfaceType getSuperOrThisLookupTarget(Node diagnosticNode,
87 bool isSuperCall, 107 {bool isSuperCall}) {
88 Node diagnosticNode) {
89 ClassElement lookupTarget = constructor.enclosingClass;
90 if (isSuperCall) { 108 if (isSuperCall) {
91 // Calculate correct lookup target and constructor name. 109 // Calculate correct lookup target and constructor name.
92 if (identical(lookupTarget, visitor.compiler.objectClass)) { 110 if (identical(constructor.enclosingClass, visitor.compiler.objectClass)) {
93 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT); 111 error(diagnosticNode, MessageKind.SUPER_INITIALIZER_IN_OBJECT);
112 isValidAsConstant = false;
94 } else { 113 } else {
95 return lookupTarget.supertype.element; 114 return constructor.enclosingClass.supertype;
96 } 115 }
97 } 116 }
98 return lookupTarget; 117 return constructor.enclosingClass.thisType;
99 } 118 }
100 119
101 Element resolveSuperOrThisForSend(FunctionElement constructor, 120 ResolutionResult resolveSuperOrThisForSend(Send call) {
102 FunctionExpression functionNode,
103 Send call) {
104 // Resolve the selector and the arguments. 121 // Resolve the selector and the arguments.
105 visitor.inStaticContext(() { 122 ArgumentsResult argumentsResult = visitor.inStaticContext(() {
106 visitor.resolveSelector(call, null); 123 visitor.resolveSelector(call, null);
107 visitor.resolveArguments(call.argumentsNode); 124 return visitor.resolveArguments(call.argumentsNode);
108 }); 125 }, inConstantInitializer: isConst);
109 Selector selector = registry.getSelector(call); 126
110 bool isSuperCall = Initializers.isSuperConstructorCall(call); 127 bool isSuperCall = Initializers.isSuperConstructorCall(call);
111 128 InterfaceType targetType =
112 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, 129 getSuperOrThisLookupTarget(call, isSuperCall: isSuperCall);
113 isSuperCall, 130 ClassElement lookupTarget = targetType.element;
114 call);
115 Selector constructorSelector = 131 Selector constructorSelector =
116 visitor.getRedirectingThisOrSuperConstructorSelector(call); 132 visitor.getRedirectingThisOrSuperConstructorSelector(call);
117 FunctionElement calledConstructor = 133 FunctionElement calledConstructor =
118 lookupTarget.lookupConstructor(constructorSelector.name); 134 lookupTarget.lookupConstructor(constructorSelector.name);
119 135
120 final bool isImplicitSuperCall = false; 136 final bool isImplicitSuperCall = false;
121 final String className = lookupTarget.name; 137 final String className = lookupTarget.name;
122 verifyThatConstructorMatchesCall(constructor, 138 verifyThatConstructorMatchesCall(calledConstructor,
123 calledConstructor, 139 argumentsResult.callStructure,
124 selector.callStructure,
125 isImplicitSuperCall, 140 isImplicitSuperCall,
126 call, 141 call,
127 className, 142 className,
128 constructorSelector); 143 constructorSelector);
129 144
130 registry.useElement(call, calledConstructor); 145 registry.useElement(call, calledConstructor);
131 registry.registerStaticUse(calledConstructor); 146 registry.registerStaticUse(calledConstructor);
132 return calledConstructor; 147 if (isConst) {
148 if (isValidAsConstant &&
149 calledConstructor.isConst &&
150 argumentsResult.isValidAsConstant) {
151 CallStructure callStructure = argumentsResult.callStructure;
152 List<ConstantExpression> arguments = argumentsResult.constantArguments;
153 return new ConstantResult(
154 call,
155 new ConstructedConstantExpression(
156 targetType,
157 calledConstructor,
158 callStructure,
159 arguments),
160 element: calledConstructor);
161 } else {
162 isValidAsConstant = false;
163 }
164 }
165 return new ResolutionResult.forElement(calledConstructor);
133 } 166 }
134 167
135 void resolveImplicitSuperConstructorSend(FunctionElement constructor, 168 ConstructedConstantExpression resolveImplicitSuperConstructorSend() {
136 FunctionExpression functionNode) {
137 // If the class has a super resolve the implicit super call. 169 // If the class has a super resolve the implicit super call.
138 ClassElement classElement = constructor.enclosingClass; 170 ClassElement classElement = constructor.enclosingClass;
139 ClassElement superClass = classElement.superclass; 171 ClassElement superClass = classElement.superclass;
140 if (classElement != visitor.compiler.objectClass) { 172 if (classElement != visitor.compiler.objectClass) {
141 assert(superClass != null); 173 assert(superClass != null);
142 assert(superClass.isResolved); 174 assert(superClass.isResolved);
143 175
144 final bool isSuperCall = true; 176 InterfaceType targetType =
145 ClassElement lookupTarget = getSuperOrThisLookupTarget(constructor, 177 getSuperOrThisLookupTarget(functionNode, isSuperCall: true);
146 isSuperCall, 178 ClassElement lookupTarget = targetType.element;
147 functionNode);
148 Selector constructorSelector = new Selector.callDefaultConstructor(); 179 Selector constructorSelector = new Selector.callDefaultConstructor();
149 Element calledConstructor = lookupTarget.lookupConstructor( 180 Element calledConstructor = lookupTarget.lookupConstructor(
150 constructorSelector.name); 181 constructorSelector.name);
151 182
152 final String className = lookupTarget.name; 183 final String className = lookupTarget.name;
153 final bool isImplicitSuperCall = true; 184 final bool isImplicitSuperCall = true;
154 verifyThatConstructorMatchesCall(constructor, 185 verifyThatConstructorMatchesCall(calledConstructor,
155 calledConstructor,
156 CallStructure.NO_ARGS, 186 CallStructure.NO_ARGS,
157 isImplicitSuperCall, 187 isImplicitSuperCall,
158 functionNode, 188 functionNode,
159 className, 189 className,
160 constructorSelector); 190 constructorSelector);
161 registry.registerImplicitSuperCall(calledConstructor); 191 registry.registerImplicitSuperCall(calledConstructor);
162 registry.registerStaticUse(calledConstructor); 192 registry.registerStaticUse(calledConstructor);
193
194 if (isConst && isValidAsConstant) {
195 return new ConstructedConstantExpression(
196 targetType,
197 calledConstructor,
198 CallStructure.NO_ARGS,
199 const <ConstantExpression>[]);
200 }
163 } 201 }
202 return null;
164 } 203 }
165 204
166 void verifyThatConstructorMatchesCall( 205 void verifyThatConstructorMatchesCall(
167 FunctionElement caller,
168 ConstructorElementX lookedupConstructor, 206 ConstructorElementX lookedupConstructor,
169 CallStructure call, 207 CallStructure call,
170 bool isImplicitSuperCall, 208 bool isImplicitSuperCall,
171 Node diagnosticNode, 209 Node diagnosticNode,
172 String className, 210 String className,
173 Selector constructorSelector) { 211 Selector constructorSelector) {
174 if (lookedupConstructor == null || 212 if (lookedupConstructor == null ||
175 !lookedupConstructor.isGenerativeConstructor) { 213 !lookedupConstructor.isGenerativeConstructor) {
176 String fullConstructorName = Elements.constructorNameForDiagnostics( 214 String fullConstructorName = Elements.constructorNameForDiagnostics(
177 className, 215 className,
178 constructorSelector.name); 216 constructorSelector.name);
179 MessageKind kind = isImplicitSuperCall 217 MessageKind kind = isImplicitSuperCall
180 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT 218 ? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
181 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR; 219 : MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
182 visitor.compiler.reportError( 220 visitor.compiler.reportError(
183 diagnosticNode, kind, {'constructorName': fullConstructorName}); 221 diagnosticNode, kind, {'constructorName': fullConstructorName});
222 isValidAsConstant = false;
184 } else { 223 } else {
185 lookedupConstructor.computeSignature(visitor.compiler); 224 lookedupConstructor.computeSignature(visitor.compiler);
186 if (!call.signatureApplies(lookedupConstructor.functionSignature)) { 225 if (!call.signatureApplies(lookedupConstructor.functionSignature)) {
187 MessageKind kind = isImplicitSuperCall 226 MessageKind kind = isImplicitSuperCall
188 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT 227 ? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
189 : MessageKind.NO_MATCHING_CONSTRUCTOR; 228 : MessageKind.NO_MATCHING_CONSTRUCTOR;
190 visitor.compiler.reportError(diagnosticNode, kind); 229 visitor.compiler.reportError(diagnosticNode, kind);
191 } else if (caller.isConst 230 isValidAsConstant = false;
231 } else if (constructor.isConst
192 && !lookedupConstructor.isConst) { 232 && !lookedupConstructor.isConst) {
193 MessageKind kind = isImplicitSuperCall 233 MessageKind kind = isImplicitSuperCall
194 ? MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT 234 ? MessageKind.CONST_CALLS_NON_CONST_FOR_IMPLICIT
195 : MessageKind.CONST_CALLS_NON_CONST; 235 : MessageKind.CONST_CALLS_NON_CONST;
196 visitor.compiler.reportError(diagnosticNode, kind); 236 visitor.compiler.reportError(diagnosticNode, kind);
237 isValidAsConstant = false;
197 } 238 }
198 } 239 }
199 } 240 }
200 241
201 /** 242 /**
202 * Resolve all initializers of this constructor. In the case of a redirecting 243 * Resolve all initializers of this constructor. In the case of a redirecting
203 * constructor, the resolved constructor's function element is returned. 244 * constructor, the resolved constructor's function element is returned.
204 */ 245 */
205 ConstructorElement resolveInitializers(ConstructorElementX constructor, 246 ConstructorElement resolveInitializers() {
206 FunctionExpression functionNode) { 247 Map<dynamic/*String|int*/, ConstantExpression> defaultValues =
248 <dynamic/*String|int*/, ConstantExpression>{};
249 ConstructedConstantExpression constructorInvocation;
207 // Keep track of all "this.param" parameters specified for constructor so 250 // Keep track of all "this.param" parameters specified for constructor so
208 // that we can ensure that fields are initialized only once. 251 // that we can ensure that fields are initialized only once.
209 FunctionSignature functionParameters = constructor.functionSignature; 252 FunctionSignature functionParameters = constructor.functionSignature;
210 functionParameters.forEachParameter((ParameterElement element) { 253 functionParameters.forEachParameter((ParameterElementX element) {
254 if (isConst) {
255 if (element.isOptional) {
256 if (element.constantCache == null) {
257 // TODO(johnniwinther): Remove this when all constant expressions
258 // can be computed during resolution.
259 isValidAsConstant = false;
260 } else {
261 ConstantExpression defaultValue = element.constant;
262 if (defaultValue != null) {
263 if (element.isNamed) {
264 defaultValues[element.name] = defaultValue;
265 } else {
266 int index =
267 element.functionDeclaration.parameters.indexOf(element);
268 defaultValues[index] = defaultValue;
269 }
270 } else {
271 isValidAsConstant = false;
272 }
273 }
274 }
275 }
211 if (element.isInitializingFormal) { 276 if (element.isInitializingFormal) {
212 InitializingFormalElement initializingFormal = element; 277 InitializingFormalElementX initializingFormal = element;
213 checkForDuplicateInitializers(initializingFormal.fieldElement, 278 FieldElement field = initializingFormal.fieldElement;
214 element.initializer); 279 checkForDuplicateInitializers(field, element.initializer);
280 if (isConst) {
281 if (element.isNamed) {
282 fieldInitializers[field] = new NamedArgumentReference(element.name);
283 } else {
284 int index = element.functionDeclaration.parameters.indexOf(element);
285 fieldInitializers[field] = new PositionalArgumentReference(index);
286 }
287 } else {
288 isValidAsConstant = false;
289 }
215 } 290 }
216 }); 291 });
217 292
218 if (functionNode.initializers == null) { 293 if (functionNode.initializers == null) {
219 initializers = const Link<Node>(); 294 initializers = const Link<Node>();
220 } else { 295 } else {
221 initializers = functionNode.initializers.nodes; 296 initializers = functionNode.initializers.nodes;
222 } 297 }
223 bool resolvedSuper = false; 298 bool resolvedSuper = false;
224 for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) { 299 for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) {
225 if (link.head.asSendSet() != null) { 300 if (link.head.asSendSet() != null) {
226 final SendSet init = link.head.asSendSet(); 301 final SendSet init = link.head.asSendSet();
227 resolveFieldInitializer(constructor, init); 302 resolveFieldInitializer(init);
228 } else if (link.head.asSend() != null) { 303 } else if (link.head.asSend() != null) {
229 final Send call = link.head.asSend(); 304 final Send call = link.head.asSend();
230 if (call.argumentsNode == null) { 305 if (call.argumentsNode == null) {
231 error(link.head, MessageKind.INVALID_INITIALIZER); 306 error(link.head, MessageKind.INVALID_INITIALIZER);
232 continue; 307 continue;
233 } 308 }
234 if (Initializers.isSuperConstructorCall(call)) { 309 if (Initializers.isSuperConstructorCall(call)) {
235 if (resolvedSuper) { 310 if (resolvedSuper) {
236 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER); 311 error(call, MessageKind.DUPLICATE_SUPER_INITIALIZER);
237 } 312 }
238 resolveSuperOrThisForSend(constructor, functionNode, call); 313 ResolutionResult result = resolveSuperOrThisForSend(call);
314 if (isConst) {
315 if (result.isConstant) {
316 constructorInvocation = result.constant;
317 } else {
318 isValidAsConstant = false;
319 }
320 }
239 resolvedSuper = true; 321 resolvedSuper = true;
240 } else if (Initializers.isConstructorRedirect(call)) { 322 } else if (Initializers.isConstructorRedirect(call)) {
241 // Check that there is no body (Language specification 7.5.1). If the 323 // Check that there is no body (Language specification 7.5.1). If the
242 // constructor is also const, we already reported an error in 324 // constructor is also const, we already reported an error in
243 // [resolveMethodElement]. 325 // [resolveMethodElement].
244 if (functionNode.hasBody() && !constructor.isConst) { 326 if (functionNode.hasBody() && !constructor.isConst) {
245 error(functionNode, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY); 327 error(functionNode, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_BODY);
246 } 328 }
247 // Check that there are no other initializers. 329 // Check that there are no other initializers.
248 if (!initializers.tail.isEmpty) { 330 if (!initializers.tail.isEmpty) {
249 error(call, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER); 331 error(call, MessageKind.REDIRECTING_CONSTRUCTOR_HAS_INITIALIZER);
250 } else { 332 } else {
251 constructor.isRedirectingGenerative = true; 333 constructor.isRedirectingGenerative = true;
252 } 334 }
253 // Check that there are no field initializing parameters. 335 // Check that there are no field initializing parameters.
254 FunctionSignature signature = constructor.functionSignature; 336 FunctionSignature signature = constructor.functionSignature;
255 signature.forEachParameter((ParameterElement parameter) { 337 signature.forEachParameter((ParameterElement parameter) {
256 if (parameter.isInitializingFormal) { 338 if (parameter.isInitializingFormal) {
257 Node node = parameter.node; 339 Node node = parameter.node;
258 error(node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED); 340 error(node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED);
341 isValidAsConstant = false;
259 } 342 }
260 }); 343 });
261 return resolveSuperOrThisForSend(constructor, functionNode, call); 344 ResolutionResult result = resolveSuperOrThisForSend(call);
345 if (isConst) {
346 if (result.isConstant) {
347 constructorInvocation = result.constant;
348 } else {
349 isValidAsConstant = false;
350 }
351 if (isConst && isValidAsConstant) {
352 constructor.constantConstructor =
353 new RedirectingGenerativeConstantConstructor(
354 defaultValues,
355 constructorInvocation);
356 }
357 }
358 return result.element;
262 } else { 359 } else {
263 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED); 360 visitor.error(call, MessageKind.CONSTRUCTOR_CALL_EXPECTED);
264 return null; 361 return null;
265 } 362 }
266 } else { 363 } else {
267 error(link.head, MessageKind.INVALID_INITIALIZER); 364 error(link.head, MessageKind.INVALID_INITIALIZER);
268 } 365 }
269 } 366 }
270 if (!resolvedSuper) { 367 if (!resolvedSuper) {
271 resolveImplicitSuperConstructorSend(constructor, functionNode); 368 constructorInvocation = resolveImplicitSuperConstructorSend();
369 }
370 if (isConst && isValidAsConstant) {
371 constructor.constantConstructor = new GenerativeConstantConstructor(
372 constructor.enclosingClass.thisType,
373 defaultValues,
374 fieldInitializers,
375 constructorInvocation);
272 } 376 }
273 return null; // If there was no redirection always return null. 377 return null; // If there was no redirection always return null.
274 } 378 }
275 } 379 }
276 380
277 class ConstructorResolver extends CommonResolverVisitor<Element> { 381 class ConstructorResolver extends CommonResolverVisitor<Element> {
278 final ResolverVisitor resolver; 382 final ResolverVisitor resolver;
279 bool inConstContext; 383 bool inConstContext;
280 DartType type; 384 DartType type;
281 385
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 return element; 572 return element;
469 } 573 }
470 574
471 /// Assumed to be called by [resolveRedirectingFactory]. 575 /// Assumed to be called by [resolveRedirectingFactory].
472 Element visitRedirectingFactoryBody(RedirectingFactoryBody node) { 576 Element visitRedirectingFactoryBody(RedirectingFactoryBody node) {
473 Node constructorReference = node.constructorReference; 577 Node constructorReference = node.constructorReference;
474 return finishConstructorReference(visit(constructorReference), 578 return finishConstructorReference(visit(constructorReference),
475 constructorReference, node); 579 constructorReference, node);
476 } 580 }
477 } 581 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698