Calls to flowInformationProvider were removed from JetTypeInferrer
This commit is contained in:
@@ -44,8 +44,8 @@ public class JetSemanticServices {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetTypeInferrer.Services getTypeInferrerServices(@NotNull BindingTrace trace, @NotNull JetFlowInformationProvider flowInformationProvider) {
|
||||
return new JetTypeInferrer(flowInformationProvider, this).getServices(trace);
|
||||
public JetTypeInferrer.Services getTypeInferrerServices(@NotNull BindingTrace trace) {
|
||||
return new JetTypeInferrer(this).getServices(trace);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -76,17 +76,17 @@ public class JetControlFlowProcessor {
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null || stack.isEmpty()) {
|
||||
if (reportUnresolved) {
|
||||
trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||
// trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else if (stack.size() > 1) {
|
||||
// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
|
||||
trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||
// trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||
}
|
||||
|
||||
JetElement result = stack.peek();
|
||||
trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
||||
// trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class AnnotationResolver {
|
||||
this.trace = trace;
|
||||
// this.typeInferrer = new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices);
|
||||
// this.services = typeInferrer.getServices(this.trace);
|
||||
this.callResolver = new CallResolver(semanticServices, new JetTypeInferrer(JetFlowInformationProvider.THROW_EXCEPTION, semanticServices), DataFlowInfo.getEmpty());
|
||||
this.callResolver = new CallResolver(semanticServices, new JetTypeInferrer(semanticServices), DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -125,7 +125,7 @@ public class BodyResolver {
|
||||
final JetScope scopeForConstructor = primaryConstructor == null
|
||||
? null
|
||||
: getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true);
|
||||
final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE); // TODO : flow
|
||||
final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors); // TODO : flow
|
||||
|
||||
final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
|
||||
JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||
@@ -290,7 +290,7 @@ public class BodyResolver {
|
||||
ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
|
||||
assert primaryConstructor != null;
|
||||
final JetScope scopeForConstructor = getInnerScopeForConstructor(primaryConstructor, classDescriptor.getScopeForMemberResolution(), true);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(createFieldAssignTrackingTrace(), JetFlowInformationProvider.NONE); // TODO : flow
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(createFieldAssignTrackingTrace()); // TODO : flow
|
||||
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
|
||||
typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), NO_EXPECTED_TYPE);
|
||||
}
|
||||
@@ -316,7 +316,7 @@ public class BodyResolver {
|
||||
private void resolveSecondaryConstructorBody(JetConstructor declaration, final ConstructorDescriptor descriptor, final JetScope declaringScope) {
|
||||
final JetScope functionInnerScope = getInnerScopeForConstructor(descriptor, declaringScope, false);
|
||||
|
||||
final JetTypeInferrer.Services typeInferrerForInitializers = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, JetFlowInformationProvider.NONE);
|
||||
final JetTypeInferrer.Services typeInferrerForInitializers = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
|
||||
JetClass containingClass = PsiTreeUtil.getParentOfType(declaration, JetClass.class);
|
||||
assert containingClass != null : "This must be guaranteed by the parser";
|
||||
@@ -377,11 +377,11 @@ public class BodyResolver {
|
||||
}
|
||||
JetExpression bodyExpression = declaration.getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, flowInformationProvider);
|
||||
//context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
//JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
|
||||
typeInferrer.checkFunctionReturnType(functionInnerScope, declaration, JetStandardClasses.getUnitType());
|
||||
typeInferrer.checkFunctionReturnType(functionInnerScope, declaration, descriptor, JetStandardClasses.getUnitType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,8 +516,8 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
private void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) {
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(property, initializer); // TODO : flow JET-15
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors, flowInformationProvider);
|
||||
//JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(property, initializer); // TODO : flow JET-15
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
JetType type = typeInferrer.getType(getPropertyDeclarationInnerScope(scope, propertyDescriptor), initializer, NO_EXPECTED_TYPE);
|
||||
|
||||
JetType expectedType = propertyDescriptor.getInType();
|
||||
@@ -552,13 +552,13 @@ public class BodyResolver {
|
||||
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
if (bodyExpression != null) {
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(function.asElement(), bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace, flowInformationProvider);
|
||||
//JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(function.asElement(), bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
|
||||
typeInferrer.checkFunctionReturnType(declaringScope, function, functionDescriptor);
|
||||
}
|
||||
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace, JetFlowInformationProvider.THROW_EXCEPTION);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
List<JetParameter> valueParameters = function.getValueParameters();
|
||||
for (int i = 0; i < valueParameters.size(); i++) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = functionDescriptor.getValueParameters().get(i);
|
||||
|
||||
@@ -178,8 +178,8 @@ public class ClassDescriptorResolver {
|
||||
returnType = DeferredType.create(trace, new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
|
||||
@Override
|
||||
protected JetType compute() {
|
||||
JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
|
||||
return semanticServices.getTypeInferrerServices(trace, flowInformationProvider).inferFunctionReturnType(scope, function, functionDescriptor);
|
||||
//JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
|
||||
return semanticServices.getTypeInferrerServices(trace).inferFunctionReturnType(scope, function, functionDescriptor);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -537,8 +537,8 @@ public class ClassDescriptorResolver {
|
||||
LazyValue<JetType> lazyValue = new LazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
|
||||
@Override
|
||||
protected JetType compute() {
|
||||
JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
|
||||
return semanticServices.getTypeInferrerServices(trace, flowInformationProvider).safeGetType(scope, initializer, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
//JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
|
||||
return semanticServices.getTypeInferrerServices(trace).safeGetType(scope, initializer, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
}
|
||||
};
|
||||
if (allowDeferred) {
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptorImpl;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class ControlFlowAnalyzer {
|
||||
private TopDownAnalysisContext context;
|
||||
private JetTypeInferrer.Services typeInferrer;
|
||||
|
||||
public ControlFlowAnalyzer(TopDownAnalysisContext context) {
|
||||
this.context = context;
|
||||
typeInferrer = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
|
||||
}
|
||||
|
||||
public void process() {
|
||||
for (Map.Entry<JetNamedFunction, FunctionDescriptorImpl> entry : context.getFunctions().entrySet()) {
|
||||
JetNamedFunction function = entry.getKey();
|
||||
FunctionDescriptorImpl functionDescriptor = entry.getValue();
|
||||
|
||||
final JetType expectedReturnType = !function.hasBlockBody() && !function.hasDeclaredReturnType() ? NO_EXPECTED_TYPE : functionDescriptor.getReturnType();
|
||||
checkFunction(function, functionDescriptor, expectedReturnType);
|
||||
}
|
||||
|
||||
for (Map.Entry<JetDeclaration, ConstructorDescriptor> entry : this.context.getConstructors().entrySet()) {
|
||||
JetDeclaration declaration = entry.getKey();
|
||||
assert declaration instanceof JetConstructor;
|
||||
JetConstructor constructor = (JetConstructor) declaration;
|
||||
ConstructorDescriptor descriptor = entry.getValue();
|
||||
|
||||
checkFunction(constructor, descriptor, JetStandardClasses.getUnitType());
|
||||
}
|
||||
|
||||
for (JetProperty property : context.getProperties().keySet()) {
|
||||
checkProperty(property);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, final @NotNull JetType expectedReturnType) {
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
if (bodyExpression == null) return;
|
||||
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData((JetElement)function, bodyExpression);
|
||||
|
||||
final boolean blockBody = function.hasBlockBody();
|
||||
List<JetElement> unreachableElements = Lists.newArrayList();
|
||||
flowInformationProvider.collectUnreachableExpressions(function.asElement(), unreachableElements);
|
||||
|
||||
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
||||
final Set<JetElement> rootUnreachableElements = JetPsiUtil.findRootExpressions(unreachableElements);
|
||||
|
||||
for (JetElement element : rootUnreachableElements) {
|
||||
context.getTrace().report(UNREACHABLE_CODE.on(element));
|
||||
}
|
||||
|
||||
List<JetExpression> returnedExpressions = Lists.newArrayList();
|
||||
flowInformationProvider.collectReturnExpressions(function.asElement(), returnedExpressions);
|
||||
|
||||
boolean nothingReturned = returnedExpressions.isEmpty();
|
||||
|
||||
returnedExpressions.remove(function); // This will be the only "expression" if the body is empty
|
||||
|
||||
final JetScope scope = this.context.getDeclaringScopes().get(function);
|
||||
|
||||
if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty() && !nothingReturned) {
|
||||
context.getTrace().report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
}
|
||||
|
||||
for (JetExpression returnedExpression : returnedExpressions) {
|
||||
returnedExpression.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitReturnExpression(JetReturnExpression expression) {
|
||||
if (!blockBody) {
|
||||
context.getTrace().report(RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY.on(expression));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpression(JetExpression expression) {
|
||||
if (blockBody && expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) {
|
||||
JetType type = typeInferrer.getType(scope, expression, expectedReturnType);
|
||||
if (type == null || !JetStandardClasses.isNothing(type)) {
|
||||
context.getTrace().report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
markDominatedExpressionsAsUnreachable(bodyExpression, scope, expectedReturnType, flowInformationProvider);
|
||||
}
|
||||
|
||||
private void markDominatedExpressionsAsUnreachable(JetExpression expression, JetScope scope, JetType expectedReturnType, JetFlowInformationProvider flowInformationProvider) {
|
||||
JetType type = typeInferrer.getType(scope, expression, expectedReturnType);
|
||||
if (type == null || !JetStandardClasses.isNothing(type) || type.isNullable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<JetElement> dominated = new ArrayList<JetElement>();
|
||||
flowInformationProvider.collectDominatedExpressions(expression, dominated);
|
||||
Set<JetElement> rootExpressions = JetPsiUtil.findRootExpressions(dominated);
|
||||
for (JetElement rootExpression : rootExpressions) {
|
||||
context.getTrace().report(UNREACHABLE_BECAUSE_OF_NOTHING.on(rootExpression, expression.getText()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void checkProperty(JetProperty property) {
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (initializer == null) return;
|
||||
JetScope scope = this.context.getDeclaringScopes().get(property);
|
||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(property, initializer);
|
||||
markDominatedExpressionsAsUnreachable(initializer, scope, NO_EXPECTED_TYPE, flowInformationProvider);
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@ public class TopDownAnalyzer {
|
||||
new OverrideResolver(context).process();
|
||||
new BodyResolver(context).resolveBehaviorDeclarationBodies();
|
||||
new DeclarationsChecker(context).process();
|
||||
new ControlFlowAnalyzer(context).process();
|
||||
}
|
||||
|
||||
public static void processStandardLibraryNamespace(
|
||||
|
||||
@@ -218,7 +218,7 @@ public class TypeHierarchyResolver {
|
||||
if (importDirective.isAllUnder()) {
|
||||
JetExpression importedReference = importDirective.getImportedReference();
|
||||
if (importedReference != null) {
|
||||
JetTypeInferrer.Services typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace(), JetFlowInformationProvider.THROW_EXCEPTION);
|
||||
JetTypeInferrer.Services typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
|
||||
JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference);
|
||||
if (type != null) {
|
||||
namespaceScope.importScope(type.getMemberScope());
|
||||
@@ -232,7 +232,7 @@ public class TypeHierarchyResolver {
|
||||
JetExpression importedReference = importDirective.getImportedReference();
|
||||
if (importedReference instanceof JetDotQualifiedExpression) {
|
||||
JetDotQualifiedExpression reference = (JetDotQualifiedExpression) importedReference;
|
||||
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace(), JetFlowInformationProvider.THROW_EXCEPTION).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression());
|
||||
JetType type = context.getSemanticServices().getTypeInferrerServices(context.getTrace()).getTypeWithNamespaces(namespaceScope, reference.getReceiverExpression());
|
||||
JetExpression selectorExpression = reference.getSelectorExpression();
|
||||
if (selectorExpression != null) {
|
||||
referenceExpression = (JetSimpleNameExpression) selectorExpression;
|
||||
|
||||
@@ -12,7 +12,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
@@ -160,14 +159,16 @@ public class JetTypeInferrer {
|
||||
.build();
|
||||
|
||||
private final JetSemanticServices semanticServices;
|
||||
private final JetFlowInformationProvider flowInformationProvider;
|
||||
// private final JetFlowInformationProvider flowInformationProvider;
|
||||
private final Map<JetPattern, DataFlowInfo> patternsToDataFlowInfo = Maps.newHashMap();
|
||||
|
||||
private final Map<JetPattern, List<VariableDescriptor>> patternsToBoundVariableLists = Maps.newHashMap();
|
||||
|
||||
private final LabelsResolver labelsResolver = new LabelsResolver();
|
||||
|
||||
public JetTypeInferrer(@NotNull JetFlowInformationProvider flowInformationProvider, @NotNull JetSemanticServices semanticServices) {
|
||||
public JetTypeInferrer(@NotNull JetSemanticServices semanticServices) {
|
||||
this.semanticServices = semanticServices;
|
||||
this.flowInformationProvider = flowInformationProvider;
|
||||
// this.flowInformationProvider = flowInformationProvider;
|
||||
}
|
||||
|
||||
public Services getServices(@NotNull BindingTrace trace) {
|
||||
@@ -254,7 +255,7 @@ public class JetTypeInferrer {
|
||||
expectedReturnType = NO_EXPECTED_TYPE;
|
||||
}
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||
checkFunctionReturnType(functionInnerScope, function, expectedReturnType, dataFlowInfo);
|
||||
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, expectedReturnType, dataFlowInfo);
|
||||
// Map<JetElement, JetType> typeMap = collectReturnedExpressionsWithTypes(outerScope, function, functionDescriptor, expectedReturnType);
|
||||
// if (typeMap.isEmpty()) {
|
||||
// return; // The function returns Nothing
|
||||
@@ -288,11 +289,11 @@ public class JetTypeInferrer {
|
||||
// }
|
||||
}
|
||||
|
||||
public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, @NotNull final JetType expectedReturnType) {
|
||||
checkFunctionReturnType(functionInnerScope, function, expectedReturnType, DataFlowInfo.getEmpty());
|
||||
public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @NotNull final JetType expectedReturnType) {
|
||||
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, expectedReturnType, DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
private void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, @NotNull final JetType expectedReturnType, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
private void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @NotNull final JetType expectedReturnType, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
assert bodyExpression != null;
|
||||
|
||||
@@ -310,56 +311,62 @@ public class JetTypeInferrer {
|
||||
typeInferrerVisitor.getType(bodyExpression, context);
|
||||
}
|
||||
|
||||
List<JetElement> unreachableElements = Lists.newArrayList();
|
||||
flowInformationProvider.collectUnreachableExpressions(function.asElement(), unreachableElements);
|
||||
// List<JetElement> unreachableElements = Lists.newArrayList();
|
||||
// flowInformationProvider.collectUnreachableExpressions(function.asElement(), unreachableElements);
|
||||
|
||||
// This is needed in order to highlight only '1 < 2' and not '1', '<' and '2' as well
|
||||
final Set<JetElement> rootUnreachableElements = JetPsiUtil.findRootExpressions(unreachableElements);
|
||||
// final Set<JetElement> rootUnreachableElements = JetPsiUtil.findRootExpressions(unreachableElements);
|
||||
|
||||
// TODO : (return 1) || (return 2) -- only || and right of it is unreachable
|
||||
// TODO : try {return 1} finally {return 2}. Currently 'return 1' is reported as unreachable,
|
||||
// though it'd better be reported more specifically
|
||||
|
||||
for (JetElement element : rootUnreachableElements) {
|
||||
// trace.getErrorHandler().genericError(element.getNode(), "Unreachable code");
|
||||
trace.report(UNREACHABLE_CODE.on(element));
|
||||
}
|
||||
// for (JetElement element : rootUnreachableElements) {
|
||||
// //trace.report(UNREACHABLE_CODE.on(element));
|
||||
// }
|
||||
|
||||
List<JetExpression> returnedExpressions = Lists.newArrayList();
|
||||
flowInformationProvider.collectReturnExpressions(function.asElement(), returnedExpressions);
|
||||
// List<JetExpression> returnedExpressions = Lists.newArrayList();
|
||||
// flowInformationProvider.collectReturnExpressions(function.asElement(), returnedExpressions);
|
||||
|
||||
boolean nothingReturned = returnedExpressions.isEmpty();
|
||||
// boolean nothingReturned = returnedExpressions.isEmpty();
|
||||
|
||||
returnedExpressions.remove(function); // This will be the only "expression" if the body is empty
|
||||
//returnedExpressions.remove(function); // This will be the only "expression" if the body is empty
|
||||
// Map<JetExpression, JetType> typeMap = collectReturnedExpressionsWithTypes(trace, functionInnerScope, function, functionDescriptor);
|
||||
// Set<JetExpression> returnedExpressions = typeMap.keySet();
|
||||
//
|
||||
//
|
||||
// if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty()) {
|
||||
// trace.report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
// }
|
||||
|
||||
if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty() && !nothingReturned) {
|
||||
// trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
|
||||
trace.report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
}
|
||||
|
||||
for (JetExpression returnedExpression : returnedExpressions) {
|
||||
returnedExpression.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitReturnExpression(JetReturnExpression expression) {
|
||||
if (!blockBody) {
|
||||
// trace.getErrorHandler().genericError(expression.getNode(), "Returns are not allowed for functions with expression body. Use block body in '{...}'");
|
||||
trace.report(RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY.on(expression));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpression(JetExpression expression) {
|
||||
if (blockBody && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) {
|
||||
//TODO move to pseudocode
|
||||
JetType type = typeInferrerVisitor.getType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
if (type == null || !JetStandardClasses.isNothing(type)) {
|
||||
// trace.getErrorHandler().genericError(expression.getNode(), "A 'return' expression required in a function with a block body ('{...}')");
|
||||
trace.report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty() && !nothingReturned) {
|
||||
//// trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
|
||||
// trace.report(RETURN_TYPE_MISMATCH.on(bodyExpression, expectedReturnType));
|
||||
// }
|
||||
//
|
||||
// for (JetExpression returnedExpression : returnedExpressions) {
|
||||
// returnedExpression.accept(new JetVisitorVoid() {
|
||||
// @Override
|
||||
// public void visitReturnExpression(JetReturnExpression expression) {
|
||||
// if (!blockBody) {
|
||||
//// trace.getErrorHandler().genericError(expression.getNode(), "Returns are not allowed for functions with expression body. Use block body in '{...}'");
|
||||
// trace.report(RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY.on(expression));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void visitExpression(JetExpression expression) {
|
||||
// if (blockBody && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) {
|
||||
// //TODO move to pseudocode
|
||||
// JetType type = typeInferrerVisitor.getType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
// if (type == null || !JetStandardClasses.isNothing(type)) {
|
||||
//// trace.getErrorHandler().genericError(expression.getNode(), "A 'return' expression required in a function with a block body ('{...}')");
|
||||
// trace.report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -376,14 +383,14 @@ public class JetTypeInferrer {
|
||||
|
||||
@NotNull
|
||||
public JetType inferFunctionReturnType(@NotNull JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) {
|
||||
Map<JetElement, JetType> typeMap = collectReturnedExpressionsWithTypes(trace, outerScope, function, functionDescriptor);
|
||||
Map<JetExpression, JetType> typeMap = collectReturnedExpressionsWithTypes(trace, outerScope, function, functionDescriptor);
|
||||
Collection<JetType> types = typeMap.values();
|
||||
return types.isEmpty()
|
||||
? JetStandardClasses.getNothingType()
|
||||
: semanticServices.getTypeChecker().commonSupertype(types);
|
||||
}
|
||||
|
||||
private Map<JetElement, JetType> collectReturnedExpressionsWithTypes(
|
||||
private Map<JetExpression, JetType> collectReturnedExpressionsWithTypes(
|
||||
@NotNull BindingTrace trace,
|
||||
JetScope outerScope,
|
||||
JetDeclarationWithBody function,
|
||||
@@ -392,10 +399,20 @@ public class JetTypeInferrer {
|
||||
assert bodyExpression != null;
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||
typeInferrerVisitor.getType(bodyExpression, newContext(trace, functionInnerScope, DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, FORBIDDEN));
|
||||
Collection<JetExpression> returnedExpressions = new ArrayList<JetExpression>();
|
||||
Collection<JetElement> elementsReturningUnit = new ArrayList<JetElement>();
|
||||
flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit);
|
||||
Map<JetElement,JetType> typeMap = new HashMap<JetElement, JetType>();
|
||||
//todo function literals
|
||||
final Collection<JetExpression> returnedExpressions = new ArrayList<JetExpression>();
|
||||
if (function.hasBlockBody()) {
|
||||
bodyExpression.accept(new JetTreeVisitorVoid() {
|
||||
@Override
|
||||
public void visitReturnExpression(JetReturnExpression expression) {
|
||||
returnedExpressions.add(expression);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
returnedExpressions.add(bodyExpression);
|
||||
}
|
||||
Map<JetExpression, JetType> typeMap = new HashMap<JetExpression, JetType>();
|
||||
for (JetExpression returnedExpression : returnedExpressions) {
|
||||
JetType cachedType = trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, returnedExpression);
|
||||
trace.record(STATEMENT, returnedExpression, false);
|
||||
@@ -403,9 +420,6 @@ public class JetTypeInferrer {
|
||||
typeMap.put(returnedExpression, cachedType);
|
||||
}
|
||||
}
|
||||
for (JetElement jetElement : elementsReturningUnit) {
|
||||
typeMap.put(jetElement, JetStandardClasses.getUnitType());
|
||||
}
|
||||
return typeMap;
|
||||
}
|
||||
|
||||
@@ -718,7 +732,6 @@ public class JetTypeInferrer {
|
||||
}
|
||||
|
||||
private class TypeInferrerVisitor extends JetVisitor<JetType, TypeInferenceContext> {
|
||||
|
||||
protected DataFlowInfo resultDataFlowInfo;
|
||||
|
||||
@Nullable
|
||||
@@ -767,10 +780,11 @@ public class JetTypeInferrer {
|
||||
}
|
||||
if (result != null) {
|
||||
context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result);
|
||||
if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
|
||||
markDominatedExpressionsAsUnreachable(expression, context);
|
||||
}
|
||||
// if (JetStandardClasses.isNothing(result) && !result.isNullable()) {
|
||||
// markDominatedExpressionsAsUnreachable(expression, context);
|
||||
// }
|
||||
}
|
||||
// }
|
||||
}
|
||||
catch (ReenteringLazyValueComputationException e) {
|
||||
// context.trace.getErrorHandler().genericError(expression.getNode(), "Type checking has run into a recursive problem"); // TODO : message
|
||||
@@ -798,16 +812,16 @@ public class JetTypeInferrer {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void markDominatedExpressionsAsUnreachable(JetExpression expression, TypeInferenceContext context) {
|
||||
List<JetElement> dominated = new ArrayList<JetElement>();
|
||||
flowInformationProvider.collectDominatedExpressions(expression, dominated);
|
||||
Set<JetElement> rootExpressions = JetPsiUtil.findRootExpressions(dominated);
|
||||
for (JetElement rootExpression : rootExpressions) {
|
||||
// context.trace.getErrorHandler().genericError(rootExpression.getNode(),
|
||||
// "This code is unreachable, because '" + expression.getText() + "' never terminates normally");
|
||||
context.trace.report(UNREACHABLE_BECAUSE_OF_NOTHING.on(rootExpression, expression.getText()));
|
||||
}
|
||||
}
|
||||
// private void markDominatedExpressionsAsUnreachable(JetExpression expression, TypeInferenceContext context) {
|
||||
// List<JetElement> dominated = new ArrayList<JetElement>();
|
||||
// flowInformationProvider.collectDominatedExpressions(expression, dominated);
|
||||
// Set<JetElement> rootExpressions = JetPsiUtil.findRootExpressions(dominated);
|
||||
// for (JetElement rootExpression : rootExpressions) {
|
||||
//// context.trace.getErrorHandler().genericError(rootExpression.getNode(),
|
||||
//// "This code is unreachable, because '" + expression.getText() + "' never terminates normally");
|
||||
// context.trace.report(UNREACHABLE_BECAUSE_OF_NOTHING.on(rootExpression, expression.getText()));
|
||||
// }
|
||||
// }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1029,7 +1043,7 @@ public class JetTypeInferrer {
|
||||
JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef();
|
||||
if (returnTypeRef != null) {
|
||||
returnType = context.typeResolver.resolveType(context.scope, returnTypeRef);
|
||||
context.services.checkFunctionReturnType(functionInnerScope, expression, returnType, context.dataFlowInfo);
|
||||
context.services.checkFunctionReturnType(functionInnerScope, expression, functionDescriptor, returnType, context.dataFlowInfo);
|
||||
}
|
||||
else {
|
||||
if (functionTypeExpected) {
|
||||
@@ -1139,6 +1153,12 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public JetType visitReturnExpression(JetReturnExpression expression, TypeInferenceContext context) {
|
||||
JetSimpleNameExpression labelElement = expression.getTargetLabel();
|
||||
if (labelElement != null) {
|
||||
String labelName = expression.getLabelName();
|
||||
assert labelName != null;
|
||||
labelsResolver.resolveLabel(labelName, labelElement, true, context);
|
||||
}
|
||||
if (context.expectedReturnType == FORBIDDEN) {
|
||||
// context.trace.getErrorHandler().genericError(expression.getNode(), "'return' is not allowed here");
|
||||
context.trace.report(RETURN_NOT_ALLOWED.on(expression));
|
||||
@@ -1161,11 +1181,13 @@ public class JetTypeInferrer {
|
||||
|
||||
@Override
|
||||
public JetType visitBreakExpression(JetBreakExpression expression, TypeInferenceContext context) {
|
||||
labelsResolver.resolveCorrespondingLoopLabel(expression, context);
|
||||
return context.services.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitContinueExpression(JetContinueExpression expression, TypeInferenceContext context) {
|
||||
labelsResolver.resolveCorrespondingLoopLabel(expression, context);
|
||||
return context.services.checkType(JetStandardClasses.getNothingType(), expression, context);
|
||||
}
|
||||
|
||||
@@ -1306,6 +1328,8 @@ public class JetTypeInferrer {
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
else if (size == 0) {
|
||||
//todo (first we put to the context, then get from it)
|
||||
labelsResolver.resolveLabel(labelName, targetLabel, false, context);
|
||||
// This uses the info written by the control flow processor
|
||||
PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(context.trace.getBindingContext(), targetLabel);
|
||||
if (psiElement instanceof JetFunctionLiteralExpression) {
|
||||
@@ -1860,19 +1884,21 @@ public class JetTypeInferrer {
|
||||
DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : extractDataFlowInfoFromCondition(condition, true, scopeToExtend, context);
|
||||
getTypeWithNewScopeAndDataFlowInfo(scopeToExtend, body, conditionInfo, context);
|
||||
}
|
||||
if (!isBreakable(expression)) {
|
||||
if (!containsBreak(expression)) {
|
||||
// resultScope = newWritableScopeImpl();
|
||||
resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false, null, context);
|
||||
}
|
||||
return context.services.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType);
|
||||
}
|
||||
|
||||
private boolean isBreakable(JetLoopExpression expression) {
|
||||
private boolean containsBreak(JetLoopExpression expression) {
|
||||
final boolean[] result = new boolean[1];
|
||||
result[0] = false;
|
||||
expression.accept(new JetTreeVisitorVoid() {
|
||||
@Override
|
||||
public void visitBreakExpression(JetBreakExpression expression) {
|
||||
//todo get exact loop for this break, compare to expression
|
||||
//expression.getLabeledExpression()
|
||||
result[0] = true;
|
||||
}
|
||||
});
|
||||
@@ -1903,7 +1929,7 @@ public class JetTypeInferrer {
|
||||
}
|
||||
JetExpression condition = expression.getCondition();
|
||||
checkCondition(conditionScope, condition, context);
|
||||
if (!isBreakable(expression)) {
|
||||
if (!containsBreak(expression)) {
|
||||
// resultScope = newWritableScopeImpl();
|
||||
resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false, null, context);
|
||||
}
|
||||
@@ -2289,8 +2315,13 @@ public class JetTypeInferrer {
|
||||
if (baseExpression == null) return null;
|
||||
JetSimpleNameExpression operationSign = expression.getOperationSign();
|
||||
if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) {
|
||||
String referencedName = operationSign.getReferencedName();
|
||||
referencedName = referencedName == null ? " <?>" : referencedName;
|
||||
labelsResolver.enterLabeledElement(referencedName.substring(1), baseExpression);
|
||||
// TODO : Some processing for the label?
|
||||
return context.services.checkType(getType(baseExpression, context.replaceExpectedReturnType(context.expectedType)), expression, context);
|
||||
JetType type = context.services.checkType(getType(baseExpression, context.replaceExpectedReturnType(context.expectedType)), expression, context);
|
||||
labelsResolver.exitLabeledElement(baseExpression);
|
||||
return type;
|
||||
}
|
||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||
String name = unaryOperationNames.get(operationType);
|
||||
@@ -2331,6 +2362,7 @@ public class JetTypeInferrer {
|
||||
else {
|
||||
result = returnType;
|
||||
}
|
||||
|
||||
return context.services.checkType(result, expression, context);
|
||||
}
|
||||
|
||||
@@ -2830,4 +2862,84 @@ public class JetTypeInferrer {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class LabelsResolver {
|
||||
private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
|
||||
|
||||
private void enterLabeledElement(@NotNull String labelName, @NotNull JetExpression labeledExpression) {
|
||||
JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression);
|
||||
if (deparenthesized != null) {
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null) {
|
||||
stack = new Stack<JetElement>();
|
||||
labeledElements.put(labelName, stack);
|
||||
}
|
||||
stack.push(deparenthesized);
|
||||
}
|
||||
}
|
||||
|
||||
private void exitLabeledElement(JetExpression expression) {
|
||||
JetExpression deparenthesized = JetPsiUtil.deparenthesize(expression);
|
||||
// TODO : really suboptimal
|
||||
for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
|
||||
Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
|
||||
Stack<JetElement> stack = entry.getValue();
|
||||
for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
|
||||
JetElement recorded = stackIter.next();
|
||||
if (recorded == deparenthesized) {
|
||||
stackIter.remove();
|
||||
}
|
||||
}
|
||||
if (stack.isEmpty()) {
|
||||
mapIter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, TypeInferenceContext context) {
|
||||
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
|
||||
int size = declarationsByLabel.size();
|
||||
|
||||
if (size == 1) {
|
||||
DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
|
||||
JetElement element;
|
||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
element = (JetElement) context.trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
|
||||
}
|
||||
else if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
|
||||
element = (JetElement) context.trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, functionDescriptor);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
context.trace.record(LABEL_TARGET, labelExpression, element);
|
||||
return;
|
||||
}
|
||||
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null || stack.isEmpty()) {
|
||||
if (reportUnresolved) {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (stack.size() > 1) {
|
||||
context.trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||
}
|
||||
|
||||
JetElement result = stack.peek();
|
||||
context.trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
||||
}
|
||||
|
||||
private void resolveCorrespondingLoopLabel(JetLabelQualifiedExpression expression, TypeInferenceContext context) {
|
||||
String labelName = expression.getLabelName();
|
||||
if (labelName != null) {
|
||||
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
assert targetLabel != null;
|
||||
resolveLabel(labelName, targetLabel, true, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
||||
@NotNull
|
||||
private FunctionDescriptor standardFunction(ClassDescriptor classDescriptor, List<TypeProjection> typeArguments, String name, JetType... parameterType) {
|
||||
List<JetType> parameterTypeList = Arrays.asList(parameterType);
|
||||
JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext(), JetFlowInformationProvider.NONE);
|
||||
JetTypeInferrer.Services typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext());
|
||||
|
||||
OverloadResolutionResults<FunctionDescriptor> functions = typeInferrerServices.getCallResolver().resolveExactSignature(
|
||||
classDescriptor.getMemberScope(typeArguments), ReceiverDescriptor.NO_RECEIVER, name, parameterTypeList);
|
||||
|
||||
@@ -493,14 +493,14 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
private void assertType(String expression, JetType expectedType) {
|
||||
Project project = getProject();
|
||||
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE, JetFlowInformationProvider.NONE).getType(scopeWithImports, jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).getType(scopeWithImports, jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
assertTrue(type + " != " + expectedType, type.equals(expectedType));
|
||||
}
|
||||
|
||||
private void assertErrorType(String expression) {
|
||||
Project project = getProject();
|
||||
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE, JetFlowInformationProvider.NONE).safeGetType(scopeWithImports, jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).safeGetType(scopeWithImports, jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
assertTrue("Error type expected but " + type + " returned", ErrorUtils.isErrorType(type));
|
||||
}
|
||||
|
||||
@@ -523,7 +523,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
private void assertType(JetScope scope, String expression, String expectedTypeStr) {
|
||||
Project project = getProject();
|
||||
JetExpression jetExpression = JetPsiFactory.createExpression(project, expression);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE, JetFlowInformationProvider.NONE).getType(addImports(scope), jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).getType(addImports(scope), jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType expectedType = expectedTypeStr == null ? null : makeType(expectedTypeStr);
|
||||
assertEquals(expectedType, type);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user