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

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

Issue 2567133002: Add support for the new function-type syntax. (Closed)
Patch Set: Fixes after rebase. Created 3 years, 9 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 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
30 class TypeResolver { 40 class TypeResolver {
31 final Resolution resolution; 41 final Resolution resolution;
32 42
33 TypeResolver(this.resolution); 43 TypeResolver(this.resolution);
34 44
35 ResolverTask get resolver => resolution.resolver; 45 ResolverTask get resolver => resolution.resolver;
36 DiagnosticReporter get reporter => resolution.reporter; 46 DiagnosticReporter get reporter => resolution.reporter;
37 Types get types => resolution.types; 47 Types get types => resolution.types;
38 48
39 /// Tries to resolve the type name as an element. 49 /// Tries to resolve the type name as an element.
(...skipping 19 matching lines...) Expand all
59 } 69 }
60 } else { 70 } else {
61 element = lookupInScope(reporter, typeName, scope, typeName.source); 71 element = lookupInScope(reporter, typeName, scope, typeName.source);
62 } 72 }
63 return element; 73 return element;
64 } 74 }
65 75
66 ResolutionDartType resolveTypeAnnotation( 76 ResolutionDartType resolveTypeAnnotation(
67 MappingVisitor visitor, TypeAnnotation node, 77 MappingVisitor visitor, TypeAnnotation node,
68 {bool malformedIsError: false, bool deferredIsMalformed: true}) { 78 {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}) {
69 ResolutionRegistry registry = visitor.registry; 227 ResolutionRegistry registry = visitor.registry;
70 228
71 Identifier typeName; 229 Identifier typeName;
72 ResolutionDartType type; 230 ResolutionDartType type;
73 231
74 ResolutionDartType checkNoTypeArguments(ResolutionDartType type) { 232 ResolutionDartType checkNoTypeArguments(ResolutionDartType type) {
75 List<ResolutionDartType> arguments = new List<ResolutionDartType>(); 233 List<ResolutionDartType> arguments = new List<ResolutionDartType>();
76 bool hasTypeArgumentMismatch = resolveTypeArguments( 234 bool hasTypeArgumentMismatch = resolveTypeArguments(
77 visitor, node, const <ResolutionDartType>[], arguments); 235 visitor, node, const <ResolutionDartType>[], arguments,
236 visibleTypeParameterNames);
78 if (hasTypeArgumentMismatch) { 237 if (hasTypeArgumentMismatch) {
79 return new MalformedType( 238 return new MalformedType(
80 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, 239 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH,
81 {'type': node}, typeName.source, visitor.enclosingElement), 240 {'type': node}, typeName.source, visitor.enclosingElement),
82 type, 241 type,
83 arguments); 242 arguments);
84 } 243 }
85 return type; 244 return type;
86 } 245 }
87 246
(...skipping 11 matching lines...) Expand all
99 registry.useType(node, type); 258 registry.useType(node, type);
100 return type; 259 return type;
101 } else if (identical(typeName.source, 'dynamic')) { 260 } else if (identical(typeName.source, 'dynamic')) {
102 type = const ResolutionDynamicType(); 261 type = const ResolutionDynamicType();
103 checkNoTypeArguments(type); 262 checkNoTypeArguments(type);
104 registry.useType(node, type); 263 registry.useType(node, type);
105 return type; 264 return type;
106 } 265 }
107 } 266 }
108 267
109 Element element = resolveTypeName(prefixName, typeName, visitor.scope,
110 deferredIsMalformed: deferredIsMalformed);
111
112 ResolutionDartType reportFailureAndCreateType( 268 ResolutionDartType reportFailureAndCreateType(
113 MessageKind messageKind, Map messageArguments, 269 MessageKind messageKind, Map messageArguments,
114 {ResolutionDartType userProvidedBadType, 270 {ResolutionDartType userProvidedBadType,
115 Element erroneousElement, 271 Element erroneousElement,
116 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { 272 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) {
117 if (malformedIsError) { 273 if (malformedIsError) {
118 reporter.reportError( 274 reporter.reportError(
119 reporter.createMessage(node, messageKind, messageArguments), infos); 275 reporter.createMessage(node, messageKind, messageArguments), infos);
120 } else { 276 } else {
121 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); 277 registry.registerFeature(Feature.THROW_RUNTIME_ERROR);
122 reporter.reportWarning( 278 reporter.reportWarning(
123 reporter.createMessage(node, messageKind, messageArguments), infos); 279 reporter.createMessage(node, messageKind, messageArguments), infos);
124 } 280 }
125 if (erroneousElement == null) { 281 if (erroneousElement == null) {
126 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); 282 registry.registerFeature(Feature.THROW_RUNTIME_ERROR);
127 erroneousElement = new ErroneousElementX(messageKind, messageArguments, 283 erroneousElement = new ErroneousElementX(messageKind, messageArguments,
128 typeName.source, visitor.enclosingElement); 284 typeName.source, visitor.enclosingElement);
129 } 285 }
130 List<ResolutionDartType> arguments = <ResolutionDartType>[]; 286 List<ResolutionDartType> arguments = <ResolutionDartType>[];
131 resolveTypeArguments( 287 resolveTypeArguments(visitor, node, const <ResolutionDartType>[],
132 visitor, node, const <ResolutionDartType>[], arguments); 288 arguments, visibleTypeParameterNames);
133 return new MalformedType( 289 return new MalformedType(
134 erroneousElement, userProvidedBadType, arguments); 290 erroneousElement, userProvidedBadType, arguments);
135 } 291 }
136 292
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
137 // Try to construct the type from the element. 305 // Try to construct the type from the element.
138 if (element == null) { 306 if (type != 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) {
139 type = reportFailureAndCreateType( 314 type = reportFailureAndCreateType(
140 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}); 315 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName});
141 } else if (element.isAmbiguous) { 316 } else if (element.isAmbiguous) {
142 AmbiguousElement ambiguous = element; 317 AmbiguousElement ambiguous = element;
143 type = reportFailureAndCreateType( 318 type = reportFailureAndCreateType(
144 ambiguous.messageKind, ambiguous.messageArguments, 319 ambiguous.messageKind, ambiguous.messageArguments,
145 infos: ambiguous.computeInfos( 320 infos: ambiguous.computeInfos(
146 registry.mapping.analyzedElement, reporter)); 321 registry.mapping.analyzedElement, reporter));
147 ; 322 ;
148 } else if (element.isMalformed) { 323 } else if (element.isMalformed) {
(...skipping 14 matching lines...) Expand all
163 return type; 338 return type;
164 } else { 339 } else {
165 bool addTypeVariableBoundsCheck = false; 340 bool addTypeVariableBoundsCheck = false;
166 if (element.isClass) { 341 if (element.isClass) {
167 ClassElement cls = element; 342 ClassElement cls = element;
168 // TODO(johnniwinther): [ensureClassWillBeResolvedInternal] should imply 343 // TODO(johnniwinther): [ensureClassWillBeResolvedInternal] should imply
169 // [computeType]. 344 // [computeType].
170 resolver.ensureClassWillBeResolvedInternal(cls); 345 resolver.ensureClassWillBeResolvedInternal(cls);
171 cls.computeType(resolution); 346 cls.computeType(resolution);
172 List<ResolutionDartType> arguments = <ResolutionDartType>[]; 347 List<ResolutionDartType> arguments = <ResolutionDartType>[];
173 bool hasTypeArgumentMismatch = 348 bool hasTypeArgumentMismatch = resolveTypeArguments(
174 resolveTypeArguments(visitor, node, cls.typeVariables, arguments); 349 visitor, node, cls.typeVariables, arguments,
350 visibleTypeParameterNames);
175 if (hasTypeArgumentMismatch) { 351 if (hasTypeArgumentMismatch) {
176 type = new BadInterfaceType( 352 type = new BadInterfaceType(
177 cls.declaration, 353 cls.declaration,
178 new ResolutionInterfaceType.forUserProvidedBadType( 354 new ResolutionInterfaceType.forUserProvidedBadType(
179 cls.declaration, arguments)); 355 cls.declaration, arguments));
180 } else { 356 } else {
181 if (arguments.isEmpty) { 357 if (arguments.isEmpty) {
182 type = cls.rawType; 358 type = cls.rawType;
183 } else { 359 } else {
184 type = new ResolutionInterfaceType( 360 type = new ResolutionInterfaceType(
185 cls.declaration, arguments.toList(growable: false)); 361 cls.declaration, arguments.toList(growable: false));
186 addTypeVariableBoundsCheck = 362 addTypeVariableBoundsCheck =
187 arguments.any((ResolutionDartType type) => !type.isDynamic); 363 arguments.any((ResolutionDartType type) => !type.isDynamic);
188 } 364 }
189 } 365 }
190 } else if (element.isTypedef) { 366 } else if (element.isTypedef) {
191 TypedefElement typdef = element; 367 TypedefElement typdef = element;
192 // TODO(johnniwinther): [ensureResolved] should imply [computeType]. 368 // TODO(johnniwinther): [ensureResolved] should imply [computeType].
193 typdef.ensureResolved(resolution); 369 typdef.ensureResolved(resolution);
194 typdef.computeType(resolution); 370 typdef.computeType(resolution);
195 List<ResolutionDartType> arguments = <ResolutionDartType>[]; 371 List<ResolutionDartType> arguments = <ResolutionDartType>[];
196 bool hasTypeArgumentMismatch = resolveTypeArguments( 372 bool hasTypeArgumentMismatch = resolveTypeArguments(
197 visitor, node, typdef.typeVariables, arguments); 373 visitor, node, typdef.typeVariables, arguments,
374 visibleTypeParameterNames);
198 if (hasTypeArgumentMismatch) { 375 if (hasTypeArgumentMismatch) {
199 type = new BadTypedefType( 376 type = new BadTypedefType(
200 typdef, 377 typdef,
201 new ResolutionTypedefType.forUserProvidedBadType( 378 new ResolutionTypedefType.forUserProvidedBadType(
202 typdef, arguments)); 379 typdef, arguments));
203 } else { 380 } else {
204 if (arguments.isEmpty) { 381 if (arguments.isEmpty) {
205 type = typdef.rawType; 382 type = typdef.rawType;
206 } else { 383 } else {
207 type = new ResolutionTypedefType( 384 type = new ResolutionTypedefType(
(...skipping 26 matching lines...) Expand all
234 if (addTypeVariableBoundsCheck) { 411 if (addTypeVariableBoundsCheck) {
235 visitor.addDeferredAction(visitor.enclosingElement, 412 visitor.addDeferredAction(visitor.enclosingElement,
236 () => checkTypeVariableBounds(node, type)); 413 () => checkTypeVariableBounds(node, type));
237 } 414 }
238 } 415 }
239 registry.useType(node, type); 416 registry.useType(node, type);
240 return type; 417 return type;
241 } 418 }
242 419
243 /// Checks the type arguments of [type] against the type variable bounds. 420 /// Checks the type arguments of [type] against the type variable bounds.
244 void checkTypeVariableBounds(TypeAnnotation node, GenericType type) { 421 void checkTypeVariableBounds(NominalTypeAnnotation node, GenericType type) {
245 void checkTypeVariableBound(_, ResolutionDartType typeArgument, 422 void checkTypeVariableBound(_, ResolutionDartType typeArgument,
246 ResolutionTypeVariableType typeVariable, ResolutionDartType bound) { 423 ResolutionTypeVariableType typeVariable, ResolutionDartType bound) {
247 if (!types.isSubtype(typeArgument, bound)) { 424 if (!types.isSubtype(typeArgument, bound)) {
248 reporter.reportWarningMessage( 425 reporter.reportWarningMessage(
249 node, MessageKind.INVALID_TYPE_VARIABLE_BOUND, { 426 node, MessageKind.INVALID_TYPE_VARIABLE_BOUND, {
250 'typeVariable': typeVariable, 427 'typeVariable': typeVariable,
251 'bound': bound, 428 'bound': bound,
252 'typeArgument': typeArgument, 429 'typeArgument': typeArgument,
253 'thisType': type.element.thisType 430 'thisType': type.element.thisType
254 }); 431 });
255 } 432 }
256 } 433 }
257 434
258 types.checkTypeVariableBounds(type, checkTypeVariableBound); 435 types.checkTypeVariableBounds(type, checkTypeVariableBound);
259 } 436 }
260 437
261 /** 438 /**
262 * Resolves the type arguments of [node] and adds these to [arguments]. 439 * Resolves the type arguments of [node] and adds these to [arguments].
263 * 440 *
264 * Returns [: true :] if the number of type arguments did not match the 441 * Returns [: true :] if the number of type arguments did not match the
265 * number of type variables. 442 * number of type variables.
266 */ 443 */
267 bool resolveTypeArguments( 444 bool resolveTypeArguments(
268 MappingVisitor visitor, 445 MappingVisitor visitor,
269 TypeAnnotation node, 446 NominalTypeAnnotation node,
270 List<ResolutionDartType> typeVariables, 447 List<ResolutionDartType> typeVariables,
271 List<ResolutionDartType> arguments) { 448 List<ResolutionDartType> arguments,
449 List<List<String>> visibleTypeParameterNames) {
272 if (node.typeArguments == null) { 450 if (node.typeArguments == null) {
273 return false; 451 return false;
274 } 452 }
275 int expectedVariables = typeVariables.length; 453 int expectedVariables = typeVariables.length;
276 int index = 0; 454 int index = 0;
277 bool typeArgumentCountMismatch = false; 455 bool typeArgumentCountMismatch = false;
278 for (Link<Node> typeArguments = node.typeArguments.nodes; 456 for (Link<Node> typeArguments = node.typeArguments.nodes;
279 !typeArguments.isEmpty; 457 !typeArguments.isEmpty;
280 typeArguments = typeArguments.tail, index++) { 458 typeArguments = typeArguments.tail, index++) {
281 if (index > expectedVariables - 1) { 459 if (index > expectedVariables - 1) {
282 reporter.reportWarningMessage( 460 reporter.reportWarningMessage(
283 typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); 461 typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT);
284 typeArgumentCountMismatch = true; 462 typeArgumentCountMismatch = true;
285 } 463 }
286 ResolutionDartType argType = 464 ResolutionDartType argType = _resolveTypeAnnotation(
287 resolveTypeAnnotation(visitor, typeArguments.head); 465 visitor, typeArguments.head, visibleTypeParameterNames);
288 // TODO(karlklose): rewrite to not modify [arguments]. 466 // TODO(karlklose): rewrite to not modify [arguments].
289 arguments.add(argType); 467 arguments.add(argType);
290 } 468 }
291 if (index < expectedVariables) { 469 if (index < expectedVariables) {
292 reporter.reportWarningMessage( 470 reporter.reportWarningMessage(
293 node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); 471 node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT);
294 typeArgumentCountMismatch = true; 472 typeArgumentCountMismatch = true;
295 } 473 }
296 return typeArgumentCountMismatch; 474 return typeArgumentCountMismatch;
297 } 475 }
298 } 476 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698