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.resolution.signatures; | 5 library dart2js.resolution.signatures; |
6 | 6 |
7 import '../compiler.dart' show | 7 import '../compiler.dart' show |
8 Compiler; | 8 Compiler; |
9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../diagnostics/diagnostic_listener.dart' show |
| 11 DiagnosticReporter; |
10 import '../diagnostics/invariant.dart' show | 12 import '../diagnostics/invariant.dart' show |
11 invariant; | 13 invariant; |
12 import '../diagnostics/messages.dart' show | 14 import '../diagnostics/messages.dart' show |
13 MessageKind; | 15 MessageKind; |
14 import '../elements/elements.dart'; | 16 import '../elements/elements.dart'; |
15 import '../elements/modelx.dart' show | 17 import '../elements/modelx.dart' show |
16 ErroneousFieldElementX, | 18 ErroneousFieldElementX, |
17 ErroneousInitializingFormalElementX, | 19 ErroneousInitializingFormalElementX, |
18 FormalElementX, | 20 FormalElementX, |
19 FunctionElementX, | 21 FunctionElementX, |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 this.resolver = | 61 this.resolver = |
60 new ResolverVisitor(compiler, enclosingElement, registry), | 62 new ResolverVisitor(compiler, enclosingElement, registry), |
61 super(compiler, registry); | 63 super(compiler, registry); |
62 | 64 |
63 bool get defaultValuesAllowed => defaultValuesError == null; | 65 bool get defaultValuesAllowed => defaultValuesError == null; |
64 | 66 |
65 visitNodeList(NodeList node) { | 67 visitNodeList(NodeList node) { |
66 // This must be a list of optional arguments. | 68 // This must be a list of optional arguments. |
67 String value = node.beginToken.stringValue; | 69 String value = node.beginToken.stringValue; |
68 if ((!identical(value, '[')) && (!identical(value, '{'))) { | 70 if ((!identical(value, '[')) && (!identical(value, '{'))) { |
69 compiler.internalError(node, "expected optional parameters"); | 71 reporter.internalError(node, "expected optional parameters"); |
70 } | 72 } |
71 optionalParametersAreNamed = (identical(value, '{')); | 73 optionalParametersAreNamed = (identical(value, '{')); |
72 isOptionalParameter = true; | 74 isOptionalParameter = true; |
73 LinkBuilder<Element> elements = analyzeNodes(node.nodes); | 75 LinkBuilder<Element> elements = analyzeNodes(node.nodes); |
74 optionalParameterCount = elements.length; | 76 optionalParameterCount = elements.length; |
75 optionalParameters = elements.toList(); | 77 optionalParameters = elements.toList(); |
76 } | 78 } |
77 | 79 |
78 FormalElementX visitVariableDefinitions(VariableDefinitions node) { | 80 FormalElementX visitVariableDefinitions(VariableDefinitions node) { |
79 Link<Node> definitions = node.definitions.nodes; | 81 Link<Node> definitions = node.definitions.nodes; |
80 if (definitions.isEmpty) { | 82 if (definitions.isEmpty) { |
81 compiler.internalError(node, 'no parameter definition'); | 83 reporter.internalError(node, 'no parameter definition'); |
82 return null; | 84 return null; |
83 } | 85 } |
84 if (!definitions.tail.isEmpty) { | 86 if (!definitions.tail.isEmpty) { |
85 compiler.internalError(definitions.tail.head, 'extra definition'); | 87 reporter.internalError(definitions.tail.head, 'extra definition'); |
86 return null; | 88 return null; |
87 } | 89 } |
88 Node definition = definitions.head; | 90 Node definition = definitions.head; |
89 if (definition is NodeList) { | 91 if (definition is NodeList) { |
90 compiler.internalError(node, 'optional parameters are not implemented'); | 92 reporter.internalError(node, 'optional parameters are not implemented'); |
91 } | 93 } |
92 if (node.modifiers.isConst) { | 94 if (node.modifiers.isConst) { |
93 compiler.reportErrorMessage(node, MessageKind.FORMAL_DECLARED_CONST); | 95 reporter.reportErrorMessage(node, MessageKind.FORMAL_DECLARED_CONST); |
94 } | 96 } |
95 if (node.modifiers.isStatic) { | 97 if (node.modifiers.isStatic) { |
96 compiler.reportErrorMessage(node, MessageKind.FORMAL_DECLARED_STATIC); | 98 reporter.reportErrorMessage(node, MessageKind.FORMAL_DECLARED_STATIC); |
97 } | 99 } |
98 | 100 |
99 if (currentDefinitions != null) { | 101 if (currentDefinitions != null) { |
100 compiler.internalError(node, 'function type parameters not supported'); | 102 reporter.internalError(node, 'function type parameters not supported'); |
101 } | 103 } |
102 currentDefinitions = node; | 104 currentDefinitions = node; |
103 FormalElementX element = definition.accept(this); | 105 FormalElementX element = definition.accept(this); |
104 if (currentDefinitions.metadata != null) { | 106 if (currentDefinitions.metadata != null) { |
105 element.metadataInternal = | 107 element.metadataInternal = |
106 compiler.resolver.resolveMetadata(element, node); | 108 compiler.resolver.resolveMetadata(element, node); |
107 } | 109 } |
108 currentDefinitions = null; | 110 currentDefinitions = null; |
109 return element; | 111 return element; |
110 } | 112 } |
111 | 113 |
112 void validateName(Identifier node) { | 114 void validateName(Identifier node) { |
113 if (isOptionalParameter && | 115 if (isOptionalParameter && |
114 optionalParametersAreNamed && | 116 optionalParametersAreNamed && |
115 Name.isPrivateName(node.source)) { | 117 Name.isPrivateName(node.source)) { |
116 compiler.reportErrorMessage(node, MessageKind.PRIVATE_NAMED_PARAMETER); | 118 reporter.reportErrorMessage(node, MessageKind.PRIVATE_NAMED_PARAMETER); |
117 } | 119 } |
118 } | 120 } |
119 | 121 |
120 void computeParameterType(FormalElementX element, | 122 void computeParameterType(FormalElementX element, |
121 [VariableElement fieldElement]) { | 123 [VariableElement fieldElement]) { |
122 void computeFunctionType(FunctionExpression functionExpression) { | 124 void computeFunctionType(FunctionExpression functionExpression) { |
123 FunctionSignature functionSignature = SignatureResolver.analyze( | 125 FunctionSignature functionSignature = SignatureResolver.analyze( |
124 compiler, functionExpression.parameters, | 126 compiler, functionExpression.parameters, |
125 functionExpression.returnType, element, registry, | 127 functionExpression.returnType, element, registry, |
126 defaultValuesError: MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT); | 128 defaultValuesError: MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 if (identifier != null) { | 167 if (identifier != null) { |
166 // Normal parameter: [:Type name:]. | 168 // Normal parameter: [:Type name:]. |
167 return identifier; | 169 return identifier; |
168 } else { | 170 } else { |
169 // Function type parameter: [:void name(DartType arg):]. | 171 // Function type parameter: [:void name(DartType arg):]. |
170 var functionExpression = node.selector.asFunctionExpression(); | 172 var functionExpression = node.selector.asFunctionExpression(); |
171 if (functionExpression != null && | 173 if (functionExpression != null && |
172 functionExpression.name.asIdentifier() != null) { | 174 functionExpression.name.asIdentifier() != null) { |
173 return functionExpression.name.asIdentifier(); | 175 return functionExpression.name.asIdentifier(); |
174 } else { | 176 } else { |
175 compiler.internalError(node, | 177 reporter.internalError(node, |
176 'internal error: unimplemented receiver on parameter send'); | 178 'internal error: unimplemented receiver on parameter send'); |
177 return null; | 179 return null; |
178 } | 180 } |
179 } | 181 } |
180 } | 182 } |
181 | 183 |
182 // The only valid [Send] can be in constructors and must be of the form | 184 // The only valid [Send] can be in constructors and must be of the form |
183 // [:this.x:] (where [:x:] represents an instance field). | 185 // [:this.x:] (where [:x:] represents an instance field). |
184 InitializingFormalElementX visitSend(Send node) { | 186 InitializingFormalElementX visitSend(Send node) { |
185 return createFieldParameter(node, null); | 187 return createFieldParameter(node, null); |
(...skipping 12 matching lines...) Expand all Loading... |
198 } | 200 } |
199 computeParameterType(parameter); | 201 computeParameterType(parameter); |
200 return parameter; | 202 return parameter; |
201 } | 203 } |
202 | 204 |
203 InitializingFormalElementX createFieldParameter(Send node, | 205 InitializingFormalElementX createFieldParameter(Send node, |
204 Expression initializer) { | 206 Expression initializer) { |
205 InitializingFormalElementX element; | 207 InitializingFormalElementX element; |
206 Identifier receiver = node.receiver.asIdentifier(); | 208 Identifier receiver = node.receiver.asIdentifier(); |
207 if (receiver == null || !receiver.isThis()) { | 209 if (receiver == null || !receiver.isThis()) { |
208 compiler.reportErrorMessage(node, MessageKind.INVALID_PARAMETER); | 210 reporter.reportErrorMessage(node, MessageKind.INVALID_PARAMETER); |
209 return new ErroneousInitializingFormalElementX( | 211 return new ErroneousInitializingFormalElementX( |
210 getParameterName(node), enclosingElement); | 212 getParameterName(node), enclosingElement); |
211 } else { | 213 } else { |
212 if (!enclosingElement.isGenerativeConstructor) { | 214 if (!enclosingElement.isGenerativeConstructor) { |
213 compiler.reportErrorMessage( | 215 reporter.reportErrorMessage( |
214 node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED); | 216 node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED); |
215 return new ErroneousInitializingFormalElementX( | 217 return new ErroneousInitializingFormalElementX( |
216 getParameterName(node), enclosingElement); | 218 getParameterName(node), enclosingElement); |
217 } | 219 } |
218 Identifier name = getParameterName(node); | 220 Identifier name = getParameterName(node); |
219 validateName(name); | 221 validateName(name); |
220 Element fieldElement = | 222 Element fieldElement = |
221 enclosingElement.enclosingClass.lookupLocalMember(name.source); | 223 enclosingElement.enclosingClass.lookupLocalMember(name.source); |
222 if (fieldElement == null || | 224 if (fieldElement == null || |
223 !identical(fieldElement.kind, ElementKind.FIELD)) { | 225 !identical(fieldElement.kind, ElementKind.FIELD)) { |
224 compiler.reportErrorMessage( | 226 reporter.reportErrorMessage( |
225 node, MessageKind.NOT_A_FIELD, {'fieldName': name}); | 227 node, MessageKind.NOT_A_FIELD, {'fieldName': name}); |
226 fieldElement = new ErroneousFieldElementX( | 228 fieldElement = new ErroneousFieldElementX( |
227 name, enclosingElement.enclosingClass); | 229 name, enclosingElement.enclosingClass); |
228 } else if (!fieldElement.isInstanceMember) { | 230 } else if (!fieldElement.isInstanceMember) { |
229 compiler.reportErrorMessage( | 231 reporter.reportErrorMessage( |
230 node, MessageKind.NOT_INSTANCE_FIELD, {'fieldName': name}); | 232 node, MessageKind.NOT_INSTANCE_FIELD, {'fieldName': name}); |
231 fieldElement = new ErroneousFieldElementX( | 233 fieldElement = new ErroneousFieldElementX( |
232 name, enclosingElement.enclosingClass); | 234 name, enclosingElement.enclosingClass); |
233 } | 235 } |
234 element = new InitializingFormalElementX(enclosingElement, | 236 element = new InitializingFormalElementX(enclosingElement, |
235 currentDefinitions, name, initializer, fieldElement, | 237 currentDefinitions, name, initializer, fieldElement, |
236 isOptional: isOptionalParameter, isNamed: optionalParametersAreNamed); | 238 isOptional: isOptionalParameter, isNamed: optionalParametersAreNamed); |
237 computeParameterType(element, fieldElement); | 239 computeParameterType(element, fieldElement); |
238 } | 240 } |
239 return element; | 241 return element; |
240 } | 242 } |
241 | 243 |
242 /// A [SendSet] node is an optional parameter with a default value. | 244 /// A [SendSet] node is an optional parameter with a default value. |
243 Element visitSendSet(SendSet node) { | 245 Element visitSendSet(SendSet node) { |
244 FormalElementX element; | 246 FormalElementX element; |
245 if (node.receiver != null) { | 247 if (node.receiver != null) { |
246 element = createFieldParameter(node, node.arguments.first); | 248 element = createFieldParameter(node, node.arguments.first); |
247 } else if (node.selector.asIdentifier() != null || | 249 } else if (node.selector.asIdentifier() != null || |
248 node.selector.asFunctionExpression() != null) { | 250 node.selector.asFunctionExpression() != null) { |
249 element = createParameter(getParameterName(node), node.arguments.first); | 251 element = createParameter(getParameterName(node), node.arguments.first); |
250 } | 252 } |
251 Node defaultValue = node.arguments.head; | 253 Node defaultValue = node.arguments.head; |
252 if (!defaultValuesAllowed) { | 254 if (!defaultValuesAllowed) { |
253 compiler.reportErrorMessage(defaultValue, defaultValuesError); | 255 reporter.reportErrorMessage(defaultValue, defaultValuesError); |
254 } | 256 } |
255 return element; | 257 return element; |
256 } | 258 } |
257 | 259 |
258 Element visitFunctionExpression(FunctionExpression node) { | 260 Element visitFunctionExpression(FunctionExpression node) { |
259 // This is a function typed parameter. | 261 // This is a function typed parameter. |
260 Modifiers modifiers = currentDefinitions.modifiers; | 262 Modifiers modifiers = currentDefinitions.modifiers; |
261 if (modifiers.isFinal) { | 263 if (modifiers.isFinal) { |
262 compiler.reportErrorMessage( | 264 reporter.reportErrorMessage( |
263 modifiers, | 265 modifiers, |
264 MessageKind.FINAL_FUNCTION_TYPE_PARAMETER); | 266 MessageKind.FINAL_FUNCTION_TYPE_PARAMETER); |
265 } | 267 } |
266 if (modifiers.isVar) { | 268 if (modifiers.isVar) { |
267 compiler.reportErrorMessage( | 269 reporter.reportErrorMessage( |
268 modifiers, MessageKind.VAR_FUNCTION_TYPE_PARAMETER); | 270 modifiers, MessageKind.VAR_FUNCTION_TYPE_PARAMETER); |
269 } | 271 } |
270 | 272 |
271 return createParameter(node.name, null); | 273 return createParameter(node.name, null); |
272 } | 274 } |
273 | 275 |
274 LinkBuilder<Element> analyzeNodes(Link<Node> link) { | 276 LinkBuilder<Element> analyzeNodes(Link<Node> link) { |
275 LinkBuilder<Element> elements = new LinkBuilder<Element>(); | 277 LinkBuilder<Element> elements = new LinkBuilder<Element>(); |
276 for (; !link.isEmpty; link = link.tail) { | 278 for (; !link.isEmpty; link = link.tail) { |
277 Element element = link.head.accept(this); | 279 Element element = link.head.accept(this); |
278 if (element != null) { | 280 if (element != null) { |
279 elements.addLast(element); | 281 elements.addLast(element); |
280 } else { | 282 } else { |
281 // If parameter is null, the current node should be the last, | 283 // If parameter is null, the current node should be the last, |
282 // and a list of optional named parameters. | 284 // and a list of optional named parameters. |
283 if (!link.tail.isEmpty || (link.head is !NodeList)) { | 285 if (!link.tail.isEmpty || (link.head is !NodeList)) { |
284 compiler.internalError(link.head, "expected optional parameters"); | 286 reporter.internalError(link.head, "expected optional parameters"); |
285 } | 287 } |
286 } | 288 } |
287 } | 289 } |
288 return elements; | 290 return elements; |
289 } | 291 } |
290 | 292 |
291 /** | 293 /** |
292 * Resolves formal parameters and return type of a [FunctionExpression] | 294 * Resolves formal parameters and return type of a [FunctionExpression] |
293 * to a [FunctionSignature]. | 295 * to a [FunctionSignature]. |
294 * | 296 * |
295 * If [createRealParameters] is `true`, the parameters will be | 297 * If [createRealParameters] is `true`, the parameters will be |
296 * real parameters implementing the [ParameterElement] interface. Otherwise, | 298 * real parameters implementing the [ParameterElement] interface. Otherwise, |
297 * the parameters will only implement [FormalElement]. | 299 * the parameters will only implement [FormalElement]. |
298 */ | 300 */ |
299 static FunctionSignature analyze( | 301 static FunctionSignature analyze( |
300 Compiler compiler, | 302 Compiler compiler, |
301 NodeList formalParameters, | 303 NodeList formalParameters, |
302 Node returnNode, | 304 Node returnNode, |
303 FunctionTypedElement element, | 305 FunctionTypedElement element, |
304 ResolutionRegistry registry, | 306 ResolutionRegistry registry, |
305 {MessageKind defaultValuesError, | 307 {MessageKind defaultValuesError, |
306 bool createRealParameters: false, | 308 bool createRealParameters: false, |
307 bool isFunctionExpression: false}) { | 309 bool isFunctionExpression: false}) { |
| 310 DiagnosticReporter reporter = compiler.reporter; |
308 | 311 |
309 SignatureResolver visitor = new SignatureResolver(compiler, element, | 312 SignatureResolver visitor = new SignatureResolver(compiler, element, |
310 registry, defaultValuesError: defaultValuesError, | 313 registry, defaultValuesError: defaultValuesError, |
311 createRealParameters: createRealParameters); | 314 createRealParameters: createRealParameters); |
312 List<Element> parameters = const <Element>[]; | 315 List<Element> parameters = const <Element>[]; |
313 int requiredParameterCount = 0; | 316 int requiredParameterCount = 0; |
314 if (formalParameters == null) { | 317 if (formalParameters == null) { |
315 if (!element.isGetter) { | 318 if (!element.isGetter) { |
316 if (element.isErroneous) { | 319 if (element.isErroneous) { |
317 // If the element is erroneous, an error should already have been | 320 // If the element is erroneous, an error should already have been |
318 // reported. In the case of parse errors, it is possible that there | 321 // reported. In the case of parse errors, it is possible that there |
319 // are formal parameters, but something else in the method failed to | 322 // are formal parameters, but something else in the method failed to |
320 // parse. So we suppress the message about missing formals. | 323 // parse. So we suppress the message about missing formals. |
321 assert(invariant(element, compiler.compilationFailed)); | 324 assert(invariant(element, compiler.compilationFailed)); |
322 } else { | 325 } else { |
323 compiler.reportErrorMessage(element, MessageKind.MISSING_FORMALS); | 326 reporter.reportErrorMessage(element, MessageKind.MISSING_FORMALS); |
324 } | 327 } |
325 } | 328 } |
326 } else { | 329 } else { |
327 if (element.isGetter) { | 330 if (element.isGetter) { |
328 if (!identical(formalParameters.endToken.next.stringValue, | 331 if (!identical(formalParameters.endToken.next.stringValue, |
329 // TODO(ahe): Remove the check for native keyword. | 332 // TODO(ahe): Remove the check for native keyword. |
330 'native')) { | 333 'native')) { |
331 compiler.reportErrorMessage( | 334 reporter.reportErrorMessage( |
332 formalParameters, | 335 formalParameters, |
333 MessageKind.EXTRA_FORMALS); | 336 MessageKind.EXTRA_FORMALS); |
334 } | 337 } |
335 } | 338 } |
336 LinkBuilder<Element> parametersBuilder = | 339 LinkBuilder<Element> parametersBuilder = |
337 visitor.analyzeNodes(formalParameters.nodes); | 340 visitor.analyzeNodes(formalParameters.nodes); |
338 requiredParameterCount = parametersBuilder.length; | 341 requiredParameterCount = parametersBuilder.length; |
339 parameters = parametersBuilder.toList(); | 342 parameters = parametersBuilder.toList(); |
340 } | 343 } |
341 DartType returnType; | 344 DartType returnType; |
(...skipping 25 matching lines...) Expand all Loading... |
367 case AsyncMarker.ASYNC_STAR: | 370 case AsyncMarker.ASYNC_STAR: |
368 returnType = compiler.coreTypes.streamType(); | 371 returnType = compiler.coreTypes.streamType(); |
369 break; | 372 break; |
370 } | 373 } |
371 } | 374 } |
372 | 375 |
373 if (element.isSetter && (requiredParameterCount != 1 || | 376 if (element.isSetter && (requiredParameterCount != 1 || |
374 visitor.optionalParameterCount != 0)) { | 377 visitor.optionalParameterCount != 0)) { |
375 // If there are no formal parameters, we already reported an error above. | 378 // If there are no formal parameters, we already reported an error above. |
376 if (formalParameters != null) { | 379 if (formalParameters != null) { |
377 compiler.reportErrorMessage( | 380 reporter.reportErrorMessage( |
378 formalParameters, | 381 formalParameters, |
379 MessageKind.ILLEGAL_SETTER_FORMALS); | 382 MessageKind.ILLEGAL_SETTER_FORMALS); |
380 } | 383 } |
381 } | 384 } |
382 LinkBuilder<DartType> parameterTypes = new LinkBuilder<DartType>(); | 385 LinkBuilder<DartType> parameterTypes = new LinkBuilder<DartType>(); |
383 for (FormalElement parameter in parameters) { | 386 for (FormalElement parameter in parameters) { |
384 parameterTypes.addLast(parameter.type); | 387 parameterTypes.addLast(parameter.type); |
385 } | 388 } |
386 List<DartType> optionalParameterTypes = const <DartType>[]; | 389 List<DartType> optionalParameterTypes = const <DartType>[]; |
387 List<String> namedParameters = const <String>[]; | 390 List<String> namedParameters = const <String>[]; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 requiredParameterCount: requiredParameterCount, | 429 requiredParameterCount: requiredParameterCount, |
427 optionalParameterCount: visitor.optionalParameterCount, | 430 optionalParameterCount: visitor.optionalParameterCount, |
428 optionalParametersAreNamed: visitor.optionalParametersAreNamed, | 431 optionalParametersAreNamed: visitor.optionalParametersAreNamed, |
429 orderedOptionalParameters: orderedOptionalParameters, | 432 orderedOptionalParameters: orderedOptionalParameters, |
430 type: type); | 433 type: type); |
431 } | 434 } |
432 | 435 |
433 DartType resolveTypeAnnotation(TypeAnnotation annotation) { | 436 DartType resolveTypeAnnotation(TypeAnnotation annotation) { |
434 DartType type = resolveReturnType(annotation); | 437 DartType type = resolveReturnType(annotation); |
435 if (type.isVoid) { | 438 if (type.isVoid) { |
436 compiler.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED); | 439 reporter.reportErrorMessage(annotation, MessageKind.VOID_NOT_ALLOWED); |
437 } | 440 } |
438 return type; | 441 return type; |
439 } | 442 } |
440 | 443 |
441 DartType resolveReturnType(TypeAnnotation annotation) { | 444 DartType resolveReturnType(TypeAnnotation annotation) { |
442 if (annotation == null) return const DynamicType(); | 445 if (annotation == null) return const DynamicType(); |
443 DartType result = resolver.resolveTypeAnnotation(annotation); | 446 DartType result = resolver.resolveTypeAnnotation(annotation); |
444 if (result == null) { | 447 if (result == null) { |
445 return const DynamicType(); | 448 return const DynamicType(); |
446 } | 449 } |
447 return result; | 450 return result; |
448 } | 451 } |
449 } | 452 } |
OLD | NEW |