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