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 analyzer.src.generated.resolver; | 5 library analyzer.src.generated.resolver; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
(...skipping 4300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4311 * Look for a single contextual type attached to [node], and returns the type | 4311 * Look for a single contextual type attached to [node], and returns the type |
4312 * if found, otherwise null. | 4312 * if found, otherwise null. |
4313 * | 4313 * |
4314 * If [node] has a contextual union type like `T | Future<T>` this will | 4314 * If [node] has a contextual union type like `T | Future<T>` this will |
4315 * simplify it to only return `T`. If the caller can handle a union type, | 4315 * simplify it to only return `T`. If the caller can handle a union type, |
4316 * [getContext] should be used instead. | 4316 * [getContext] should be used instead. |
4317 */ | 4317 */ |
4318 static DartType getType(AstNode node) { | 4318 static DartType getType(AstNode node) { |
4319 DartType t = getContext(node); | 4319 DartType t = getContext(node); |
4320 if (t is FutureUnionType) { | 4320 if (t is FutureUnionType) { |
4321 return t.type; | 4321 return _substituteForUnknown(t.type); |
4322 } | 4322 } |
4323 return t; | 4323 return _substituteForUnknown(t); |
4324 } | 4324 } |
4325 | 4325 |
4326 /** | 4326 /** |
4327 * Like [getContext] but expands a union type into a list of types. | 4327 * Like [getContext] but expands a union type into a list of types. |
4328 */ | 4328 */ |
4329 static Iterable<DartType> getTypes(AstNode node) { | 4329 static Iterable<DartType> getTypes(AstNode node) { |
4330 DartType t = getContext(node); | 4330 DartType t = getContext(node); |
4331 if (t == null) { | 4331 if (t == null) { |
4332 return DartType.EMPTY_LIST; | 4332 return DartType.EMPTY_LIST; |
4333 } | 4333 } |
4334 if (t is FutureUnionType) { | 4334 Iterable<DartType> result = t is FutureUnionType ? t.types : [t]; |
4335 return t.types; | 4335 return result.map(_substituteForUnknown).where((t) => t != null); |
4336 } | 4336 } |
4337 return <DartType>[t]; | 4337 |
4338 static DartType _substituteForUnknown(DartType t) { | |
4339 if (t == null) return null; | |
4340 // Since the type is being used for downwards inference, the expression | |
4341 // type E must be a subtype of the context type T, i.e. T is an upper bound. | |
4342 // | |
4343 // TODO(jmesserly): our downwards inference code is not designed to handle | |
4344 // the bottom type, so we need to prevent it from resulting here. | |
4345 // Instead use `dynamic`. | |
4346 //return UnknownInferredType.upperBoundForType(t); | |
vsm
2016/11/30 04:05:32
Did you mean to keep this commented line?
Jennifer Messerly
2016/11/30 04:35:04
Yeah, I can remove it. I kinda put it there to go
| |
4347 return UnknownInferredType.substituteDynamic(t); | |
4338 } | 4348 } |
4339 | 4349 |
4340 /** | 4350 /** |
4341 * Attach contextual type information [type] to [node] for use during | 4351 * Attach contextual type information [type] to [node] for use during |
4342 * inference. | 4352 * inference. |
4343 */ | 4353 */ |
4344 static void setType(AstNode node, DartType type) { | 4354 static void setType(AstNode node, DartType type) { |
4345 if (type == null || type.isDynamic) { | 4355 if (type == null || type.isDynamic) { |
4346 clearType(node); | 4356 clearType(node); |
4347 } else { | 4357 } else { |
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5391 assert(parent is PartOfDirective); | 5401 assert(parent is PartOfDirective); |
5392 } else { | 5402 } else { |
5393 elementAnnotationImpl.annotationAst = | 5403 elementAnnotationImpl.annotationAst = |
5394 new ConstantAstCloner().cloneNode(node); | 5404 new ConstantAstCloner().cloneNode(node); |
5395 } | 5405 } |
5396 return null; | 5406 return null; |
5397 } | 5407 } |
5398 | 5408 |
5399 @override | 5409 @override |
5400 Object visitArgumentList(ArgumentList node) { | 5410 Object visitArgumentList(ArgumentList node) { |
5401 DartType callerType = InferenceContext.getType(node); | 5411 DartType callerType = InferenceContext.getContext(node); |
5402 if (callerType is FunctionType) { | 5412 if (callerType is FunctionType) { |
5403 Map<String, DartType> namedParameterTypes = | 5413 Map<String, DartType> namedParameterTypes = |
5404 callerType.namedParameterTypes; | 5414 callerType.namedParameterTypes; |
5405 List<DartType> normalParameterTypes = callerType.normalParameterTypes; | 5415 List<DartType> normalParameterTypes = callerType.normalParameterTypes; |
5406 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes; | 5416 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes; |
5407 int normalCount = normalParameterTypes.length; | 5417 int normalCount = normalParameterTypes.length; |
5408 int optionalCount = optionalParameterTypes.length; | 5418 int optionalCount = optionalParameterTypes.length; |
5409 | 5419 |
5410 NodeList<Expression> arguments = node.arguments; | 5420 NodeList<Expression> arguments = node.arguments; |
5411 Iterable<Expression> positional = | 5421 Iterable<Expression> positional = |
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6148 | 6158 |
6149 @override | 6159 @override |
6150 Object visitInstanceCreationExpression(InstanceCreationExpression node) { | 6160 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
6151 TypeName classTypeName = node.constructorName.type; | 6161 TypeName classTypeName = node.constructorName.type; |
6152 // TODO(leafp): Currently, we may re-infer types here, since we | 6162 // TODO(leafp): Currently, we may re-infer types here, since we |
6153 // sometimes resolve multiple times. We should really check that we | 6163 // sometimes resolve multiple times. We should really check that we |
6154 // have not already inferred something. However, the obvious ways to | 6164 // have not already inferred something. However, the obvious ways to |
6155 // check this don't work, since we may have been instantiated | 6165 // check this don't work, since we may have been instantiated |
6156 // to bounds in an earlier phase, and we *do* want to do inference | 6166 // to bounds in an earlier phase, and we *do* want to do inference |
6157 // in that case. | 6167 // in that case. |
6158 if (classTypeName.typeArguments == null) { | 6168 |
6169 if (strongMode && classTypeName.typeArguments == null) { | |
6159 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first | 6170 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first |
6160 // valid instantiation `new C<Ti>`, if it exists. | 6171 // valid instantiation `new C<Ti>`, if it exists. |
6161 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>` | 6172 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>` |
6162 // will become a valid possibility. Right now the only allowed union is | 6173 // will become a valid possibility. Right now the only allowed union is |
6163 // `T | Future<T>` so we can take a simple approach. | 6174 // `T | Future<T>` so we can take a simple approach. |
6164 for (var contextType in InferenceContext.getTypes(node)) { | 6175 |
6176 TypeDefiningElement classElement = classTypeName.type?.element; | |
6177 DartType rawType = classElement?.type; | |
Leaf
2016/11/30 05:24:29
Comment here, just for the reader, maybe? Here's
Jennifer Messerly
2016/11/30 21:19:28
sure :) to be honest I don't understand this code
| |
6178 Iterable<DartType> contextTypes = InferenceContext.getTypes(node); | |
6179 for (var contextType in contextTypes) { | |
6165 if (contextType is InterfaceType && | 6180 if (contextType is InterfaceType && |
6166 contextType.typeArguments != null && | 6181 contextType.typeArguments != null && |
6167 contextType.typeArguments.isNotEmpty) { | 6182 contextType.typeArguments.isNotEmpty) { |
6168 // TODO(jmesserly): for generic methods we use the | 6183 // TODO(jmesserly): for generic methods we use the |
6169 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to | 6184 // StrongTypeSystemImpl.inferGenericFunctionOrType, which appears to |
6170 // be a tad more powerful than matchTypes. | 6185 // be a tad more powerful than matchTypes. |
6171 // | 6186 // |
6172 // For example it can infer this case: | 6187 // For example it can infer this case: |
6173 // | 6188 // |
6174 // class E<S, T> extends A<C<S>, T> { ... } | 6189 // class E<S, T> extends A<C<S>, T> { ... } |
6175 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello"); | 6190 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello"); |
6176 // | 6191 // |
6177 // See _inferArgumentTypesFromContext in this file for use of it. | 6192 // See _inferArgumentTypesFromContext in this file for use of it. |
6178 List<DartType> targs = | 6193 List<DartType> targs = |
6179 inferenceContext.matchTypes(classTypeName.type, contextType); | 6194 inferenceContext.matchTypes(classTypeName.type, contextType); |
Leaf
2016/11/30 05:24:29
Aargh... I'm lost again. What's the difference be
Jennifer Messerly
2016/11/30 21:19:28
I would but.... I don't understand this code eithe
| |
6180 if (targs != null && targs.any((t) => !t.isDynamic)) { | 6195 if (targs != null && |
6181 ClassElement classElement = classTypeName.type.element; | 6196 targs.any((t) => !t.isDynamic) && |
6182 InterfaceType rawType = classElement.type; | 6197 rawType is InterfaceType) { |
Leaf
2016/11/30 05:24:29
Can matchTypes return ? for one of the targs? If
Jennifer Messerly
2016/11/30 21:19:28
it shouldn't be able to, because` InferenceContext
| |
6183 InterfaceType fullType = | 6198 InterfaceType fullType = |
6184 rawType.substitute2(targs, rawType.typeArguments); | 6199 rawType.substitute2(targs, rawType.typeArguments); |
6185 // The element resolver uses the type on the constructor name, so | 6200 // The element resolver uses the type on the constructor name, so |
6186 // infer it first | 6201 // infer it first |
6187 typeAnalyzer.inferConstructorName(node.constructorName, fullType); | 6202 typeAnalyzer.inferConstructorName(node.constructorName, fullType); |
6188 break; | 6203 break; |
6189 } | 6204 } |
6190 } | 6205 } |
6191 } | 6206 } |
6207 if (contextTypes.isEmpty && | |
Leaf
2016/11/30 05:24:29
//comment
I think this is instance failure? In w
Jennifer Messerly
2016/11/30 21:19:28
I think the idea was: for downwards inference, e.g
Leaf
2016/12/01 04:36:27
Ok, I think this makes sense then. I didn't get t
Jennifer Messerly
2017/01/06 22:31:45
yeah, I think so. Maybe I should take a shot at un
Jennifer Messerly
2017/01/11 02:24:38
Hello again! I've now removed matchTypes and this
| |
6208 rawType is InterfaceType && | |
6209 rawType.typeArguments.isNotEmpty) { | |
6210 node.constructorName.type.type = rawType.substitute2( | |
6211 new List.filled( | |
6212 rawType.typeArguments.length, UnknownInferredType.instance), | |
6213 rawType.typeArguments); | |
6214 } | |
6192 } | 6215 } |
6193 node.constructorName?.accept(this); | 6216 node.constructorName?.accept(this); |
6194 FunctionType constructorType = node.constructorName.staticElement?.type; | 6217 ConstructorElement constructor = node.constructorName.staticElement; |
6195 if (constructorType != null) { | 6218 FunctionType constructorType = constructor?.type; |
6219 if (strongMode && constructorType != null) { | |
6196 InferenceContext.setType(node.argumentList, constructorType); | 6220 InferenceContext.setType(node.argumentList, constructorType); |
6197 } | 6221 } |
6198 node.argumentList?.accept(this); | 6222 node.argumentList?.accept(this); |
6199 node.accept(elementResolver); | 6223 node.accept(elementResolver); |
6200 node.accept(typeAnalyzer); | 6224 node.accept(typeAnalyzer); |
6201 return null; | 6225 return null; |
6202 } | 6226 } |
6203 | 6227 |
6204 @override | 6228 @override |
6205 Object visitLabel(Label node) => null; | 6229 Object visitLabel(Label node) => null; |
6206 | 6230 |
6207 @override | 6231 @override |
6208 Object visitLibraryIdentifier(LibraryIdentifier node) => null; | 6232 Object visitLibraryIdentifier(LibraryIdentifier node) => null; |
6209 | 6233 |
6210 @override | 6234 @override |
6211 Object visitListLiteral(ListLiteral node) { | 6235 Object visitListLiteral(ListLiteral node) { |
6212 DartType contextType = InferenceContext.getType(node); | 6236 DartType contextType = InferenceContext.getContext(node); |
6237 if (contextType is FutureUnionType) { | |
Leaf
2016/11/30 05:24:29
Consider making this pattern a method on Inference
Jennifer Messerly
2016/11/30 21:19:28
great idea, done!
| |
6238 contextType = (contextType as FutureUnionType).type; | |
6239 } | |
6213 List<DartType> targs = null; | 6240 List<DartType> targs = null; |
6214 if (node.typeArguments != null) { | 6241 if (node.typeArguments != null) { |
6215 targs = node.typeArguments.arguments.map((t) => t.type).toList(); | 6242 targs = node.typeArguments.arguments.map((t) => t.type).toList(); |
6216 } else if (contextType is InterfaceType) { | 6243 } else if (contextType is InterfaceType) { |
6217 InterfaceType listD = | 6244 InterfaceType listD = |
6218 typeProvider.listType.instantiate([typeProvider.dynamicType]); | 6245 typeProvider.listType.instantiate([typeProvider.dynamicType]); |
6219 targs = inferenceContext.matchTypes(listD, contextType); | 6246 targs = inferenceContext.matchTypes(listD, contextType); |
6220 } | 6247 } |
6221 if (targs != null && targs.length == 1 && !targs[0].isDynamic) { | 6248 if (targs != null && targs.length == 1 && !targs[0].isDynamic) { |
6222 DartType eType = targs[0]; | 6249 DartType eType = targs[0]; |
6223 InterfaceType listT = typeProvider.listType.instantiate([eType]); | 6250 InterfaceType listT = typeProvider.listType.instantiate([eType]); |
6224 for (Expression child in node.elements) { | 6251 for (Expression child in node.elements) { |
6225 InferenceContext.setType(child, eType); | 6252 InferenceContext.setType(child, eType); |
6226 } | 6253 } |
6227 InferenceContext.setType(node, listT); | 6254 InferenceContext.setType(node, listT); |
6228 } else { | 6255 } else { |
6229 InferenceContext.clearType(node); | 6256 InferenceContext.clearType(node); |
6230 } | 6257 } |
6231 super.visitListLiteral(node); | 6258 super.visitListLiteral(node); |
6232 return null; | 6259 return null; |
6233 } | 6260 } |
6234 | 6261 |
6235 @override | 6262 @override |
6236 Object visitMapLiteral(MapLiteral node) { | 6263 Object visitMapLiteral(MapLiteral node) { |
6237 DartType contextType = InferenceContext.getType(node); | 6264 DartType contextType = InferenceContext.getContext(node); |
6265 if (contextType is FutureUnionType) { | |
6266 contextType = (contextType as FutureUnionType).type; | |
6267 } | |
6238 List<DartType> targs = null; | 6268 List<DartType> targs = null; |
6239 if (node.typeArguments != null) { | 6269 if (node.typeArguments != null) { |
6240 targs = node.typeArguments.arguments.map((t) => t.type).toList(); | 6270 targs = node.typeArguments.arguments.map((t) => t.type).toList(); |
6241 } else if (contextType is InterfaceType) { | 6271 } else if (contextType is InterfaceType) { |
6242 InterfaceType mapD = typeProvider.mapType | 6272 InterfaceType mapD = typeProvider.mapType |
6243 .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]); | 6273 .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]); |
6244 targs = inferenceContext.matchTypes(mapD, contextType); | 6274 targs = inferenceContext.matchTypes(mapD, contextType); |
6245 } | 6275 } |
6246 if (targs != null && targs.length == 2 && targs.any((t) => !t.isDynamic)) { | 6276 if (targs != null && targs.length == 2 && targs.any((t) => !t.isDynamic)) { |
6247 DartType kType = targs[0]; | 6277 DartType kType = targs[0]; |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6679 // Use propagated type inference for lambdas if not in strong mode. | 6709 // Use propagated type inference for lambdas if not in strong mode. |
6680 _inferFunctionExpressionsParametersTypes(node.argumentList); | 6710 _inferFunctionExpressionsParametersTypes(node.argumentList); |
6681 return; | 6711 return; |
6682 } | 6712 } |
6683 | 6713 |
6684 DartType contextType = node.staticInvokeType; | 6714 DartType contextType = node.staticInvokeType; |
6685 if (contextType is FunctionType) { | 6715 if (contextType is FunctionType) { |
6686 DartType originalType = node.function.staticType; | 6716 DartType originalType = node.function.staticType; |
6687 DartType returnContextType = InferenceContext.getContext(node); | 6717 DartType returnContextType = InferenceContext.getContext(node); |
6688 TypeSystem ts = typeSystem; | 6718 TypeSystem ts = typeSystem; |
6689 if (returnContextType != null && | 6719 if (node.typeArguments == null && |
6690 node.typeArguments == null && | |
6691 originalType is FunctionType && | 6720 originalType is FunctionType && |
6692 originalType.typeFormals.isNotEmpty && | 6721 originalType.typeFormals.isNotEmpty && |
6693 ts is StrongTypeSystemImpl) { | 6722 ts is StrongTypeSystemImpl) { |
6694 contextType = ts.inferGenericFunctionCall( | 6723 contextType = ts.inferGenericFunctionOrType/*<FunctionType>*/( |
6695 typeProvider, | 6724 typeProvider, |
6696 originalType, | 6725 originalType, |
6697 DartType.EMPTY_LIST, | 6726 ParameterElement.EMPTY_LIST, |
6698 DartType.EMPTY_LIST, | 6727 DartType.EMPTY_LIST, |
6699 originalType.returnType, | 6728 originalType.returnType, |
6700 returnContextType); | 6729 returnContextType, |
6730 downwards: true); | |
6701 } | 6731 } |
6702 | 6732 |
6703 InferenceContext.setType(node.argumentList, contextType); | 6733 InferenceContext.setType(node.argumentList, contextType); |
6704 } | 6734 } |
6705 } | 6735 } |
6706 | 6736 |
6707 void _inferFormalParameterList(FormalParameterList node, DartType type) { | 6737 void _inferFormalParameterList(FormalParameterList node, DartType type) { |
6708 if (typeAnalyzer.inferFormalParameterList(node, type)) { | 6738 if (typeAnalyzer.inferFormalParameterList(node, type)) { |
6709 // TODO(leafp): This gets dropped on the floor if we're in the field | 6739 // TODO(leafp): This gets dropped on the floor if we're in the field |
6710 // inference task. We should probably keep these infos. | 6740 // inference task. We should probably keep these infos. |
(...skipping 4051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10762 return null; | 10792 return null; |
10763 } | 10793 } |
10764 if (identical(node.staticElement, variable)) { | 10794 if (identical(node.staticElement, variable)) { |
10765 if (node.inSetterContext()) { | 10795 if (node.inSetterContext()) { |
10766 result = true; | 10796 result = true; |
10767 } | 10797 } |
10768 } | 10798 } |
10769 return null; | 10799 return null; |
10770 } | 10800 } |
10771 } | 10801 } |
OLD | NEW |