OLD | NEW |
| (Empty) |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 part of resolution; | |
6 | |
7 /** | |
8 * [SignatureResolver] resolves function signatures. | |
9 */ | |
10 class SignatureResolver extends MappingVisitor<FormalElementX> { | |
11 final ResolverVisitor resolver; | |
12 final FunctionTypedElement enclosingElement; | |
13 final Scope scope; | |
14 final MessageKind defaultValuesError; | |
15 final bool createRealParameters; | |
16 Link<Element> optionalParameters = const Link<Element>(); | |
17 int optionalParameterCount = 0; | |
18 bool isOptionalParameter = false; | |
19 bool optionalParametersAreNamed = false; | |
20 VariableDefinitions currentDefinitions; | |
21 | |
22 SignatureResolver(Compiler compiler, | |
23 FunctionTypedElement enclosingElement, | |
24 ResolutionRegistry registry, | |
25 {this.defaultValuesError, | |
26 this.createRealParameters}) | |
27 : this.enclosingElement = enclosingElement, | |
28 this.scope = enclosingElement.buildScope(), | |
29 this.resolver = | |
30 new ResolverVisitor(compiler, enclosingElement, registry), | |
31 super(compiler, registry); | |
32 | |
33 bool get defaultValuesAllowed => defaultValuesError == null; | |
34 | |
35 visitNodeList(NodeList node) { | |
36 // This must be a list of optional arguments. | |
37 String value = node.beginToken.stringValue; | |
38 if ((!identical(value, '[')) && (!identical(value, '{'))) { | |
39 internalError(node, "expected optional parameters"); | |
40 } | |
41 optionalParametersAreNamed = (identical(value, '{')); | |
42 isOptionalParameter = true; | |
43 LinkBuilder<Element> elements = analyzeNodes(node.nodes); | |
44 optionalParameterCount = elements.length; | |
45 optionalParameters = elements.toLink(); | |
46 } | |
47 | |
48 FormalElementX visitVariableDefinitions(VariableDefinitions node) { | |
49 Link<Node> definitions = node.definitions.nodes; | |
50 if (definitions.isEmpty) { | |
51 internalError(node, 'no parameter definition'); | |
52 return null; | |
53 } | |
54 if (!definitions.tail.isEmpty) { | |
55 internalError(definitions.tail.head, 'extra definition'); | |
56 return null; | |
57 } | |
58 Node definition = definitions.head; | |
59 if (definition is NodeList) { | |
60 internalError(node, 'optional parameters are not implemented'); | |
61 } | |
62 if (node.modifiers.isConst) { | |
63 compiler.reportError(node, MessageKind.FORMAL_DECLARED_CONST); | |
64 } | |
65 if (node.modifiers.isStatic) { | |
66 compiler.reportError(node, MessageKind.FORMAL_DECLARED_STATIC); | |
67 } | |
68 | |
69 if (currentDefinitions != null) { | |
70 internalError(node, 'function type parameters not supported'); | |
71 } | |
72 currentDefinitions = node; | |
73 FormalElementX element = definition.accept(this); | |
74 if (currentDefinitions.metadata != null) { | |
75 element.metadata = compiler.resolver.resolveMetadata(element, node); | |
76 } | |
77 currentDefinitions = null; | |
78 return element; | |
79 } | |
80 | |
81 void validateName(Identifier node) { | |
82 String name = node.source; | |
83 if (isOptionalParameter && | |
84 optionalParametersAreNamed && | |
85 isPrivateName(node.source)) { | |
86 compiler.reportError(node, MessageKind.PRIVATE_NAMED_PARAMETER); | |
87 } | |
88 } | |
89 | |
90 void computeParameterType(FormalElementX element, | |
91 [VariableElement fieldElement]) { | |
92 void computeFunctionType(FunctionExpression functionExpression) { | |
93 FunctionSignature functionSignature = SignatureResolver.analyze( | |
94 compiler, functionExpression.parameters, | |
95 functionExpression.returnType, element, registry, | |
96 defaultValuesError: MessageKind.FUNCTION_TYPE_FORMAL_WITH_DEFAULT); | |
97 element.functionSignatureCache = functionSignature; | |
98 element.typeCache = functionSignature.type; | |
99 } | |
100 | |
101 if (currentDefinitions.type != null) { | |
102 element.typeCache = resolveTypeAnnotation(currentDefinitions.type); | |
103 } else { | |
104 // Is node.definitions exactly one FunctionExpression? | |
105 Link<Node> link = currentDefinitions.definitions.nodes; | |
106 assert(invariant(currentDefinitions, !link.isEmpty)); | |
107 assert(invariant(currentDefinitions, link.tail.isEmpty)); | |
108 if (link.head.asFunctionExpression() != null) { | |
109 // Inline function typed parameter, like `void m(int f(String s))`. | |
110 computeFunctionType(link.head); | |
111 } else if (link.head.asSend() != null && | |
112 link.head.asSend().selector.asFunctionExpression() != null) { | |
113 // Inline function typed initializing formal or | |
114 // parameter with default value, like `C(int this.f(String s))` or | |
115 // `void m([int f(String s) = null])`. | |
116 computeFunctionType(link.head.asSend().selector.asFunctionExpression()); | |
117 } else { | |
118 assert(invariant(currentDefinitions, | |
119 link.head.asIdentifier() != null || link.head.asSend() != null)); | |
120 if (fieldElement != null) { | |
121 element.typeCache = fieldElement.computeType(compiler); | |
122 } else { | |
123 element.typeCache = const DynamicType(); | |
124 } | |
125 } | |
126 } | |
127 } | |
128 | |
129 Element visitIdentifier(Identifier node) { | |
130 return createParameter(node, null); | |
131 } | |
132 | |
133 Identifier getParameterName(Send node) { | |
134 var identifier = node.selector.asIdentifier(); | |
135 if (identifier != null) { | |
136 // Normal parameter: [:Type name:]. | |
137 return identifier; | |
138 } else { | |
139 // Function type parameter: [:void name(DartType arg):]. | |
140 var functionExpression = node.selector.asFunctionExpression(); | |
141 if (functionExpression != null && | |
142 functionExpression.name.asIdentifier() != null) { | |
143 return functionExpression.name.asIdentifier(); | |
144 } else { | |
145 internalError(node, | |
146 'internal error: unimplemented receiver on parameter send'); | |
147 return null; | |
148 } | |
149 } | |
150 } | |
151 | |
152 // The only valid [Send] can be in constructors and must be of the form | |
153 // [:this.x:] (where [:x:] represents an instance field). | |
154 InitializingFormalElementX visitSend(Send node) { | |
155 return createFieldParameter(node, null); | |
156 } | |
157 | |
158 FormalElementX createParameter(Identifier name, Expression initializer) { | |
159 validateName(name); | |
160 FormalElementX parameter; | |
161 if (createRealParameters) { | |
162 parameter = new LocalParameterElementX( | |
163 enclosingElement, currentDefinitions, name, initializer); | |
164 } else { | |
165 parameter = new FormalElementX( | |
166 ElementKind.PARAMETER, enclosingElement, currentDefinitions, name); | |
167 } | |
168 computeParameterType(parameter); | |
169 return parameter; | |
170 } | |
171 | |
172 InitializingFormalElementX createFieldParameter(Send node, | |
173 Expression initializer) { | |
174 InitializingFormalElementX element; | |
175 if (node.receiver.asIdentifier() == null || | |
176 !node.receiver.asIdentifier().isThis()) { | |
177 error(node, MessageKind.INVALID_PARAMETER); | |
178 } else if (!identical(enclosingElement.kind, | |
179 ElementKind.GENERATIVE_CONSTRUCTOR)) { | |
180 error(node, MessageKind.INITIALIZING_FORMAL_NOT_ALLOWED); | |
181 } else { | |
182 Identifier name = getParameterName(node); | |
183 validateName(name); | |
184 Element fieldElement = | |
185 enclosingElement.enclosingClass.lookupLocalMember(name.source); | |
186 if (fieldElement == null || | |
187 !identical(fieldElement.kind, ElementKind.FIELD)) { | |
188 error(node, MessageKind.NOT_A_FIELD, {'fieldName': name}); | |
189 } else if (!fieldElement.isInstanceMember) { | |
190 error(node, MessageKind.NOT_INSTANCE_FIELD, {'fieldName': name}); | |
191 } | |
192 element = new InitializingFormalElementX(enclosingElement, | |
193 currentDefinitions, name, initializer, fieldElement); | |
194 computeParameterType(element, fieldElement); | |
195 } | |
196 return element; | |
197 } | |
198 | |
199 /// A [SendSet] node is an optional parameter with a default value. | |
200 Element visitSendSet(SendSet node) { | |
201 FormalElementX element; | |
202 if (node.receiver != null) { | |
203 element = createFieldParameter(node, node.arguments.first); | |
204 } else if (node.selector.asIdentifier() != null || | |
205 node.selector.asFunctionExpression() != null) { | |
206 element = createParameter(getParameterName(node), node.arguments.first); | |
207 } | |
208 Node defaultValue = node.arguments.head; | |
209 if (!defaultValuesAllowed) { | |
210 compiler.reportError(defaultValue, defaultValuesError); | |
211 } | |
212 return element; | |
213 } | |
214 | |
215 Element visitFunctionExpression(FunctionExpression node) { | |
216 // This is a function typed parameter. | |
217 Modifiers modifiers = currentDefinitions.modifiers; | |
218 if (modifiers.isFinal) { | |
219 compiler.reportError(modifiers, | |
220 MessageKind.FINAL_FUNCTION_TYPE_PARAMETER); | |
221 } | |
222 if (modifiers.isVar) { | |
223 compiler.reportError(modifiers, MessageKind.VAR_FUNCTION_TYPE_PARAMETER); | |
224 } | |
225 | |
226 return createParameter(node.name, null); | |
227 } | |
228 | |
229 LinkBuilder<Element> analyzeNodes(Link<Node> link) { | |
230 LinkBuilder<Element> elements = new LinkBuilder<Element>(); | |
231 for (; !link.isEmpty; link = link.tail) { | |
232 Element element = link.head.accept(this); | |
233 if (element != null) { | |
234 elements.addLast(element); | |
235 } else { | |
236 // If parameter is null, the current node should be the last, | |
237 // and a list of optional named parameters. | |
238 if (!link.tail.isEmpty || (link.head is !NodeList)) { | |
239 internalError(link.head, "expected optional parameters"); | |
240 } | |
241 } | |
242 } | |
243 return elements; | |
244 } | |
245 | |
246 /** | |
247 * Resolves formal parameters and return type of a [FunctionExpression] | |
248 * to a [FunctionSignature]. | |
249 * | |
250 * If [createRealParameters] is `true`, the parameters will be | |
251 * real parameters implementing the [ParameterElement] interface. Otherwise, | |
252 * the parameters will only implement [FormalElement]. | |
253 */ | |
254 static FunctionSignature analyze(Compiler compiler, | |
255 NodeList formalParameters, | |
256 Node returnNode, | |
257 FunctionTypedElement element, | |
258 ResolutionRegistry registry, | |
259 {MessageKind defaultValuesError, | |
260 bool createRealParameters: false}) { | |
261 SignatureResolver visitor = new SignatureResolver(compiler, element, | |
262 registry, defaultValuesError: defaultValuesError, | |
263 createRealParameters: createRealParameters); | |
264 Link<Element> parameters = const Link<Element>(); | |
265 int requiredParameterCount = 0; | |
266 if (formalParameters == null) { | |
267 if (!element.isGetter) { | |
268 if (element.isErroneous) { | |
269 // If the element is erroneous, an error should already have been | |
270 // reported. In the case of parse errors, it is possible that there | |
271 // are formal parameters, but something else in the method failed to | |
272 // parse. So we suppress the message about missing formals. | |
273 assert(invariant(element, compiler.compilationFailed)); | |
274 } else { | |
275 compiler.reportError(element, MessageKind.MISSING_FORMALS); | |
276 } | |
277 } | |
278 } else { | |
279 if (element.isGetter) { | |
280 if (!identical(formalParameters.endToken.next.stringValue, | |
281 // TODO(ahe): Remove the check for native keyword. | |
282 'native')) { | |
283 compiler.reportError(formalParameters, | |
284 MessageKind.EXTRA_FORMALS); | |
285 } | |
286 } | |
287 LinkBuilder<Element> parametersBuilder = | |
288 visitor.analyzeNodes(formalParameters.nodes); | |
289 requiredParameterCount = parametersBuilder.length; | |
290 parameters = parametersBuilder.toLink(); | |
291 } | |
292 DartType returnType; | |
293 if (element.isFactoryConstructor) { | |
294 returnType = element.enclosingClass.thisType; | |
295 // Because there is no type annotation for the return type of | |
296 // this element, we explicitly add one. | |
297 if (compiler.enableTypeAssertions) { | |
298 registry.registerIsCheck(returnType); | |
299 } | |
300 } else { | |
301 returnType = visitor.resolveReturnType(returnNode); | |
302 } | |
303 | |
304 if (element.isSetter && (requiredParameterCount != 1 || | |
305 visitor.optionalParameterCount != 0)) { | |
306 // If there are no formal parameters, we already reported an error above. | |
307 if (formalParameters != null) { | |
308 compiler.reportError(formalParameters, | |
309 MessageKind.ILLEGAL_SETTER_FORMALS); | |
310 } | |
311 } | |
312 LinkBuilder<DartType> parameterTypes = new LinkBuilder<DartType>(); | |
313 for (FormalElement parameter in parameters) { | |
314 parameterTypes.addLast(parameter.type); | |
315 } | |
316 List<DartType> optionalParameterTypes = const <DartType>[]; | |
317 List<String> namedParameters = const <String>[]; | |
318 List<DartType> namedParameterTypes = const <DartType>[]; | |
319 List<Element> orderedOptionalParameters = | |
320 visitor.optionalParameters.toList(); | |
321 if (visitor.optionalParametersAreNamed) { | |
322 // TODO(karlklose); replace when [visitor.optinalParameters] is a [List]. | |
323 orderedOptionalParameters.sort((Element a, Element b) { | |
324 return a.name.compareTo(b.name); | |
325 }); | |
326 LinkBuilder<String> namedParametersBuilder = new LinkBuilder<String>(); | |
327 LinkBuilder<DartType> namedParameterTypesBuilder = | |
328 new LinkBuilder<DartType>(); | |
329 for (FormalElement parameter in orderedOptionalParameters) { | |
330 namedParametersBuilder.addLast(parameter.name); | |
331 namedParameterTypesBuilder.addLast(parameter.type); | |
332 } | |
333 namedParameters = namedParametersBuilder.toLink().toList(growable: false); | |
334 namedParameterTypes = namedParameterTypesBuilder.toLink() | |
335 .toList(growable: false); | |
336 } else { | |
337 // TODO(karlklose); replace when [visitor.optinalParameters] is a [List]. | |
338 LinkBuilder<DartType> optionalParameterTypesBuilder = | |
339 new LinkBuilder<DartType>(); | |
340 for (FormalElement parameter in visitor.optionalParameters) { | |
341 optionalParameterTypesBuilder.addLast(parameter.type); | |
342 } | |
343 optionalParameterTypes = optionalParameterTypesBuilder.toLink() | |
344 .toList(growable: false); | |
345 } | |
346 FunctionType type = new FunctionType( | |
347 element.declaration, | |
348 returnType, | |
349 parameterTypes.toLink().toList(growable: false), | |
350 optionalParameterTypes, | |
351 namedParameters, | |
352 namedParameterTypes); | |
353 return new FunctionSignatureX(parameters, | |
354 visitor.optionalParameters, | |
355 requiredParameterCount, | |
356 visitor.optionalParameterCount, | |
357 visitor.optionalParametersAreNamed, | |
358 orderedOptionalParameters, | |
359 type); | |
360 } | |
361 | |
362 DartType resolveTypeAnnotation(TypeAnnotation annotation) { | |
363 DartType type = resolveReturnType(annotation); | |
364 if (type.isVoid) { | |
365 compiler.reportError(annotation, MessageKind.VOID_NOT_ALLOWED); | |
366 } | |
367 return type; | |
368 } | |
369 | |
370 DartType resolveReturnType(TypeAnnotation annotation) { | |
371 if (annotation == null) return const DynamicType(); | |
372 DartType result = resolver.resolveTypeAnnotation(annotation); | |
373 if (result == null) { | |
374 return const DynamicType(); | |
375 } | |
376 return result; | |
377 } | |
378 } | |
OLD | NEW |