OLD | NEW |
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.types; | 5 library dart2js.resolution.types; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/resolution.dart' show Resolution; | 8 import '../common/resolution.dart' show Resolution; |
9 import '../elements/resolution_types.dart'; | 9 import '../elements/resolution_types.dart'; |
10 import '../elements/elements.dart' | 10 import '../elements/elements.dart' |
11 show | 11 show |
12 AmbiguousElement, | 12 AmbiguousElement, |
13 ClassElement, | 13 ClassElement, |
14 Element, | 14 Element, |
15 Elements, | 15 Elements, |
16 ErroneousElement, | 16 ErroneousElement, |
17 PrefixElement, | 17 PrefixElement, |
18 TypedefElement, | 18 TypedefElement, |
19 TypeVariableElement; | 19 TypeVariableElement; |
20 import '../elements/modelx.dart' show ErroneousElementX; | 20 import '../elements/modelx.dart' show ErroneousElementX; |
21 import '../resolution/resolution.dart'; | 21 import '../resolution/resolution.dart'; |
22 import '../tree/tree.dart'; | 22 import '../tree/tree.dart'; |
23 import '../universe/feature.dart' show Feature; | 23 import '../universe/feature.dart' show Feature; |
24 import '../util/util.dart' show Link; | 24 import '../util/util.dart' show Link; |
25 import 'members.dart' show lookupInScope; | 25 import 'members.dart' show lookupInScope; |
26 import 'registry.dart' show ResolutionRegistry; | 26 import 'registry.dart' show ResolutionRegistry; |
27 import 'resolution_common.dart' show MappingVisitor; | 27 import 'resolution_common.dart' show MappingVisitor; |
28 import 'scope.dart' show Scope; | 28 import 'scope.dart' show Scope; |
29 | 29 |
30 class _FormalsTypeResolutionResult { | |
31 final List<ResolutionDartType> requiredTypes; | |
32 final List<ResolutionDartType> orderedTypes; | |
33 final List<String> names; | |
34 final List<ResolutionDartType> nameTypes; | |
35 | |
36 _FormalsTypeResolutionResult( | |
37 this.requiredTypes, this.orderedTypes, this.names, this.nameTypes); | |
38 } | |
39 | |
40 class TypeResolver { | 30 class TypeResolver { |
41 final Resolution resolution; | 31 final Resolution resolution; |
42 | 32 |
43 TypeResolver(this.resolution); | 33 TypeResolver(this.resolution); |
44 | 34 |
45 ResolverTask get resolver => resolution.resolver; | 35 ResolverTask get resolver => resolution.resolver; |
46 DiagnosticReporter get reporter => resolution.reporter; | 36 DiagnosticReporter get reporter => resolution.reporter; |
47 Types get types => resolution.types; | 37 Types get types => resolution.types; |
48 | 38 |
49 /// Tries to resolve the type name as an element. | 39 /// Tries to resolve the type name as an element. |
(...skipping 19 matching lines...) Expand all Loading... |
69 } | 59 } |
70 } else { | 60 } else { |
71 element = lookupInScope(reporter, typeName, scope, typeName.source); | 61 element = lookupInScope(reporter, typeName, scope, typeName.source); |
72 } | 62 } |
73 return element; | 63 return element; |
74 } | 64 } |
75 | 65 |
76 ResolutionDartType resolveTypeAnnotation( | 66 ResolutionDartType resolveTypeAnnotation( |
77 MappingVisitor visitor, TypeAnnotation node, | 67 MappingVisitor visitor, TypeAnnotation node, |
78 {bool malformedIsError: false, bool deferredIsMalformed: true}) { | 68 {bool malformedIsError: false, bool deferredIsMalformed: true}) { |
79 return _resolveTypeAnnotation( | |
80 visitor, node, const [], malformedIsError: malformedIsError, | |
81 deferredIsMalformed: deferredIsMalformed); | |
82 } | |
83 | |
84 // TODO(floitsch): the [visibleTypeParameterNames] is a hack to put | |
85 // type parameters in scope for the nested types. | |
86 // | |
87 // For example, in the following example, the generic type "A" would be stored | |
88 // in `visibleTypeParameterNames`. | |
89 // `typedef F = Function(List<A> Function<A>(A x))`. | |
90 // | |
91 // They are resolved to `dynamic` until dart2js supports generic methods. | |
92 ResolutionDartType _resolveTypeAnnotation( | |
93 MappingVisitor visitor, TypeAnnotation node, | |
94 List<List<String>> visibleTypeParameterNames, | |
95 {bool malformedIsError: false, bool deferredIsMalformed: true}) { | |
96 | |
97 if (node.asNominalTypeAnnotation() != null) { | |
98 return resolveNominalTypeAnnotation( | |
99 visitor, node, | |
100 visibleTypeParameterNames, | |
101 malformedIsError: malformedIsError, | |
102 deferredIsMalformed: deferredIsMalformed); | |
103 } | |
104 assert(node.asFunctionTypeAnnotation() != null); | |
105 return _resolveFunctionTypeAnnotation( | |
106 visitor, node, visibleTypeParameterNames, | |
107 malformedIsError: malformedIsError, | |
108 deferredIsMalformed: deferredIsMalformed); | |
109 } | |
110 | |
111 /// Resolves the types of a parameter list. | |
112 /// | |
113 /// This function does not accept "inline" function types. For example | |
114 /// `foo(int bar(String x))` is not accepted. | |
115 /// | |
116 /// However, it does work with nested generalized function types: | |
117 /// `foo(int Function(String) x)`. | |
118 _FormalsTypeResolutionResult _resolveFormalTypes( | |
119 MappingVisitor visitor, NodeList formals, | |
120 List<List<String>> visibleTypeParameterNames) { | |
121 | |
122 ResolutionDartType resolvePositionalType(VariableDefinitions node) { | |
123 return _resolveTypeAnnotation( | |
124 visitor, node.type, visibleTypeParameterNames); | |
125 } | |
126 | |
127 void fillNamedTypes(NodeList namedFormals, | |
128 List<String> names, List<ResolutionDartType> types) { | |
129 List<Node> nodes = namedFormals.nodes.toList(growable: false); | |
130 | |
131 // Sort the named arguments first. | |
132 nodes.sort((node1, node2) { | |
133 VariableDefinitions a = node1; | |
134 VariableDefinitions b = node2; | |
135 assert(a.definitions.nodes.tail.isEmpty); | |
136 assert(b.definitions.nodes.tail.isEmpty); | |
137 return a.definitions.nodes.head.asIdentifier().source.compareTo( | |
138 b.definitions.nodes.head.asIdentifier().source); | |
139 }); | |
140 | |
141 for (VariableDefinitions node in nodes) { | |
142 String name = node.definitions.nodes.head.asIdentifier().source; | |
143 ResolutionDartType type = node.type == null | |
144 ? const ResolutionDynamicType() | |
145 : _resolveTypeAnnotation( | |
146 visitor, node.type, visibleTypeParameterNames); | |
147 names.add(name); | |
148 types.add(type); | |
149 } | |
150 } | |
151 | |
152 List<ResolutionDartType> requiredTypes = <ResolutionDartType>[]; | |
153 NodeList optionalFormals = null; | |
154 for (Link<Node> link = formals.nodes; !link.isEmpty; link = link.tail) { | |
155 if (link.tail.isEmpty && link.head is NodeList) { | |
156 optionalFormals = link.head; | |
157 break; | |
158 } | |
159 requiredTypes.add(resolvePositionalType(link.head)); | |
160 } | |
161 | |
162 | |
163 List<ResolutionDartType> orderedTypes = const <ResolutionDartType>[]; | |
164 List<String> names = const <String>[]; | |
165 List<ResolutionDartType> namedTypes = const <ResolutionDartType>[]; | |
166 | |
167 if (optionalFormals != null) { | |
168 // This must be a list of optional arguments. | |
169 String value = optionalFormals.beginToken.stringValue; | |
170 if ((!identical(value, '[')) && (!identical(value, '{'))) { | |
171 reporter.internalError(optionalFormals, "expected optional parameters"); | |
172 } | |
173 bool optionalParametersAreNamed = (identical(value, '{')); | |
174 | |
175 if (optionalParametersAreNamed) { | |
176 names = <String>[]; | |
177 namedTypes = <ResolutionDartType>[]; | |
178 fillNamedTypes(optionalFormals, names, namedTypes); | |
179 } else { | |
180 orderedTypes = <ResolutionDartType>[]; | |
181 for (Link<Node> link = optionalFormals.nodes; | |
182 !link.isEmpty; | |
183 link = link.tail) { | |
184 orderedTypes.add(resolvePositionalType(link.head)); | |
185 } | |
186 } | |
187 } | |
188 return new _FormalsTypeResolutionResult( | |
189 requiredTypes, orderedTypes, names, namedTypes); | |
190 } | |
191 | |
192 ResolutionFunctionType _resolveFunctionTypeAnnotation(MappingVisitor visitor, | |
193 FunctionTypeAnnotation node, | |
194 List<List<String>> visibleTypeParameterNames, | |
195 {bool malformedIsError: false, bool deferredIsMalformed: true}) { | |
196 | |
197 assert(visibleTypeParameterNames != null); | |
198 | |
199 if (node.typeParameters != null) { | |
200 List<String> newTypeNames = node.typeParameters.map((TypeVariable node) { | |
201 return node.name.asIdentifier().source; | |
202 }).toList(); | |
203 visibleTypeParameterNames = | |
204 visibleTypeParameterNames.toList()..add(newTypeNames); | |
205 } | |
206 | |
207 ResolutionDartType returnType = node.returnType == null | |
208 ? const ResolutionDynamicType() | |
209 : _resolveTypeAnnotation(visitor, node.returnType, | |
210 visibleTypeParameterNames); | |
211 var formalTypes = | |
212 _resolveFormalTypes(visitor, node.formals, visibleTypeParameterNames); | |
213 var result = new ResolutionFunctionType.generalized( | |
214 returnType, | |
215 formalTypes.requiredTypes, | |
216 formalTypes.orderedTypes, | |
217 formalTypes.names, | |
218 formalTypes.nameTypes); | |
219 visitor.registry.useType(node, result); | |
220 return result; | |
221 } | |
222 | |
223 ResolutionDartType resolveNominalTypeAnnotation(MappingVisitor visitor, | |
224 NominalTypeAnnotation node, | |
225 List<List<String>> visibleTypeParameterNames, | |
226 {bool malformedIsError: false, bool deferredIsMalformed: true}) { | |
227 ResolutionRegistry registry = visitor.registry; | 69 ResolutionRegistry registry = visitor.registry; |
228 | 70 |
229 Identifier typeName; | 71 Identifier typeName; |
230 ResolutionDartType type; | 72 ResolutionDartType type; |
231 | 73 |
232 ResolutionDartType checkNoTypeArguments(ResolutionDartType type) { | 74 ResolutionDartType checkNoTypeArguments(ResolutionDartType type) { |
233 List<ResolutionDartType> arguments = new List<ResolutionDartType>(); | 75 List<ResolutionDartType> arguments = new List<ResolutionDartType>(); |
234 bool hasTypeArgumentMismatch = resolveTypeArguments( | 76 bool hasTypeArgumentMismatch = resolveTypeArguments( |
235 visitor, node, const <ResolutionDartType>[], arguments, | 77 visitor, node, const <ResolutionDartType>[], arguments); |
236 visibleTypeParameterNames); | |
237 if (hasTypeArgumentMismatch) { | 78 if (hasTypeArgumentMismatch) { |
238 return new MalformedType( | 79 return new MalformedType( |
239 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, | 80 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
240 {'type': node}, typeName.source, visitor.enclosingElement), | 81 {'type': node}, typeName.source, visitor.enclosingElement), |
241 type, | 82 type, |
242 arguments); | 83 arguments); |
243 } | 84 } |
244 return type; | 85 return type; |
245 } | 86 } |
246 | 87 |
(...skipping 11 matching lines...) Expand all Loading... |
258 registry.useType(node, type); | 99 registry.useType(node, type); |
259 return type; | 100 return type; |
260 } else if (identical(typeName.source, 'dynamic')) { | 101 } else if (identical(typeName.source, 'dynamic')) { |
261 type = const ResolutionDynamicType(); | 102 type = const ResolutionDynamicType(); |
262 checkNoTypeArguments(type); | 103 checkNoTypeArguments(type); |
263 registry.useType(node, type); | 104 registry.useType(node, type); |
264 return type; | 105 return type; |
265 } | 106 } |
266 } | 107 } |
267 | 108 |
| 109 Element element = resolveTypeName(prefixName, typeName, visitor.scope, |
| 110 deferredIsMalformed: deferredIsMalformed); |
| 111 |
268 ResolutionDartType reportFailureAndCreateType( | 112 ResolutionDartType reportFailureAndCreateType( |
269 MessageKind messageKind, Map messageArguments, | 113 MessageKind messageKind, Map messageArguments, |
270 {ResolutionDartType userProvidedBadType, | 114 {ResolutionDartType userProvidedBadType, |
271 Element erroneousElement, | 115 Element erroneousElement, |
272 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { | 116 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { |
273 if (malformedIsError) { | 117 if (malformedIsError) { |
274 reporter.reportError( | 118 reporter.reportError( |
275 reporter.createMessage(node, messageKind, messageArguments), infos); | 119 reporter.createMessage(node, messageKind, messageArguments), infos); |
276 } else { | 120 } else { |
277 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 121 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
278 reporter.reportWarning( | 122 reporter.reportWarning( |
279 reporter.createMessage(node, messageKind, messageArguments), infos); | 123 reporter.createMessage(node, messageKind, messageArguments), infos); |
280 } | 124 } |
281 if (erroneousElement == null) { | 125 if (erroneousElement == null) { |
282 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 126 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
283 erroneousElement = new ErroneousElementX(messageKind, messageArguments, | 127 erroneousElement = new ErroneousElementX(messageKind, messageArguments, |
284 typeName.source, visitor.enclosingElement); | 128 typeName.source, visitor.enclosingElement); |
285 } | 129 } |
286 List<ResolutionDartType> arguments = <ResolutionDartType>[]; | 130 List<ResolutionDartType> arguments = <ResolutionDartType>[]; |
287 resolveTypeArguments(visitor, node, const <ResolutionDartType>[], | 131 resolveTypeArguments( |
288 arguments, visibleTypeParameterNames); | 132 visitor, node, const <ResolutionDartType>[], arguments); |
289 return new MalformedType( | 133 return new MalformedType( |
290 erroneousElement, userProvidedBadType, arguments); | 134 erroneousElement, userProvidedBadType, arguments); |
291 } | 135 } |
292 | 136 |
293 Element element; | |
294 // Resolve references to type names as dynamic. | |
295 // TODO(floitsch): this hackishly resolves generic function type arguments | |
296 // to dynamic. | |
297 if (prefixName == null && | |
298 visibleTypeParameterNames.any((n) => n.contains(typeName.source))) { | |
299 type = const ResolutionDynamicType(); | |
300 } else { | |
301 element = resolveTypeName(prefixName, typeName, visitor.scope, | |
302 deferredIsMalformed: deferredIsMalformed); | |
303 } | |
304 | |
305 // Try to construct the type from the element. | 137 // Try to construct the type from the element. |
306 if (type != null) { | 138 if (element == null) { |
307 // Already assigned to through the visibleTypeParameterNames. | |
308 // Just make sure that it doesn't have type arguments. | |
309 if (node.typeArguments != null) { | |
310 reporter.reportWarningMessage(node.typeArguments.nodes.head, | |
311 MessageKind.ADDITIONAL_TYPE_ARGUMENT); | |
312 } | |
313 } else if (element == null) { | |
314 type = reportFailureAndCreateType( | 139 type = reportFailureAndCreateType( |
315 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}); | 140 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}); |
316 } else if (element.isAmbiguous) { | 141 } else if (element.isAmbiguous) { |
317 AmbiguousElement ambiguous = element; | 142 AmbiguousElement ambiguous = element; |
318 type = reportFailureAndCreateType( | 143 type = reportFailureAndCreateType( |
319 ambiguous.messageKind, ambiguous.messageArguments, | 144 ambiguous.messageKind, ambiguous.messageArguments, |
320 infos: ambiguous.computeInfos( | 145 infos: ambiguous.computeInfos( |
321 registry.mapping.analyzedElement, reporter)); | 146 registry.mapping.analyzedElement, reporter)); |
322 ; | 147 ; |
323 } else if (element.isMalformed) { | 148 } else if (element.isMalformed) { |
(...skipping 14 matching lines...) Expand all Loading... |
338 return type; | 163 return type; |
339 } else { | 164 } else { |
340 bool addTypeVariableBoundsCheck = false; | 165 bool addTypeVariableBoundsCheck = false; |
341 if (element.isClass) { | 166 if (element.isClass) { |
342 ClassElement cls = element; | 167 ClassElement cls = element; |
343 // TODO(johnniwinther): [ensureClassWillBeResolvedInternal] should imply | 168 // TODO(johnniwinther): [ensureClassWillBeResolvedInternal] should imply |
344 // [computeType]. | 169 // [computeType]. |
345 resolver.ensureClassWillBeResolvedInternal(cls); | 170 resolver.ensureClassWillBeResolvedInternal(cls); |
346 cls.computeType(resolution); | 171 cls.computeType(resolution); |
347 List<ResolutionDartType> arguments = <ResolutionDartType>[]; | 172 List<ResolutionDartType> arguments = <ResolutionDartType>[]; |
348 bool hasTypeArgumentMismatch = resolveTypeArguments( | 173 bool hasTypeArgumentMismatch = |
349 visitor, node, cls.typeVariables, arguments, | 174 resolveTypeArguments(visitor, node, cls.typeVariables, arguments); |
350 visibleTypeParameterNames); | |
351 if (hasTypeArgumentMismatch) { | 175 if (hasTypeArgumentMismatch) { |
352 type = new BadInterfaceType( | 176 type = new BadInterfaceType( |
353 cls.declaration, | 177 cls.declaration, |
354 new ResolutionInterfaceType.forUserProvidedBadType( | 178 new ResolutionInterfaceType.forUserProvidedBadType( |
355 cls.declaration, arguments)); | 179 cls.declaration, arguments)); |
356 } else { | 180 } else { |
357 if (arguments.isEmpty) { | 181 if (arguments.isEmpty) { |
358 type = cls.rawType; | 182 type = cls.rawType; |
359 } else { | 183 } else { |
360 type = new ResolutionInterfaceType( | 184 type = new ResolutionInterfaceType( |
361 cls.declaration, arguments.toList(growable: false)); | 185 cls.declaration, arguments.toList(growable: false)); |
362 addTypeVariableBoundsCheck = | 186 addTypeVariableBoundsCheck = |
363 arguments.any((ResolutionDartType type) => !type.isDynamic); | 187 arguments.any((ResolutionDartType type) => !type.isDynamic); |
364 } | 188 } |
365 } | 189 } |
366 } else if (element.isTypedef) { | 190 } else if (element.isTypedef) { |
367 TypedefElement typdef = element; | 191 TypedefElement typdef = element; |
368 // TODO(johnniwinther): [ensureResolved] should imply [computeType]. | 192 // TODO(johnniwinther): [ensureResolved] should imply [computeType]. |
369 typdef.ensureResolved(resolution); | 193 typdef.ensureResolved(resolution); |
370 typdef.computeType(resolution); | 194 typdef.computeType(resolution); |
371 List<ResolutionDartType> arguments = <ResolutionDartType>[]; | 195 List<ResolutionDartType> arguments = <ResolutionDartType>[]; |
372 bool hasTypeArgumentMismatch = resolveTypeArguments( | 196 bool hasTypeArgumentMismatch = resolveTypeArguments( |
373 visitor, node, typdef.typeVariables, arguments, | 197 visitor, node, typdef.typeVariables, arguments); |
374 visibleTypeParameterNames); | |
375 if (hasTypeArgumentMismatch) { | 198 if (hasTypeArgumentMismatch) { |
376 type = new BadTypedefType( | 199 type = new BadTypedefType( |
377 typdef, | 200 typdef, |
378 new ResolutionTypedefType.forUserProvidedBadType( | 201 new ResolutionTypedefType.forUserProvidedBadType( |
379 typdef, arguments)); | 202 typdef, arguments)); |
380 } else { | 203 } else { |
381 if (arguments.isEmpty) { | 204 if (arguments.isEmpty) { |
382 type = typdef.rawType; | 205 type = typdef.rawType; |
383 } else { | 206 } else { |
384 type = new ResolutionTypedefType( | 207 type = new ResolutionTypedefType( |
(...skipping 26 matching lines...) Expand all Loading... |
411 if (addTypeVariableBoundsCheck) { | 234 if (addTypeVariableBoundsCheck) { |
412 visitor.addDeferredAction(visitor.enclosingElement, | 235 visitor.addDeferredAction(visitor.enclosingElement, |
413 () => checkTypeVariableBounds(node, type)); | 236 () => checkTypeVariableBounds(node, type)); |
414 } | 237 } |
415 } | 238 } |
416 registry.useType(node, type); | 239 registry.useType(node, type); |
417 return type; | 240 return type; |
418 } | 241 } |
419 | 242 |
420 /// Checks the type arguments of [type] against the type variable bounds. | 243 /// Checks the type arguments of [type] against the type variable bounds. |
421 void checkTypeVariableBounds(NominalTypeAnnotation node, GenericType type) { | 244 void checkTypeVariableBounds(TypeAnnotation node, GenericType type) { |
422 void checkTypeVariableBound(_, ResolutionDartType typeArgument, | 245 void checkTypeVariableBound(_, ResolutionDartType typeArgument, |
423 ResolutionTypeVariableType typeVariable, ResolutionDartType bound) { | 246 ResolutionTypeVariableType typeVariable, ResolutionDartType bound) { |
424 if (!types.isSubtype(typeArgument, bound)) { | 247 if (!types.isSubtype(typeArgument, bound)) { |
425 reporter.reportWarningMessage( | 248 reporter.reportWarningMessage( |
426 node, MessageKind.INVALID_TYPE_VARIABLE_BOUND, { | 249 node, MessageKind.INVALID_TYPE_VARIABLE_BOUND, { |
427 'typeVariable': typeVariable, | 250 'typeVariable': typeVariable, |
428 'bound': bound, | 251 'bound': bound, |
429 'typeArgument': typeArgument, | 252 'typeArgument': typeArgument, |
430 'thisType': type.element.thisType | 253 'thisType': type.element.thisType |
431 }); | 254 }); |
432 } | 255 } |
433 } | 256 } |
434 | 257 |
435 types.checkTypeVariableBounds(type, checkTypeVariableBound); | 258 types.checkTypeVariableBounds(type, checkTypeVariableBound); |
436 } | 259 } |
437 | 260 |
438 /** | 261 /** |
439 * Resolves the type arguments of [node] and adds these to [arguments]. | 262 * Resolves the type arguments of [node] and adds these to [arguments]. |
440 * | 263 * |
441 * Returns [: true :] if the number of type arguments did not match the | 264 * Returns [: true :] if the number of type arguments did not match the |
442 * number of type variables. | 265 * number of type variables. |
443 */ | 266 */ |
444 bool resolveTypeArguments( | 267 bool resolveTypeArguments( |
445 MappingVisitor visitor, | 268 MappingVisitor visitor, |
446 NominalTypeAnnotation node, | 269 TypeAnnotation node, |
447 List<ResolutionDartType> typeVariables, | 270 List<ResolutionDartType> typeVariables, |
448 List<ResolutionDartType> arguments, | 271 List<ResolutionDartType> arguments) { |
449 List<List<String>> visibleTypeParameterNames) { | |
450 if (node.typeArguments == null) { | 272 if (node.typeArguments == null) { |
451 return false; | 273 return false; |
452 } | 274 } |
453 int expectedVariables = typeVariables.length; | 275 int expectedVariables = typeVariables.length; |
454 int index = 0; | 276 int index = 0; |
455 bool typeArgumentCountMismatch = false; | 277 bool typeArgumentCountMismatch = false; |
456 for (Link<Node> typeArguments = node.typeArguments.nodes; | 278 for (Link<Node> typeArguments = node.typeArguments.nodes; |
457 !typeArguments.isEmpty; | 279 !typeArguments.isEmpty; |
458 typeArguments = typeArguments.tail, index++) { | 280 typeArguments = typeArguments.tail, index++) { |
459 if (index > expectedVariables - 1) { | 281 if (index > expectedVariables - 1) { |
460 reporter.reportWarningMessage( | 282 reporter.reportWarningMessage( |
461 typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 283 typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
462 typeArgumentCountMismatch = true; | 284 typeArgumentCountMismatch = true; |
463 } | 285 } |
464 ResolutionDartType argType = _resolveTypeAnnotation( | 286 ResolutionDartType argType = |
465 visitor, typeArguments.head, visibleTypeParameterNames); | 287 resolveTypeAnnotation(visitor, typeArguments.head); |
466 // TODO(karlklose): rewrite to not modify [arguments]. | 288 // TODO(karlklose): rewrite to not modify [arguments]. |
467 arguments.add(argType); | 289 arguments.add(argType); |
468 } | 290 } |
469 if (index < expectedVariables) { | 291 if (index < expectedVariables) { |
470 reporter.reportWarningMessage( | 292 reporter.reportWarningMessage( |
471 node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); | 293 node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
472 typeArgumentCountMismatch = true; | 294 typeArgumentCountMismatch = true; |
473 } | 295 } |
474 return typeArgumentCountMismatch; | 296 return typeArgumentCountMismatch; |
475 } | 297 } |
476 } | 298 } |
OLD | NEW |