blob: 3713e551eea30d80776d0ad1a0f18d57ad68e1b0 [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/fasta/resolution_applier.dart';
import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/type_algebra.dart';
class ResolutionData<Type, Declaration, Reference, PrefixInfo> {
final List<Type> argumentTypes;
final Reference combiner;
final Declaration declaration;
final Type inferredType;
final Type invokeType;
final bool isExplicitCall;
final bool isImplicitCall;
final bool isWriteReference;
final Type literalType;
final PrefixInfo prefixInfo;
final Reference reference;
final Type writeContext;
ResolutionData(
{this.argumentTypes,
this.combiner,
this.declaration,
this.inferredType,
this.invokeType,
this.isExplicitCall = false,
this.isImplicitCall = false,
this.isWriteReference = false,
this.literalType,
this.prefixInfo,
this.reference,
this.writeContext});
}
/// Type inference listener that records inferred types for later use by
/// [ResolutionApplier].
class ResolutionStorer extends _ResolutionStorer<int, int, Node, int> {
ResolutionStorer(Map<int, ResolutionData<DartType, int, Node, int>> data)
: super(data);
}
/// Implementation of [ResolutionStorer], with types parameterized to avoid
/// accidentally peeking into kernel internals.
///
/// TODO(paulberry): when the time is right, fuse this with [ResolutionStorer].
class _ResolutionStorer<Location, Declaration, Reference, PrefixInfo>
implements
TypeInferenceListener<Location, Declaration, Reference, PrefixInfo> {
final Map<Location,
ResolutionData<DartType, Declaration, Reference, PrefixInfo>> _data;
_ResolutionStorer(this._data);
void _store(Location location,
{List<DartType> argumentTypes,
Reference combiner,
Declaration declaration,
DartType inferredType,
DartType invokeType,
bool isExplicitCall = false,
bool isImplicitCall = false,
bool isWriteReference = false,
DartType literalType,
PrefixInfo prefixInfo,
Reference reference,
bool replace = false,
DartType writeContext}) {
if (!replace && _data.containsKey(location)) {
throw new StateError('Data already stored for offset $location');
}
_data[location] = new ResolutionData(
argumentTypes: argumentTypes,
combiner: combiner,
declaration: declaration,
inferredType: inferredType,
invokeType: invokeType,
isExplicitCall: isExplicitCall,
isImplicitCall: isImplicitCall,
isWriteReference: isWriteReference,
literalType: literalType,
prefixInfo: prefixInfo,
reference: reference,
writeContext: writeContext);
}
void _unstore(Location location) {
_data.remove(location) == null;
}
@override
void asExpression(
ExpressionJudgment judgment, Location location, DartType inferredType) {
_store(location, literalType: inferredType, inferredType: inferredType);
}
@override
void assertInitializer(InitializerJudgment judgment, Location location) {}
@override
void assertStatement(StatementJudgment judgment, Location location) {}
@override
void awaitExpression(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("awaitExpression", location, inferredType);
@override
void block(StatementJudgment judgment, Location location) {}
@override
void boolLiteral(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("boolLiteral", location, inferredType);
@override
void breakStatement(StatementJudgment judgment, Location location) {}
@override
void cascadeExpression(
ExpressionJudgment judgment, Location location, DartType inferredType) {
// Overridden so that the type of the expression will not be recorded. We
// don't need to record the type because the type is always the same as the
// type of the target, and we don't have the appropriate offset so we can't
// correctly apply the type even if we recorded it.
}
@override
void catchStatement(
Catch judgment,
Location location,
DartType guardType,
Location exceptionLocation,
DartType exceptionType,
Location stackTraceLocation,
DartType stackTraceType) {
_store(location, literalType: guardType);
if (exceptionLocation != null) {
_store(exceptionLocation, literalType: exceptionType);
}
if (stackTraceLocation != null) {
_store(stackTraceLocation, literalType: stackTraceType);
}
}
@override
void conditionalExpression(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("conditionalExpression", location, inferredType);
@override
void constructorInvocation(ExpressionJudgment judgment, Location location,
Reference expressionTarget, DartType inferredType) {
// A class reference may have already been stored at this location by
// storeClassReference. We want to replace it with a constructor
// reference.
_unstore(location);
_store(location, inferredType: inferredType, reference: expressionTarget);
}
@override
void continueSwitchStatement(StatementJudgment judgment, Location location) {}
@override
void deferredCheck(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("deferredCheck", location, inferredType);
@override
void doStatement(StatementJudgment judgment, Location location) {}
@override
void doubleLiteral(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("doubleLiteral", location, inferredType);
@override
void expressionStatement(StatementJudgment judgment, Location location) {}
@override
void fieldInitializer(InitializerJudgment judgment, Location location,
Reference initializerField) {
_store(location, reference: initializerField);
}
@override
void forInStatement(
StatementJudgment judgment,
Location location,
Location variableLocation,
DartType variableType,
Location writeLocation,
DartType writeType,
Declaration writeVariable,
Reference writeTarget) {
if (variableLocation != null) {
_store(variableLocation, inferredType: variableType);
} else {
if (writeVariable != null) {
_store(writeLocation,
declaration: writeVariable, inferredType: writeType);
} else {
_store(writeLocation,
reference: writeTarget,
isWriteReference: true,
writeContext: writeType);
}
}
}
@override
void forStatement(StatementJudgment judgment, Location location) {}
@override
void functionDeclaration(StatementJudgment judgment, Location location,
FunctionType inferredType) {
_store(location, inferredType: inferredType);
}
@override
void functionExpression(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("functionExpression", location, inferredType);
void genericExpression(
String expressionType, Location location, DartType inferredType) {
_store(location, inferredType: inferredType);
}
@override
void ifNull(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression('ifNull', location, inferredType);
@override
void ifStatement(StatementJudgment judgment, Location location) {}
@override
void intLiteral(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("intLiteral", location, inferredType);
@override
void invalidInitializer(InitializerJudgment judgment, Location location) {}
@override
void labeledStatement(StatementJudgment judgment, Location location) {}
@override
void listLiteral(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("listLiteral", location, inferredType);
@override
void logicalExpression(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("logicalExpression", location, inferredType);
@override
void mapLiteral(ExpressionJudgment judgment, Location location,
DartType typeContext) =>
genericExpression("mapLiteral", location, typeContext);
@override
void namedFunctionExpression(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("namedFunctionExpression", location, inferredType);
@override
void not(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("not", location, inferredType);
@override
void nullLiteral(ExpressionJudgment judgment, Location location,
bool isSynthetic, DartType inferredType) {
if (isSynthetic) return null;
genericExpression("nullLiteral", location, inferredType);
}
@override
void indexAssign(ExpressionJudgment judgment, Location location,
Reference writeMember, Reference combiner, DartType inferredType) {
_store(location,
reference: writeMember, inferredType: inferredType, combiner: combiner);
}
@override
void isExpression(ExpressionJudgment judgment, Location location,
DartType testedType, DartType inferredType) {
_store(location, literalType: testedType, inferredType: inferredType);
}
void isNotExpression(ExpressionJudgment judgment, Location location,
DartType type, DartType inferredType) {
_store(location, literalType: type, inferredType: inferredType);
}
@override
void methodInvocation(
ExpressionJudgment judgment,
Location resultOffset,
List<DartType> argumentsTypes,
bool isImplicitCall,
Reference interfaceMember,
FunctionType calleeType,
Substitution substitution,
DartType inferredType) {
FunctionType invokeType = substitution == null
? calleeType
: substitution.substituteType(calleeType.withoutTypeParameters);
_store(resultOffset,
inferredType: inferredType,
argumentTypes: argumentsTypes,
invokeType: invokeType,
isImplicitCall: isImplicitCall,
reference: interfaceMember);
}
@override
void methodInvocationCall(
ExpressionJudgment judgment,
Location resultOffset,
List<DartType> argumentsTypes,
bool isImplicitCall,
FunctionType calleeType,
Substitution substitution,
DartType inferredType) {
FunctionType invokeType = substitution == null
? calleeType
: substitution.substituteType(calleeType.withoutTypeParameters);
_store(resultOffset,
inferredType: inferredType,
argumentTypes: argumentsTypes,
invokeType: invokeType,
isImplicitCall: isImplicitCall);
}
@override
void propertyAssign(
ExpressionJudgment judgment,
Location location,
Reference writeMember,
DartType writeContext,
Reference combiner,
DartType inferredType) {
_store(location,
isWriteReference: true,
reference: writeMember,
writeContext: writeContext,
combiner: combiner,
inferredType: inferredType);
}
@override
void propertySet(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("propertySet", location, inferredType);
@override
void propertyGet(ExpressionJudgment judgment, Location location,
Reference member, DartType inferredType) {
_store(location, reference: member, inferredType: inferredType);
}
@override
void propertyGetCall(
ExpressionJudgment judgment, Location location, DartType inferredType) {
_store(location, isExplicitCall: true);
}
@override
void redirectingInitializer(InitializerJudgment judgment, Location location,
Reference initializerTarget) {
_store(location, reference: initializerTarget);
}
@override
void rethrow_(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression('rethrow', location, inferredType);
@override
void returnStatement(StatementJudgment judgment, Location location) {}
@override
void staticAssign(
ExpressionJudgment judgment,
Location location,
Reference writeMember,
DartType writeContext,
Reference combiner,
DartType inferredType) {
_store(location,
reference: writeMember,
isWriteReference: true,
writeContext: writeContext,
combiner: combiner,
inferredType: inferredType);
}
@override
void staticGet(ExpressionJudgment judgment, Location location,
Reference expressionTarget, DartType inferredType) {
_store(location, reference: expressionTarget, inferredType: inferredType);
}
@override
void staticInvocation(
ExpressionJudgment judgment,
Location location,
Reference expressionTarget,
List<DartType> expressionArgumentsTypes,
FunctionType calleeType,
Substitution substitution,
DartType inferredType) {
FunctionType invokeType = substitution == null
? calleeType
: substitution.substituteType(calleeType.withoutTypeParameters);
_store(location,
invokeType: invokeType,
argumentTypes: expressionArgumentsTypes,
reference: expressionTarget,
inferredType: inferredType);
}
@override
void stringConcatenation(
ExpressionJudgment judgment, Location location, DartType inferredType) {
// We don't need the type - we already know that it is String.
// Moreover, the file offset for StringConcatenation is `-1`.
}
@override
void stringLiteral(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("StringLiteral", location, inferredType);
@override
void superInitializer(InitializerJudgment judgment, Location location) {}
@override
void switchStatement(StatementJudgment judgment, Location location) {}
@override
void symbolLiteral(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("symbolLiteral", location, inferredType);
@override
void thisExpression(
ExpressionJudgment judgment, Location location, DartType inferredType) {}
@override
void throw_(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression('throw', location, inferredType);
@override
void tryCatch(StatementJudgment judgment, Location location) {}
@override
void tryFinally(StatementJudgment judgment, Location location) {}
void typeLiteral(ExpressionJudgment judgment, Location location,
Reference expressionType, DartType inferredType) {
_store(location, reference: expressionType, inferredType: inferredType);
}
@override
void variableAssign(
ExpressionJudgment judgment,
Location location,
DartType writeContext,
Declaration writeVariable,
Reference combiner,
DartType inferredType) {
_store(location,
declaration: writeVariable,
isWriteReference: true,
writeContext: writeContext,
combiner: combiner,
inferredType: inferredType);
}
@override
void variableDeclaration(StatementJudgment judgment, Location location,
DartType statementType, DartType inferredType) {
_store(location, literalType: statementType, inferredType: inferredType);
}
@override
void variableGet(ExpressionJudgment judgment, Location location,
bool isInCascade, Declaration expressionVariable, DartType inferredType) {
if (isInCascade) {
return;
}
_store(location,
declaration: expressionVariable, inferredType: inferredType);
}
@override
void variableSet(ExpressionJudgment judgment, Location location,
DartType inferredType) =>
genericExpression("variableSet", location, inferredType);
@override
void whileStatement(StatementJudgment judgment, Location location) {}
@override
void yieldStatement(StatementJudgment judgment, Location location) {}
@override
void storePrefixInfo(Location location, PrefixInfo prefixInfo) {
_store(location, prefixInfo: prefixInfo);
}
@override
void storeClassReference(
Location location, Reference reference, DartType rawType) {
// TODO(paulberry): would it be better to use literalType?
_store(location, reference: reference, inferredType: rawType);
}
}
/// A [DartType] wrapper around invocation type arguments.
class TypeArgumentsDartType implements DartType {
final List<DartType> types;
TypeArgumentsDartType(this.types);
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@override
String toString() {
return '<${types.join(', ')}>';
}
}