ExpressionTyping* refactoring

removed expectedReturnType
inlined unnecessary checkFunctionReturnType functions
This commit is contained in:
Svetlana Isakova
2012-05-18 16:37:18 +04:00
parent cfa2425f3d
commit 9c9149d3e6
7 changed files with 32 additions and 61 deletions
@@ -404,7 +404,8 @@ public class BodyResolver {
JetExpression bodyExpression = declaration.getBodyExpression();
if (bodyExpression != null) {
expressionTypingServices.checkFunctionReturnType(scopeForConstructorBody, declaration, descriptor, JetStandardClasses.getUnitType(), trace);
expressionTypingServices.checkFunctionReturnType(scopeForConstructorBody, declaration, descriptor, DataFlowInfo.EMPTY,
JetStandardClasses.getUnitType(), trace);
}
checkDefaultParameterValues(declaration.getValueParameters(), descriptor.getValueParameters(), scopeForConstructorBody);
@@ -548,7 +549,7 @@ public class BodyResolver {
JetExpression bodyExpression = function.getBodyExpression();
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, functionDescriptor, trace);
if (bodyExpression != null) {
expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, trace);
expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, DataFlowInfo.EMPTY, null, trace);
}
List<JetParameter> valueParameters = function.getValueParameters();
@@ -531,10 +531,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetExpression selectorExpression = expression.getSelectorExpression();
JetExpression receiverExpression = expression.getReceiverExpression();
ExpressionTypingContext contextWithNoExpectedType = context.replaceExpectedType(NO_EXPECTED_TYPE);
JetType receiverType = facade.getType(receiverExpression,
contextWithNoExpectedType
.replaceExpectedReturnType(NO_EXPECTED_TYPE)
.replaceNamespacesAllowed(true));
JetType receiverType = facade.getType(receiverExpression, contextWithNoExpectedType.replaceNamespacesAllowed(true));
if (selectorExpression == null) return null;
if (receiverType == null) receiverType = ErrorUtils.createErrorType("Type for " + expression.getText());
@@ -686,8 +683,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
referencedName = referencedName == null ? " <?>" : referencedName;
context.labelResolver.enterLabeledElement(referencedName.substring(1), baseExpression);
// TODO : Some processing for the label?
ExpressionTypingContext newContext = context.replaceExpectedReturnType(context.expectedType);
JetType type = facade.getType(baseExpression, newContext, isStatement);
JetType type = facade.getType(baseExpression, context, isStatement);
context.labelResolver.exitLabeledElement(baseExpression);
return DataFlowUtils.checkType(type, expression, context);
}
@@ -102,14 +102,14 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
if (returnTypeRef != null) {
returnType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, returnTypeRef, context.trace, true);
context.expressionTypingServices.checkFunctionReturnType(expression, context.replaceScope(functionInnerScope).
replaceExpectedType(returnType).replaceExpectedReturnType(returnType).replaceDataFlowInfo(context.dataFlowInfo), context.trace);
replaceExpectedType(returnType).replaceDataFlowInfo(context.dataFlowInfo), context.trace);
}
else {
if (functionTypeExpected) {
returnType = JetStandardClasses.getReturnTypeFromFunctionType(expectedType);
}
returnType = context.expressionTypingServices.getBlockReturnedType(functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT,
context.replaceExpectedType(returnType).replaceExpectedReturnType(returnType), context.trace);
context.replaceExpectedType(returnType), context.trace);
}
JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("<return type>") : returnType;
functionDescriptor.setReturnType(safeReturnType);
@@ -51,10 +51,9 @@ public class ExpressionTypingContext {
@NotNull JetScope scope,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull JetType expectedType,
@NotNull JetType expectedReturnType,
boolean namespacesAllowed) {
return new ExpressionTypingContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists,
labelResolver, trace, scope, dataFlowInfo, expectedType, expectedReturnType, namespacesAllowed);
labelResolver, trace, scope, dataFlowInfo, expectedType, namespacesAllowed);
}
// @NotNull
@@ -74,7 +73,6 @@ public class ExpressionTypingContext {
public final DataFlowInfo dataFlowInfo;
public final JetType expectedType;
public final JetType expectedReturnType;
public final Map<JetPattern, DataFlowInfo> patternsToDataFlowInfo;
public final Map<JetPattern, List<VariableDescriptor>> patternsToBoundVariableLists;
@@ -94,7 +92,6 @@ public class ExpressionTypingContext {
@NotNull JetScope scope,
@NotNull DataFlowInfo dataFlowInfo,
@NotNull JetType expectedType,
@NotNull JetType expectedReturnType,
boolean namespacesAllowed) {
this.expressionTypingServices = expressionTypingServices;
this.trace = trace;
@@ -104,43 +101,36 @@ public class ExpressionTypingContext {
this.scope = scope;
this.dataFlowInfo = dataFlowInfo;
this.expectedType = expectedType;
this.expectedReturnType = expectedReturnType;
this.namespacesAllowed = namespacesAllowed;
}
@NotNull
public ExpressionTypingContext replaceNamespacesAllowed(boolean namespacesAllowed) {
if (namespacesAllowed == this.namespacesAllowed) return this;
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, expectedType, expectedReturnType, namespacesAllowed);
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, expectedType, namespacesAllowed);
}
@NotNull
public ExpressionTypingContext replaceDataFlowInfo(DataFlowInfo newDataFlowInfo) {
if (newDataFlowInfo == dataFlowInfo) return this;
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, newDataFlowInfo, expectedType, expectedReturnType, namespacesAllowed);
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, newDataFlowInfo, expectedType, namespacesAllowed);
}
public ExpressionTypingContext replaceExpectedType(@Nullable JetType newExpectedType) {
if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
if (expectedType == newExpectedType) return this;
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, newExpectedType, expectedReturnType, namespacesAllowed);
}
public ExpressionTypingContext replaceExpectedReturnType(@Nullable JetType newExpectedReturnType) {
if (newExpectedReturnType == null) return replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
if (expectedReturnType == newExpectedReturnType) return this;
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, expectedType, newExpectedReturnType, namespacesAllowed);
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, newExpectedType, namespacesAllowed);
}
public ExpressionTypingContext replaceBindingTrace(@NotNull BindingTrace newTrace) {
if (newTrace == trace) return this;
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, newTrace, scope, dataFlowInfo, expectedType, expectedReturnType, namespacesAllowed);
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, newTrace, scope, dataFlowInfo, expectedType, namespacesAllowed);
}
@NotNull
public ExpressionTypingContext replaceScope(@NotNull JetScope newScope) {
if (newScope == scope) return this;
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, newScope, dataFlowInfo, expectedType, expectedReturnType, namespacesAllowed);
return newContext(expressionTypingServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, newScope, dataFlowInfo, expectedType, namespacesAllowed);
}
///////////// LAZY ACCESSORS
@@ -125,7 +125,7 @@ public class ExpressionTypingServices {
ExpressionTypingContext context = ExpressionTypingContext.newContext(
this,
new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
trace, scope, dataFlowInfo, expectedType, FORBIDDEN, false
trace, scope, dataFlowInfo, expectedType, false
);
return expressionTypingFacade.getType(expression, context);
}
@@ -134,8 +134,7 @@ public class ExpressionTypingServices {
ExpressionTypingContext context = ExpressionTypingContext.newContext(
this,
new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
trace, scope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, FORBIDDEN,
true);
trace, scope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, true);
return expressionTypingFacade.getType(expression, context);
// return ((ExpressionTypingContext) ExpressionTyperVisitorWithNamespaces).INSTANCE.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.NO_EXPECTED_TYPE));
}
@@ -150,20 +149,9 @@ public class ExpressionTypingServices {
}
public void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, BindingTrace trace) {
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, DataFlowInfo.EMPTY, null, trace);
}
/////////////////////////////////////////////////////////
public void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @Nullable JetType expectedReturnType, BindingTrace trace) {
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, DataFlowInfo.EMPTY, expectedReturnType, trace);
}
/////////////////////////////////////////////////////////
/*package*/ void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull DataFlowInfo dataFlowInfo, BindingTrace trace) {
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, dataFlowInfo, null, trace);
}
/*package*/ void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedReturnType, BindingTrace trace) {
public void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedReturnType, BindingTrace trace) {
if (expectedReturnType == null) {
expectedReturnType = functionDescriptor.getReturnType();
if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) {
@@ -173,7 +161,7 @@ public class ExpressionTypingServices {
checkFunctionReturnType(function, ExpressionTypingContext.newContext(
this,
new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE, expectedReturnType, false
trace, functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE, false
), trace);
}
@@ -185,7 +173,7 @@ public class ExpressionTypingServices {
final ExpressionTypingContext newContext =
blockBody
? context.replaceExpectedType(NO_EXPECTED_TYPE)
: context.replaceExpectedType(context.expectedReturnType == FORBIDDEN ? NO_EXPECTED_TYPE : context.expectedReturnType).replaceExpectedReturnType(FORBIDDEN);
: context;
if (function instanceof JetFunctionLiteralExpression) {
JetFunctionLiteralExpression functionLiteralExpression = (JetFunctionLiteralExpression) function;
@@ -222,7 +210,7 @@ public class ExpressionTypingServices {
expressionTypingFacade.getType(bodyExpression, ExpressionTypingContext.newContext(
this,
new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(),
trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, FORBIDDEN, false), !function.hasBlockBody());
trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, false), !function.hasBlockBody());
//todo function literals
final Collection<JetExpression> returnedExpressions = Lists.newArrayList();
if (function.hasBlockBody()) {
@@ -272,7 +260,7 @@ public class ExpressionTypingServices {
}
ExpressionTypingInternals blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(scope);
ExpressionTypingContext newContext = createContext(context, trace, scope, context.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
ExpressionTypingContext newContext = createContext(context, trace, scope, context.dataFlowInfo, NO_EXPECTED_TYPE);
JetType result = null;
for (Iterator<? extends JetElement> iterator = block.iterator(); iterator.hasNext(); ) {
@@ -287,13 +275,13 @@ public class ExpressionTypingServices {
TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace);
final boolean[] mismatch = new boolean[1];
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
newContext = createContext(newContext, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType);
result = blockLevelVisitor.getType(statementExpression, newContext, true);
if (mismatch[0]) {
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
mismatch[0] = false;
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
newContext = createContext(newContext, interceptingTrace, scope, newContext.dataFlowInfo, NO_EXPECTED_TYPE);
result = blockLevelVisitor.getType(statementExpression, newContext, true);
if (mismatch[0]) {
temporaryTraceExpectingUnit.commit();
@@ -307,7 +295,7 @@ public class ExpressionTypingServices {
}
}
else {
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
newContext = createContext(newContext, trace, scope, newContext.dataFlowInfo, context.expectedType);
result = blockLevelVisitor.getType(statementExpression, newContext, true);
}
}
@@ -342,16 +330,17 @@ public class ExpressionTypingServices {
newDataFlowInfo = context.dataFlowInfo;
}
if (newDataFlowInfo != context.dataFlowInfo) {
newContext = createContext(newContext, trace, scope, newDataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType);
newContext = createContext(newContext, trace, scope, newDataFlowInfo, NO_EXPECTED_TYPE);
}
blockLevelVisitor = ExpressionTypingVisitorDispatcher.createForBlock(scope);
}
return result;
}
private ExpressionTypingContext createContext(ExpressionTypingContext oldContext, BindingTrace trace, WritableScope scope, DataFlowInfo dataFlowInfo, JetType expectedType, JetType expectedReturnType) {
private ExpressionTypingContext createContext(ExpressionTypingContext oldContext, BindingTrace trace, WritableScope scope, DataFlowInfo dataFlowInfo, JetType expectedType) {
return ExpressionTypingContext.newContext(
this, oldContext.patternsToDataFlowInfo, oldContext.patternsToBoundVariableLists, oldContext.labelResolver, trace, scope, dataFlowInfo, expectedType, expectedReturnType, oldContext.namespacesAllowed);
this, oldContext.patternsToDataFlowInfo, oldContext.patternsToBoundVariableLists, oldContext.labelResolver,
trace, scope, dataFlowInfo, expectedType, oldContext.namespacesAllowed);
}
private ObservableBindingTrace makeTraceInterceptingTypeMismatch(final BindingTrace trace, final JetExpression expressionToWatch, final boolean[] mismatchFound) {
@@ -163,7 +163,6 @@ public class ExpressionTypingUtils {
scope,
DataFlowInfo.EMPTY,
TypeUtils.NO_EXPECTED_TYPE,
TypeUtils.NO_EXPECTED_TYPE,
false
);
return ControlStructureTypingVisitor.checkIterableConvention(expressionReceiver, context) != null;
@@ -25,11 +25,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResultsUtil;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
@@ -132,7 +128,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
SimpleFunctionDescriptor functionDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function, context.trace);
scope.addFunctionDescriptor(functionDescriptor);
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
context.expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, context.trace);
context.expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace);
return DataFlowUtils.checkStatementType(function, context);
}
@@ -174,7 +170,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
//There is a temporary binding trace for an opportunity to resolve set method for array if needed (the initial trace should be used there)
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(contextWithExpectedType.trace);
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE).replaceBindingTrace(temporaryBindingTrace);
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceBindingTrace(temporaryBindingTrace);
JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType();
@@ -234,7 +230,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
}
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
JetExpression right = expression.getRight();
if (left instanceof JetArrayAccessExpression) {