Refactoring done, something broken in label resolution
This commit is contained in:
@@ -2,10 +2,12 @@ package org.jetbrains.jet.lang;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTyperServices;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -44,13 +46,12 @@ public class JetSemanticServices {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetTypeInferrer.Services getTypeInferrerServices(@NotNull BindingTrace trace) {
|
||||
return new JetTypeInferrer(this).getServices(trace);
|
||||
public ExpressionTyperServices getTypeInferrerServices(@NotNull BindingTrace trace) {
|
||||
return new ExpressionTyperServices(this, trace);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetTypeChecker getTypeChecker() {
|
||||
return typeChecker;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
@@ -216,7 +216,7 @@ public class JetControlFlowProcessor {
|
||||
builder.unsupported(expression); // TODO
|
||||
}
|
||||
}
|
||||
else if (JetTypeInferrer.assignmentOperationNames.containsKey(operationType)) {
|
||||
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
if (left != null) {
|
||||
value(left, false);
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
import org.jetbrains.jet.util.lazy.LazyValue;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -4,21 +4,23 @@ import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetAnnotationEntry;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetModifierList;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -34,7 +36,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(semanticServices), DataFlowInfo.getEmpty());
|
||||
this.callResolver = new CallResolver(semanticServices, DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -6,15 +6,17 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.Queue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTyperServices;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
|
||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||
|
||||
import java.util.*;
|
||||
@@ -23,7 +25,7 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPES;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DeferredTypeKey.DEFERRED_TYPE_KEY;
|
||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -125,7 +127,7 @@ public class BodyResolver {
|
||||
final JetScope scopeForConstructor = primaryConstructor == null
|
||||
? null
|
||||
: getInnerScopeForConstructor(primaryConstructor, descriptor.getScopeForMemberResolution(), true);
|
||||
final JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors); // TODO : flow
|
||||
final ExpressionTyperServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors); // TODO : flow
|
||||
|
||||
final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
|
||||
JetVisitorVoid visitor = new JetVisitorVoid() {
|
||||
@@ -292,7 +294,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()); // TODO : flow
|
||||
ExpressionTyperServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(createFieldAssignTrackingTrace()); // TODO : flow
|
||||
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
|
||||
typeInferrer.getType(scopeForConstructor, anonymousInitializer.getBody(), NO_EXPECTED_TYPE);
|
||||
}
|
||||
@@ -318,7 +320,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);
|
||||
final ExpressionTyperServices typeInferrerForInitializers = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
|
||||
JetClass containingClass = PsiTreeUtil.getParentOfType(declaration, JetClass.class);
|
||||
assert containingClass != null : "This must be guaranteed by the parser";
|
||||
@@ -382,7 +384,7 @@ public class BodyResolver {
|
||||
if (bodyExpression != null) {
|
||||
//context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
//JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData(declaration, bodyExpression);
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
ExpressionTyperServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
|
||||
typeInferrer.checkFunctionReturnType(functionInnerScope, declaration, descriptor, JetStandardClasses.getUnitType());
|
||||
}
|
||||
@@ -520,7 +522,7 @@ 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);
|
||||
ExpressionTyperServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(traceForConstructors);
|
||||
JetType type = typeInferrer.getType(getPropertyDeclarationInnerScope(scope, propertyDescriptor), initializer, NO_EXPECTED_TYPE);
|
||||
|
||||
JetType expectedType = propertyDescriptor.getInType();
|
||||
@@ -556,12 +558,12 @@ 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);
|
||||
ExpressionTyperServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
|
||||
typeInferrer.checkFunctionReturnType(declaringScope, function, functionDescriptor);
|
||||
}
|
||||
|
||||
JetTypeInferrer.Services typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
ExpressionTyperServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace);
|
||||
List<JetParameter> valueParameters = function.getValueParameters();
|
||||
for (int i = 0; i < valueParameters.size(); i++) {
|
||||
ValueParameterDescriptor valueParameterDescriptor = functionDescriptor.getValueParameters().get(i);
|
||||
|
||||
@@ -22,6 +22,8 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.util.lazy.LazyValue;
|
||||
import org.jetbrains.jet.util.lazy.LazyValueWithDefault;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -541,7 +543,7 @@ public class ClassDescriptorResolver {
|
||||
@Override
|
||||
protected JetType compute() {
|
||||
//JetFlowInformationProvider flowInformationProvider = computeFlowData(property, initializer);
|
||||
return semanticServices.getTypeInferrerServices(trace).safeGetType(scope, initializer, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
return semanticServices.getTypeInferrerServices(trace).safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE);
|
||||
}
|
||||
};
|
||||
if (allowDeferred) {
|
||||
|
||||
@@ -10,22 +10,21 @@ 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 org.jetbrains.jet.lang.types.expressions.ExpressionTyperServices;
|
||||
|
||||
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;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
/**
|
||||
* @author svtk
|
||||
*/
|
||||
public class ControlFlowAnalyzer {
|
||||
private TopDownAnalysisContext context;
|
||||
private JetTypeInferrer.Services typeInferrer;
|
||||
private ExpressionTyperServices typeInferrer;
|
||||
|
||||
public ControlFlowAnalyzer(TopDownAnalysisContext context) {
|
||||
this.context = context;
|
||||
|
||||
@@ -8,7 +8,6 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
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.psi.*;
|
||||
@@ -16,6 +15,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WriteThroughScope;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTyperServices;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
@@ -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());
|
||||
ExpressionTyperServices typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
|
||||
JetType type = typeInferrerServices.getTypeWithNamespaces(namespaceScope, importedReference);
|
||||
if (type != null) {
|
||||
namespaceScope.importScope(type.getMemberScope());
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.util.lazy.LazyValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.jetbrains.jet.lang.resolve.calls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.jetbrains.jet.lang.psi.JetThisExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.lang.ASTNode;
|
||||
@@ -15,6 +15,8 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTyperServices;
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
@@ -26,20 +28,17 @@ import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.*;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_CANDIDATE;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_RESULT;
|
||||
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class CallResolver {
|
||||
|
||||
private final JetTypeInferrer typeInferrer;
|
||||
private final JetSemanticServices semanticServices;
|
||||
private final OverloadingConflictResolver overloadingConflictResolver;
|
||||
private final DataFlowInfo dataFlowInfo;
|
||||
|
||||
public CallResolver(JetSemanticServices semanticServices, JetTypeInferrer typeInferrer, DataFlowInfo dataFlowInfo) {
|
||||
this.typeInferrer = typeInferrer;
|
||||
public CallResolver(JetSemanticServices semanticServices, DataFlowInfo dataFlowInfo) {
|
||||
this.semanticServices = semanticServices;
|
||||
this.overloadingConflictResolver = new OverloadingConflictResolver(semanticServices);
|
||||
this.dataFlowInfo = dataFlowInfo;
|
||||
@@ -301,7 +300,7 @@ public class CallResolver {
|
||||
if (callElement instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) callElement;
|
||||
JetSimpleNameExpression operationReference = binaryExpression.getOperationReference();
|
||||
String operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ? operationReference.getText() : JetTypeInferrer.getNameForOperationSymbol(operationReference.getReferencedNameElementType());
|
||||
String operationString = operationReference.getReferencedNameElementType() == JetTokens.IDENTIFIER ? operationReference.getText() : OperatorConventions.getNameForOperationSymbol(operationReference.getReferencedNameElementType());
|
||||
trace.report(UNSAFE_INFIX_CALL.on(reference, binaryExpression.getLeft().getText(), operationString, binaryExpression.getRight().getText()));
|
||||
}
|
||||
else {
|
||||
@@ -385,7 +384,7 @@ public class CallResolver {
|
||||
for (JetExpression expression : valueArgument.getArgumentExpressions()) {
|
||||
// JetExpression expression = valueArgument.getArgumentExpression();
|
||||
// TODO : more attempts, with different expected types
|
||||
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
|
||||
ExpressionTyperServices temporaryServices = new ExpressionTyperServices(semanticServices, temporaryTrace);
|
||||
JetType type = temporaryServices.getType(scope, expression, NO_EXPECTED_TYPE);
|
||||
if (type != null) {
|
||||
constraintSystem.addSubtypingConstraint(type, valueParameterDescriptor.getOutType());
|
||||
@@ -510,15 +509,16 @@ public class CallResolver {
|
||||
}
|
||||
|
||||
private void checkTypesWithNoCallee(BindingTrace trace, JetScope scope, Call call) {
|
||||
ExpressionTyperServices typeInferrerServices = new ExpressionTyperServices(semanticServices, trace);
|
||||
for (ValueArgument valueArgument : call.getValueArguments()) {
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
if (argumentExpression != null) {
|
||||
typeInferrer.getServices(trace).getType(scope, argumentExpression, NO_EXPECTED_TYPE);
|
||||
typeInferrerServices.getType(scope, argumentExpression, NO_EXPECTED_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
for (JetExpression expression : call.getFunctionLiteralArguments()) {
|
||||
typeInferrer.getServices(trace).getType(scope, expression, NO_EXPECTED_TYPE);
|
||||
typeInferrerServices.getType(scope, expression, NO_EXPECTED_TYPE);
|
||||
}
|
||||
|
||||
for (JetTypeProjection typeProjection : call.getTypeArguments()) {
|
||||
@@ -602,7 +602,7 @@ public class CallResolver {
|
||||
|
||||
List<JetExpression> argumentExpressions = resolvedArgument.getArgumentExpressions();
|
||||
for (JetExpression argumentExpression : argumentExpressions) {
|
||||
JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(candidateCall.getTrace());
|
||||
ExpressionTyperServices temporaryServices = new ExpressionTyperServices(semanticServices, candidateCall.getTrace());
|
||||
JetType type = temporaryServices.getType(scope, argumentExpression, parameterType);
|
||||
if (type == null) {
|
||||
candidateCall.argumentHasNoType();
|
||||
|
||||
+3
-1
@@ -1,10 +1,12 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
package org.jetbrains.jet.lang.resolve.calls;
|
||||
|
||||
import com.google.common.collect.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.util.CommonSuppliers;
|
||||
|
||||
import java.util.*;
|
||||
@@ -4,7 +4,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.Call;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import org.jetbrains.jet.lang.psi.Call;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||
|
||||
-1
@@ -8,7 +8,6 @@ import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.CallMaker;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
+1
-1
@@ -260,7 +260,7 @@ public class CompileTimeConstantResolver {
|
||||
}
|
||||
|
||||
private boolean noExpectedType(JetType expectedType) {
|
||||
return expectedType == JetTypeInferrer.NO_EXPECTED_TYPE || JetStandardClasses.isUnit(expectedType);
|
||||
return expectedType == TypeUtils.NO_EXPECTED_TYPE || JetStandardClasses.isUnit(expectedType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.resolve.scopes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.resolve.AbstractScopeAdapter;
|
||||
import org.jetbrains.jet.lang.types.LazyValue;
|
||||
import org.jetbrains.jet.util.lazy.LazyValue;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
|
||||
@@ -4,6 +4,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.util.lazy.LazyValue;
|
||||
import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class DfsNodeHandler<R> {
|
||||
|
||||
public void beforeChildren(JetType current) {
|
||||
|
||||
}
|
||||
|
||||
public void afterChildren(JetType current) {
|
||||
|
||||
}
|
||||
|
||||
public R result() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,7 @@ public class ErrorUtils {
|
||||
}
|
||||
|
||||
public static boolean isErrorType(@NotNull JetType type) {
|
||||
return type != JetTypeInferrer.NO_EXPECTED_TYPE &&(
|
||||
return type != TypeUtils.NO_EXPECTED_TYPE &&(
|
||||
(type instanceof DeferredType && ((DeferredType) type).getActualType() == null) ||
|
||||
type instanceof ErrorTypeImpl ||
|
||||
isError(type.getConstructor()));
|
||||
|
||||
@@ -598,4 +598,20 @@ public class JetTypeChecker {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class DfsNodeHandler<R> {
|
||||
|
||||
public void beforeChildren(JetType current) {
|
||||
|
||||
}
|
||||
|
||||
public void afterChildren(JetType current) {
|
||||
|
||||
}
|
||||
|
||||
public R result() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,75 @@ import java.util.*;
|
||||
* @author abreslav
|
||||
*/
|
||||
public class TypeUtils {
|
||||
public static final JetType FORBIDDEN = new JetType() {
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeConstructor getConstructor() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TypeProjection> getArguments() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetScope getMemberScope() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AnnotationDescriptor> getAnnotations() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FORBIDDEN";
|
||||
}
|
||||
};
|
||||
public static final JetType NO_EXPECTED_TYPE = new JetType() {
|
||||
@NotNull
|
||||
@Override
|
||||
public TypeConstructor getConstructor() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<TypeProjection> getArguments() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNullable() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetScope getMemberScope() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AnnotationDescriptor> getAnnotations() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NO_EXPECTED_TYPE";
|
||||
}
|
||||
};
|
||||
|
||||
public static JetType makeNullable(@NotNull JetType type) {
|
||||
return makeNullableAsSpecified(type, true);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public enum CoercionStrategy {
|
||||
NO_COERCION,
|
||||
COERCION_TO_UNIT
|
||||
}
|
||||
+484
@@ -0,0 +1,484 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptorUtil;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithPsiElement;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.AutoCastUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.TYPE_MISMATCH;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ExpressionTyperServices {
|
||||
private final JetSemanticServices semanticServices;
|
||||
private final BindingTrace trace;
|
||||
|
||||
private final ExpressionTyperVisitor expressionTyperVisitor;
|
||||
private final CallResolver callResolver;
|
||||
|
||||
public ExpressionTyperServices(JetSemanticServices semanticServices, BindingTrace trace) {
|
||||
this.semanticServices = semanticServices;
|
||||
this.trace = trace;
|
||||
this.expressionTyperVisitor = new ExpressionTyperVisitor();
|
||||
this.callResolver = new CallResolver(semanticServices, DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
public ExpressionTyperVisitorWithWritableScope newTypeInferrerVisitorWithWritableScope(WritableScope scope) {
|
||||
return new ExpressionTyperVisitorWithWritableScope(scope);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType safeGetType(@NotNull JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType) {
|
||||
JetType type = getType(scope, expression, expectedType);
|
||||
if (type != null) {
|
||||
return type;
|
||||
}
|
||||
return ErrorUtils.createErrorType("Type for " + expression.getText());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType) {
|
||||
return expressionTyperVisitor.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), expectedType, TypeUtils.FORBIDDEN));
|
||||
}
|
||||
|
||||
public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression) {
|
||||
return ExpressionTyperVisitorWithNamespaces.INSTANCE.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.NO_EXPECTED_TYPE));
|
||||
}
|
||||
|
||||
public CallResolver getCallResolver() {
|
||||
return callResolver;
|
||||
}
|
||||
|
||||
// TODO JetElement -> JetWhenConditionCall || JetQualifiedExpression
|
||||
// private void checkNullSafety(@Nullable JetType receiverType, @NotNull ASTNode operationTokenNode, @Nullable FunctionDescriptor callee, @NotNull JetElement element) {
|
||||
// if (receiverType != null && callee != null) {
|
||||
// boolean namespaceType = receiverType instanceof NamespaceType;
|
||||
// boolean nullableReceiver = !namespaceType && receiverType.isNullable();
|
||||
// ReceiverDescriptor calleeReceiver = callee.getReceiverParameter();
|
||||
// boolean calleeForbidsNullableReceiver = !calleeReceiver.exists() || !calleeReceiver.getType().isNullable();
|
||||
//
|
||||
// IElementType operationSign = operationTokenNode.getElementType();
|
||||
// if (nullableReceiver && calleeForbidsNullableReceiver && operationSign == JetTokens.DOT) {
|
||||
//// trace.getErrorHandler().genericError(operationTokenNode, "Only safe calls (?.) are allowed on a nullable receiver of type " + receiverType);
|
||||
// trace.report(UNSAFE_CALL.on(operationTokenNode, receiverType));
|
||||
// }
|
||||
// else if ((!nullableReceiver || !calleeForbidsNullableReceiver) && operationSign == JetTokens.SAFE_ACCESS) {
|
||||
// if (namespaceType) {
|
||||
//// trace.getErrorHandler().genericError(operationTokenNode, "Safe calls are not allowed on namespaces");
|
||||
// trace.report(SAFE_CALLS_ARE_NOT_ALLOWED_ON_NAMESPACES.on(operationTokenNode));
|
||||
// }
|
||||
// else {
|
||||
//// trace.getErrorHandler().genericWarning(operationTokenNode, "Unnecessary safe call on a non-null receiver of type " + receiverType);
|
||||
//
|
||||
// trace.report(UNNECESSARY_SAFE_CALL.on(element, operationTokenNode, receiverType));
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) {
|
||||
checkFunctionReturnType(outerScope, function, functionDescriptor, DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
/*package*/ void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, DataFlowInfo dataFlowInfo) {
|
||||
JetType expectedReturnType = functionDescriptor.getReturnType();
|
||||
if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) {
|
||||
expectedReturnType = TypeUtils.NO_EXPECTED_TYPE;
|
||||
}
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, expectedReturnType, dataFlowInfo);
|
||||
// Map<JetElement, JetType> typeMap = collectReturnedExpressionsWithTypes(outerScope, function, functionDescriptor, expectedReturnType);
|
||||
// if (typeMap.isEmpty()) {
|
||||
// return; // The function returns Nothing
|
||||
// }
|
||||
// for (Map.Entry<JetElement, JetType> entry : typeMap.entrySet()) {
|
||||
// JetType actualType = entry.castValue();
|
||||
// JetElement element = entry.getKey();
|
||||
// JetTypeChecker typeChecker = semanticServices.getTypeChecker();
|
||||
// if (!typeChecker.isSubtypeOf(actualType, expectedReturnType)) {
|
||||
// if (typeChecker.isConvertibleBySpecialConversion(actualType, expectedReturnType)) {
|
||||
// if (expectedReturnType.getConstructor().equals(JetStandardClasses.getUnitType().getConstructor())
|
||||
// && element.getParent() instanceof JetReturnExpression) {
|
||||
// context.trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type Unit");
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (element == function) {
|
||||
// JetExpression bodyExpression = function.getBodyExpression();
|
||||
// assert bodyExpression != null;
|
||||
// context.trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType);
|
||||
// }
|
||||
// else if (element instanceof JetExpression) {
|
||||
// JetExpression expression = (JetExpression) element;
|
||||
// context.trace.report(TYPE_MISMATCH.on(expression, expectedReturnType, actualType));
|
||||
// }
|
||||
// else {
|
||||
// context.trace.getErrorHandler().genericError(element.getNode(), "This function must return a value of type " + expectedReturnType);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @NotNull final JetType expectedReturnType) {
|
||||
checkFunctionReturnType(functionInnerScope, function, functionDescriptor, expectedReturnType, DataFlowInfo.getEmpty());
|
||||
}
|
||||
|
||||
/*package*/ void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @NotNull final JetType expectedReturnType, @NotNull DataFlowInfo dataFlowInfo) {
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
if (bodyExpression == null) return;
|
||||
|
||||
final boolean blockBody = function.hasBlockBody();
|
||||
final ExpressionTypingContext context =
|
||||
blockBody
|
||||
? ExpressionTypingContext.newRootContext(semanticServices, trace, functionInnerScope, dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, expectedReturnType)
|
||||
: ExpressionTypingContext.newRootContext(semanticServices, trace, functionInnerScope, dataFlowInfo, expectedReturnType, TypeUtils.FORBIDDEN);
|
||||
|
||||
if (function instanceof JetFunctionLiteralExpression) {
|
||||
JetFunctionLiteralExpression functionLiteralExpression = (JetFunctionLiteralExpression) function;
|
||||
getBlockReturnedType(functionInnerScope, functionLiteralExpression.getBodyExpression(), CoercionStrategy.COERCION_TO_UNIT, context);
|
||||
}
|
||||
else {
|
||||
expressionTyperVisitor.getType(bodyExpression, context);
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// 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.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
|
||||
// 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 = expressionTyperVisitor.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
|
||||
/*package*/ JetType getBlockReturnedType(@NotNull JetScope outerScope, @NotNull JetBlockExpression expression, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context) {
|
||||
List<JetElement> block = expression.getStatements();
|
||||
if (block.isEmpty()) {
|
||||
return checkType(JetStandardClasses.getUnitType(), expression, context);
|
||||
}
|
||||
|
||||
DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration();
|
||||
WritableScope scope = new WritableScopeImpl(outerScope, containingDescriptor, new TraceBasedRedeclarationHandler(context.trace)).setDebugName("getBlockReturnedType");
|
||||
return getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JetType inferFunctionReturnType(@NotNull JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor 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<JetExpression, JetType> collectReturnedExpressionsWithTypes(
|
||||
final @NotNull BindingTrace trace,
|
||||
JetScope outerScope,
|
||||
final JetDeclarationWithBody function,
|
||||
FunctionDescriptor functionDescriptor) {
|
||||
JetExpression bodyExpression = function.getBodyExpression();
|
||||
assert bodyExpression != null;
|
||||
JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
|
||||
expressionTyperVisitor.getType(bodyExpression, ExpressionTypingContext.newRootContext(semanticServices, trace, functionInnerScope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.FORBIDDEN));
|
||||
//todo function literals
|
||||
final Collection<JetExpression> returnedExpressions = new ArrayList<JetExpression>();
|
||||
if (function.hasBlockBody()) {
|
||||
//now this code is never invoked!, it should be invoked for inference of return type of function literal with local returns
|
||||
bodyExpression.visit(new JetTreeVisitor<JetDeclarationWithBody>() {
|
||||
@Override
|
||||
public Void visitReturnExpression(JetReturnExpression expression, JetDeclarationWithBody outerFunction) {
|
||||
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
PsiElement element = targetLabel != null ? trace.get(LABEL_TARGET, targetLabel) : null;
|
||||
if (element == function || (targetLabel == null && outerFunction == function)) {
|
||||
returnedExpressions.add(expression);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, JetDeclarationWithBody outerFunction) {
|
||||
return super.visitFunctionLiteralExpression(expression, expression.getFunctionLiteral());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitNamedFunction(JetNamedFunction function, JetDeclarationWithBody outerFunction) {
|
||||
return super.visitNamedFunction(function, function);
|
||||
}
|
||||
}, function);
|
||||
}
|
||||
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);
|
||||
if (cachedType != null) {
|
||||
typeMap.put(returnedExpression, cachedType);
|
||||
}
|
||||
}
|
||||
return typeMap;
|
||||
}
|
||||
|
||||
/*package*/ JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List<? extends JetElement> block, @NotNull CoercionStrategy coercionStrategyForLastExpression, ExpressionTypingContext context) {
|
||||
if (block.isEmpty()) {
|
||||
return JetStandardClasses.getUnitType();
|
||||
}
|
||||
|
||||
ExpressionTyperVisitorWithWritableScope blockLevelVisitor = newTypeInferrerVisitorWithWritableScope(scope);
|
||||
ExpressionTypingContext newContext = ExpressionTypingContext.newRootContext(semanticServices, trace, scope, context.dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, context.expectedReturnType);
|
||||
|
||||
JetType result = null;
|
||||
for (Iterator<? extends JetElement> iterator = block.iterator(); iterator.hasNext(); ) {
|
||||
final JetElement statement = iterator.next();
|
||||
trace.record(STATEMENT, statement);
|
||||
final JetExpression statementExpression = (JetExpression) statement;
|
||||
//TODO constructor assert context.expectedType != FORBIDDEN : ""
|
||||
if (!iterator.hasNext()) {
|
||||
if (context.expectedType != TypeUtils.NO_EXPECTED_TYPE) {
|
||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT && JetStandardClasses.isUnit(context.expectedType)) {
|
||||
// This implements coercion to Unit
|
||||
TemporaryBindingTrace temporaryTraceExpectingUnit = TemporaryBindingTrace.create(trace);
|
||||
final boolean[] mismatch = new boolean[1];
|
||||
ObservableBindingTrace errorInterceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceExpectingUnit, statementExpression, mismatch);
|
||||
newContext = ExpressionTypingContext.newRootContext(semanticServices, errorInterceptingTrace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
if (mismatch[0]) {
|
||||
TemporaryBindingTrace temporaryTraceNoExpectedType = TemporaryBindingTrace.create(trace);
|
||||
mismatch[0] = false;
|
||||
ObservableBindingTrace interceptingTrace = makeTraceInterceptingTypeMismatch(temporaryTraceNoExpectedType, statementExpression, mismatch);
|
||||
newContext = ExpressionTypingContext.newRootContext(semanticServices, interceptingTrace, scope, newContext.dataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, context.expectedReturnType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
if (mismatch[0]) {
|
||||
temporaryTraceExpectingUnit.commit();
|
||||
}
|
||||
else {
|
||||
temporaryTraceNoExpectedType.commit();
|
||||
}
|
||||
}
|
||||
else {
|
||||
temporaryTraceExpectingUnit.commit();
|
||||
}
|
||||
}
|
||||
else {
|
||||
newContext = ExpressionTypingContext.newRootContext(semanticServices, trace, scope, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType);
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
if (coercionStrategyForLastExpression == CoercionStrategy.COERCION_TO_UNIT) {
|
||||
boolean mightBeUnit = false;
|
||||
if (statementExpression instanceof JetDeclaration) {
|
||||
mightBeUnit = true;
|
||||
}
|
||||
if (statementExpression instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) statementExpression;
|
||||
IElementType operationType = binaryExpression.getOperationToken();
|
||||
if (operationType == JetTokens.EQ || OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||
mightBeUnit = true;
|
||||
}
|
||||
}
|
||||
if (mightBeUnit) {
|
||||
// ExpressionTyperVisitorWithWritableScope should return only null or Unit for declarations and assignments
|
||||
assert result == null || JetStandardClasses.isUnit(result);
|
||||
result = JetStandardClasses.getUnitType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = blockLevelVisitor.getType(statementExpression, newContext);
|
||||
}
|
||||
|
||||
DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo();
|
||||
if (newDataFlowInfo == null) {
|
||||
newDataFlowInfo = context.dataFlowInfo;
|
||||
}
|
||||
if (newDataFlowInfo != context.dataFlowInfo) {
|
||||
newContext = ExpressionTypingContext.newRootContext(semanticServices, trace, scope, newDataFlowInfo, TypeUtils.NO_EXPECTED_TYPE, context.expectedReturnType);
|
||||
}
|
||||
blockLevelVisitor.resetResult(); // TODO : maybe it's better to recreate the visitors with the same scope?
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ObservableBindingTrace makeTraceInterceptingTypeMismatch(final BindingTrace trace, final JetExpression expressionToWatch, final boolean[] mismatchFound) {
|
||||
return new ObservableBindingTrace(trace) {
|
||||
|
||||
@Override
|
||||
public void report(@NotNull Diagnostic diagnostic) {
|
||||
if (diagnostic.getFactory() == TYPE_MISMATCH && ((DiagnosticWithPsiElement) diagnostic).getPsiElement() == expressionToWatch) {
|
||||
mismatchFound[0] = true;
|
||||
}
|
||||
super.report(diagnostic);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// //TODO
|
||||
// private JetType enrichOutType(JetExpression expression, JetType initialType, @NotNull ExpressionTypingContext context) {
|
||||
// if (expression == null) return initialType;
|
||||
// VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression, context);
|
||||
// if (variableDescriptor != null) {
|
||||
// return context.dataFlowInfo.getOutType(variableDescriptor);
|
||||
// }
|
||||
// return initialType;
|
||||
// }
|
||||
|
||||
// @Nullable
|
||||
// private JetType checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context) {
|
||||
// if (expressionType != null && context.expectedType != null && context.expectedType != NO_EXPECTED_TYPE) {
|
||||
// if (!semanticServices.getTypeChecker().isSubtypeOf(expressionType, context.expectedType)) {
|
||||
// context.trace.report(TYPE_MISMATCH.on(expression, context.expectedType, expressionType));
|
||||
// }
|
||||
// }
|
||||
// return expressionType;
|
||||
// }
|
||||
|
||||
@Nullable
|
||||
/*package*/ JetType checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull ExpressionTypingContext context) {
|
||||
if (expressionType == null || context.expectedType == null || context.expectedType == TypeUtils.NO_EXPECTED_TYPE ||
|
||||
semanticServices.getTypeChecker().isSubtypeOf(expressionType, context.expectedType)) {
|
||||
return expressionType;
|
||||
}
|
||||
// VariableDescriptor variableDescriptor = AutoCastUtils.getVariableDescriptorFromSimpleName(context.trace.getBindingContext(), expression);
|
||||
// boolean appropriateTypeFound = false;
|
||||
// if (variableDescriptor != null) {
|
||||
// List<JetType> possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypesForVariable(variableDescriptor));
|
||||
// Collections.reverse(possibleTypes);
|
||||
// for (JetType possibleType : possibleTypes) {
|
||||
// if (semanticServices.getTypeChecker().isSubtypeOf(possibleType, context.expectedType)) {
|
||||
// appropriateTypeFound = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (!appropriateTypeFound) {
|
||||
// JetType notnullType = context.dataFlowInfo.getOutType(variableDescriptor);
|
||||
// if (notnullType != null && semanticServices.getTypeChecker().isSubtypeOf(notnullType, context.expectedType)) {
|
||||
// appropriateTypeFound = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (AutoCastUtils.castExpression(expression, context.expectedType, context.dataFlowInfo, context.trace) == null) {
|
||||
// context.trace.getErrorHandler().typeMismatch(expression, context.expectedType, expressionType);
|
||||
context.trace.report(TYPE_MISMATCH.on(expression, context.expectedType, expressionType));
|
||||
return expressionType;
|
||||
}
|
||||
// checkAutoCast(expression, context.expectedType, variableDescriptor, context.trace);
|
||||
return context.expectedType;
|
||||
}
|
||||
|
||||
// private void checkAutoCast(JetExpression expression, JetType type, VariableDescriptor variableDescriptor, BindingTrace trace) {
|
||||
// if (variableDescriptor.isVar()) {
|
||||
//// trace.getErrorHandler().genericError(expression.getNode(), "Automatic cast to " + type + " is impossible, because variable " + variableDescriptor.getName() + " is mutable");
|
||||
// trace.report(AUTOCAST_IMPOSSIBLE.on(expression, type, variableDescriptor));
|
||||
// } else {
|
||||
// trace.record(BindingContext.AUTOCAST, expression, type);
|
||||
// }
|
||||
// }
|
||||
|
||||
@NotNull
|
||||
/*package*/ List<JetType> checkArgumentTypes(@NotNull List<JetType> argumentTypes, @NotNull List<JetExpression> arguments, @NotNull List<TypeProjection> expectedArgumentTypes, @NotNull ExpressionTypingContext context) {
|
||||
if (arguments.size() == 0 || argumentTypes.size() != arguments.size() || expectedArgumentTypes.size() != arguments.size()) {
|
||||
return argumentTypes;
|
||||
}
|
||||
List<JetType> result = Lists.newArrayListWithCapacity(arguments.size());
|
||||
for (int i = 0, argumentTypesSize = argumentTypes.size(); i < argumentTypesSize; i++) {
|
||||
result.add(checkType(argumentTypes.get(i), arguments.get(i), context.replaceExpectedType(expectedArgumentTypes.get(i).getType())));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
/*package*/ VariableDescriptor getVariableDescriptorFromSimpleName(@NotNull JetExpression receiverExpression, @NotNull ExpressionTypingContext context) {
|
||||
if (receiverExpression instanceof JetBinaryExpressionWithTypeRHS) {
|
||||
JetBinaryExpressionWithTypeRHS expression = (JetBinaryExpressionWithTypeRHS) receiverExpression;
|
||||
if (expression.getOperationSign().getReferencedNameElementType() == JetTokens.COLON) {
|
||||
return getVariableDescriptorFromSimpleName(expression.getLeft(), context);
|
||||
}
|
||||
}
|
||||
VariableDescriptor variableDescriptor = null;
|
||||
if (receiverExpression instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) receiverExpression;
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(REFERENCE_TARGET, nameExpression);
|
||||
if (declarationDescriptor instanceof VariableDescriptor) {
|
||||
variableDescriptor = (VariableDescriptor) declarationDescriptor;
|
||||
}
|
||||
}
|
||||
return variableDescriptor;
|
||||
}
|
||||
}
|
||||
+1944
File diff suppressed because it is too large
Load Diff
+33
@@ -0,0 +1,33 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetRootNamespaceExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
|
||||
import org.jetbrains.jet.lang.resolve.JetModuleUtil;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ExpressionTyperVisitorWithNamespaces extends ExpressionTyperVisitor {
|
||||
public static final ExpressionTyperVisitorWithNamespaces INSTANCE = new ExpressionTyperVisitorWithNamespaces();
|
||||
|
||||
private ExpressionTyperVisitorWithNamespaces() {}
|
||||
|
||||
@Override
|
||||
public boolean isNamespacePosition() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitRootNamespaceExpression(JetRootNamespaceExpression expression, ExpressionTypingContext context) {
|
||||
return context.getServices().checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName, @NotNull JetType[] result, ExpressionTypingContext context) {
|
||||
result[0] = lookupNamespaceType(expression, referencedName, context);
|
||||
return result[0] != null;
|
||||
}
|
||||
|
||||
}
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
|
||||
import org.jetbrains.jet.lang.resolve.calls.AutoCastUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.MUST_BE_WRAPPED_IN_A_REF;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class ExpressionTyperVisitorWithWritableScope extends ExpressionTyperVisitor {
|
||||
private final WritableScope scope;
|
||||
|
||||
public ExpressionTyperVisitorWithWritableScope(@NotNull WritableScope scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitObjectDeclaration(JetObjectDeclaration declaration, ExpressionTypingContext context) {
|
||||
TopDownAnalyzer.processObject(context.semanticServices, context.trace, scope, scope.getContainingDeclaration(), declaration);
|
||||
ClassDescriptor classDescriptor = context.trace.getBindingContext().get(BindingContext.CLASS, declaration);
|
||||
if (classDescriptor != null) {
|
||||
PropertyDescriptor propertyDescriptor = context.getClassDescriptorResolver().resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor);
|
||||
scope.addVariableDescriptor(propertyDescriptor);
|
||||
}
|
||||
return checkExpectedType(declaration, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitProperty(JetProperty property, ExpressionTypingContext context) {
|
||||
JetTypeReference receiverTypeRef = property.getReceiverTypeRef();
|
||||
if (receiverTypeRef != null) {
|
||||
// context.trace.getErrorHandler().genericError(receiverTypeRef.getNode(), "Local receiver-properties are not allowed");
|
||||
context.trace.report(LOCAL_EXTENSION_PROPERTY.on(receiverTypeRef));
|
||||
}
|
||||
|
||||
JetPropertyAccessor getter = property.getGetter();
|
||||
if (getter != null) {
|
||||
// context.trace.getErrorHandler().genericError(getter.getNode(), "Local variables are not allowed to have getters");
|
||||
context.trace.report(LOCAL_VARIABLE_WITH_GETTER.on(getter));
|
||||
}
|
||||
|
||||
JetPropertyAccessor setter = property.getSetter();
|
||||
if (setter != null) {
|
||||
// context.trace.getErrorHandler().genericError(setter.getNode(), "Local variables are not allowed to have setters");
|
||||
context.trace.report(LOCAL_VARIABLE_WITH_SETTER.on(setter));
|
||||
}
|
||||
|
||||
VariableDescriptor propertyDescriptor = context.getClassDescriptorResolver().resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, property);
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (property.getPropertyTypeRef() != null && initializer != null) {
|
||||
JetType outType = propertyDescriptor.getOutType();
|
||||
JetType initializerType = getType(initializer, context.replaceExpectedType(outType).replaceScope(scope));
|
||||
// if (outType != null &&
|
||||
// initializerType != null &&
|
||||
// !semanticServices.getTypeChecker().isConvertibleTo(initializerType, outType)) {
|
||||
// context.trace.report(TYPE_MISMATCH.on(initializer, outType, initializerType));
|
||||
// }
|
||||
}
|
||||
|
||||
scope.addVariableDescriptor(propertyDescriptor);
|
||||
return checkExpectedType(property, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) {
|
||||
FunctionDescriptorImpl functionDescriptor = context.getClassDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function);
|
||||
scope.addFunctionDescriptor(functionDescriptor);
|
||||
context.getServices().checkFunctionReturnType(context.scope, function, functionDescriptor, context.dataFlowInfo);
|
||||
return checkExpectedType(function, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitClass(JetClass klass, ExpressionTypingContext context) {
|
||||
return super.visitClass(klass, context); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitTypedef(JetTypedef typedef, ExpressionTypingContext context) {
|
||||
return super.visitTypedef(typedef, context); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitDeclaration(JetDeclaration dcl, ExpressionTypingContext context) {
|
||||
return checkExpectedType(dcl, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JetType visitAssignmentOperation(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
String name = OperatorConventions.ASSIGNMENT_OPERATIONS.get(operationType);
|
||||
|
||||
TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace);
|
||||
JetType assignmentOperationType = getTypeForBinaryCall(scope, name, context.replaceBindingTrace(temporaryBindingTrace), expression);
|
||||
|
||||
if (assignmentOperationType == null) {
|
||||
String counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
||||
|
||||
JetType typeForBinaryCall = getTypeForBinaryCall(scope, counterpartName, context, expression);
|
||||
if (typeForBinaryCall != null) {
|
||||
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
||||
}
|
||||
}
|
||||
else {
|
||||
temporaryBindingTrace.commit();
|
||||
}
|
||||
return checkExpectedType(expression, context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JetType checkExpectedType(JetExpression expression, ExpressionTypingContext context) {
|
||||
if (context.expectedType != TypeUtils.NO_EXPECTED_TYPE) {
|
||||
if (JetStandardClasses.isUnit(context.expectedType)) {
|
||||
return JetStandardClasses.getUnitType();
|
||||
}
|
||||
context.trace.report(EXPECTED_TYPE_MISMATCH.on(expression, context.expectedType));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||
JetExpression left = expression.getLeft();
|
||||
JetExpression deparenthesized = JetPsiUtil.deparenthesize(left);
|
||||
JetExpression right = expression.getRight();
|
||||
if (deparenthesized instanceof JetArrayAccessExpression) {
|
||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) deparenthesized;
|
||||
return resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context);
|
||||
}
|
||||
JetType leftType = getType(left, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope));
|
||||
if (right != null) {
|
||||
JetType rightType = getType(right, context.replaceExpectedType(leftType).replaceScope(scope));
|
||||
// if (rightType != null &&
|
||||
// leftType != null &&
|
||||
// !semanticServices.getTypeChecker().isConvertibleTo(rightType, leftType)) {
|
||||
// context.trace.report(TYPE_MISMATCH.on(right, leftType, rightType));
|
||||
// }
|
||||
}
|
||||
if (left instanceof JetSimpleNameExpression) {
|
||||
JetSimpleNameExpression simpleName = (JetSimpleNameExpression) left;
|
||||
String referencedName = simpleName.getReferencedName();
|
||||
if (simpleName.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER
|
||||
&& referencedName != null) {
|
||||
PropertyDescriptor property = context.scope.getPropertyByFieldReference(referencedName);
|
||||
if (property != null) {
|
||||
context.trace.record(BindingContext.VARIABLE_ASSIGNMENT, simpleName, property);
|
||||
}
|
||||
}
|
||||
VariableDescriptor variable = AutoCastUtils.getVariableDescriptorFromSimpleName(context.trace.getBindingContext(), simpleName);
|
||||
if (variable != null) {
|
||||
DeclarationDescriptor containingDeclaration = variable.getContainingDeclaration();
|
||||
if (context.scope.getContainingDeclaration() != containingDeclaration && containingDeclaration instanceof CallableDescriptor) {
|
||||
context.trace.record(MUST_BE_WRAPPED_IN_A_REF, variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
return checkExpectedType(expression, context);
|
||||
}
|
||||
|
||||
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context) {
|
||||
ExpressionReceiver receiver = getExpressionReceiver(arrayAccessExpression.getArrayExpression(), context.replaceScope(scope));
|
||||
if (receiver == null) return null;
|
||||
//
|
||||
Call call = CallMaker.makeCall(receiver, arrayAccessExpression, rightHandSide);
|
||||
// // TODO : nasty hack: effort is duplicated
|
||||
// callResolver.resolveCallWithGivenName(
|
||||
// scope,
|
||||
// call,
|
||||
// arrayAccessExpression,
|
||||
// "set", arrayAccessExpression.getArrayExpression(), NO_EXPECTED_TYPE);
|
||||
FunctionDescriptor functionDescriptor = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
|
||||
call,
|
||||
arrayAccessExpression,
|
||||
"set", receiver);
|
||||
if (functionDescriptor == null) return null;
|
||||
context.trace.record(REFERENCE_TARGET, operationSign, functionDescriptor);
|
||||
return context.getServices().checkType(functionDescriptor.getReturnType(), arrayAccessExpression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitAnnotatedExpression(JetAnnotatedExpression expression, ExpressionTypingContext data) {
|
||||
return getType(expression.getBaseExpression(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JetType visitJetElement(JetElement element, ExpressionTypingContext context) {
|
||||
context.trace.report(UNSUPPORTED.on(element, "in a block"));
|
||||
// context.trace.getErrorHandler().genericError(element.getNode(), "Unsupported element in a block: " + element + " " + element.getClass().getCanonicalName());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.TypeResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
/*package*/ class ExpressionTypingContext {
|
||||
@NotNull
|
||||
public static ExpressionTypingContext newContext(
|
||||
@NotNull JetSemanticServices semanticServices,
|
||||
@NotNull Map<JetPattern, DataFlowInfo> patternsToDataFlowInfo,
|
||||
@NotNull Map<JetPattern, List<VariableDescriptor>> patternsToBoundVariableLists,
|
||||
@NotNull LabelResolver labelResolver,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull JetType expectedReturnType) {
|
||||
return new ExpressionTypingContext(semanticServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, expectedType, expectedReturnType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ExpressionTypingContext newRootContext(
|
||||
@NotNull JetSemanticServices semanticServices,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull JetType expectedReturnType) {
|
||||
return new ExpressionTypingContext(semanticServices, new HashMap<JetPattern, DataFlowInfo>(), new HashMap<JetPattern, List<VariableDescriptor>>(), new LabelResolver(), trace, scope, dataFlowInfo, expectedType, expectedReturnType);
|
||||
}
|
||||
|
||||
public final JetSemanticServices semanticServices;
|
||||
public final BindingTrace trace;
|
||||
public final JetScope scope;
|
||||
|
||||
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;
|
||||
public final LabelResolver labelResolver;
|
||||
|
||||
private CallResolver callResolver;
|
||||
private TypeResolver typeResolver;
|
||||
private ClassDescriptorResolver classDescriptorResolver;
|
||||
private ExpressionTyperServices services;
|
||||
private CompileTimeConstantResolver compileTimeConstantResolver;
|
||||
|
||||
private ExpressionTypingContext(
|
||||
@NotNull JetSemanticServices semanticServices,
|
||||
@NotNull Map<JetPattern, DataFlowInfo> patternsToDataFlowInfo,
|
||||
@NotNull Map<JetPattern, List<VariableDescriptor>> patternsToBoundVariableLists,
|
||||
@NotNull LabelResolver labelResolver,
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull DataFlowInfo dataFlowInfo,
|
||||
@NotNull JetType expectedType,
|
||||
@NotNull JetType expectedReturnType) {
|
||||
this.trace = trace;
|
||||
// this.typeResolver = new TypeResolver(semanticServices, trace, true);
|
||||
this.patternsToBoundVariableLists = patternsToBoundVariableLists;
|
||||
this.patternsToDataFlowInfo = patternsToDataFlowInfo;
|
||||
this.labelResolver = labelResolver;
|
||||
this.scope = scope;
|
||||
// this.services = new ExpressionTyperServices(semanticServices, trace);
|
||||
this.semanticServices = semanticServices;
|
||||
// this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
|
||||
this.dataFlowInfo = dataFlowInfo;
|
||||
this.expectedType = expectedType;
|
||||
this.expectedReturnType = expectedReturnType;
|
||||
}
|
||||
|
||||
public ExpressionTypingContext replaceDataFlowInfo(DataFlowInfo newDataFlowInfo) {
|
||||
return newContext(semanticServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, newDataFlowInfo, expectedType, expectedReturnType);
|
||||
}
|
||||
|
||||
public ExpressionTypingContext replaceExpectedType(@Nullable JetType newExpectedType) {
|
||||
if (newExpectedType == null) return replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
if (expectedType == newExpectedType) return this;
|
||||
return newContext(semanticServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, newExpectedType, expectedReturnType);
|
||||
}
|
||||
|
||||
public ExpressionTypingContext replaceExpectedReturnType(@Nullable JetType newExpectedReturnType) {
|
||||
if (newExpectedReturnType == null) return replaceExpectedReturnType(TypeUtils.NO_EXPECTED_TYPE);
|
||||
if (expectedReturnType == newExpectedReturnType) return this;
|
||||
return newContext(semanticServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, expectedType, newExpectedReturnType);
|
||||
}
|
||||
|
||||
public ExpressionTypingContext replaceBindingTrace(@NotNull BindingTrace newTrace) {
|
||||
if (newTrace == trace) return this;
|
||||
return newContext(semanticServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, newTrace, scope, dataFlowInfo, expectedType, expectedReturnType);
|
||||
}
|
||||
|
||||
public ExpressionTypingContext replaceExpectedTypeAndTrace(@NotNull JetType newExpectedType, @NotNull BindingTrace newTrace) {
|
||||
if (newExpectedType == expectedType && newTrace == trace) return this;
|
||||
return newContext(semanticServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, newTrace, scope, dataFlowInfo, newExpectedType, expectedReturnType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ExpressionTypingContext replaceScope(@NotNull JetScope newScope) {
|
||||
if (newScope == scope) return this;
|
||||
return newContext(semanticServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, newScope, dataFlowInfo, expectedType, expectedReturnType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ExpressionTypingContext replaceExpectedTypes(@NotNull JetType newExpectedType, @NotNull JetType newExpectedReturnType) {
|
||||
if (expectedType == newExpectedType && expectedReturnType == newExpectedReturnType) return this;
|
||||
return newContext(semanticServices, patternsToDataFlowInfo, patternsToBoundVariableLists, labelResolver, trace, scope, dataFlowInfo, newExpectedType, newExpectedReturnType);
|
||||
}
|
||||
|
||||
public CallResolver getCallResolver() {
|
||||
if (callResolver == null) {
|
||||
callResolver = new CallResolver(semanticServices, dataFlowInfo);
|
||||
}
|
||||
return callResolver;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name, @NotNull ReceiverDescriptor receiver) {
|
||||
return getCallResolver().resolveCallWithGivenName(trace, scope, call, functionReference, name, expectedType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) {
|
||||
return getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public VariableDescriptor resolveSimpleProperty(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetSimpleNameExpression nameExpression) {
|
||||
Call call = CallMaker.makePropertyCall(receiver, callOperationNode, nameExpression);
|
||||
return getCallResolver().resolveSimpleProperty(trace, scope, call, expectedType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public OverloadResolutionResults<FunctionDescriptor> resolveExactSignature(@NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List<JetType> parameterTypes) {
|
||||
return getCallResolver().resolveExactSignature(scope, receiver, name, parameterTypes);
|
||||
}
|
||||
|
||||
public ExpressionTyperServices getServices() {
|
||||
if (services == null) {
|
||||
services = new ExpressionTyperServices(semanticServices, trace);
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
public TypeResolver getTypeResolver() {
|
||||
if (typeResolver == null) {
|
||||
typeResolver = new TypeResolver(semanticServices, trace, true);
|
||||
}
|
||||
return typeResolver;
|
||||
}
|
||||
|
||||
public ClassDescriptorResolver getClassDescriptorResolver() {
|
||||
if (classDescriptorResolver == null) {
|
||||
classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace);
|
||||
}
|
||||
return classDescriptorResolver;
|
||||
}
|
||||
|
||||
public CompileTimeConstantResolver getCompileTimeConstantResolver() {
|
||||
if (compileTimeConstantResolver == null) {
|
||||
compileTimeConstantResolver = new CompileTimeConstantResolver(semanticServices, trace);
|
||||
}
|
||||
return compileTimeConstantResolver;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.AMBIGUOUS_LABEL;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.LABEL_NAME_CLASH;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.UNRESOLVED_REFERENCE;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DESCRIPTOR_TO_DECLARATION;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.LABEL_TARGET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class LabelResolver {
|
||||
|
||||
private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
|
||||
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
|
||||
public void exitLabeledElement(@NotNull 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 JetElement resolveControlLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, ExpressionTypingContext 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 FunctionDescriptor || declarationDescriptor instanceof ClassDescriptor) {
|
||||
element = (JetElement) context.trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declarationDescriptor);
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
context.trace.record(LABEL_TARGET, labelExpression, element);
|
||||
return element;
|
||||
}
|
||||
else if (size == 0) {
|
||||
return resolveNamedLabel(labelName, labelExpression, reportUnresolved, context);
|
||||
}
|
||||
context.trace.report(AMBIGUOUS_LABEL.on(labelExpression));
|
||||
return null;
|
||||
}
|
||||
|
||||
public void recordLabel(JetLabelQualifiedExpression expression, ExpressionTypingContext context) {
|
||||
JetSimpleNameExpression labelElement = expression.getTargetLabel();
|
||||
if (labelElement != null) {
|
||||
String labelName = expression.getLabelName();
|
||||
assert labelName != null;
|
||||
resolveControlLabel(labelName, labelElement, true, context);
|
||||
}
|
||||
}
|
||||
|
||||
private JetElement resolveNamedLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, ExpressionTypingContext context) {
|
||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||
if (stack == null || stack.isEmpty()) {
|
||||
if (reportUnresolved) {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
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);
|
||||
return result;
|
||||
}
|
||||
|
||||
public ReceiverDescriptor resolveThisLabel(JetThisExpression expression, ExpressionTypingContext context, ReceiverDescriptor thisReceiver, String labelName) {
|
||||
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
|
||||
int size = declarationsByLabel.size();
|
||||
final JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||
assert targetLabel != null;
|
||||
if (size == 1) {
|
||||
DeclarationDescriptor declarationDescriptor = declarationsByLabel.iterator().next();
|
||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
|
||||
thisReceiver = classDescriptor.getImplicitReceiver();
|
||||
}
|
||||
else if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
|
||||
thisReceiver = functionDescriptor.getReceiverParameter();
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
PsiElement element = context.trace.get(DESCRIPTOR_TO_DECLARATION, declarationDescriptor);
|
||||
assert element != null;
|
||||
context.trace.record(LABEL_TARGET, targetLabel, element);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
else if (size == 0) {
|
||||
JetElement element = resolveNamedLabel(labelName, targetLabel, false, context);
|
||||
if (element instanceof JetFunctionLiteralExpression) {
|
||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||
if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiverParameter();
|
||||
if (thisReceiver.exists()) {
|
||||
context.trace.record(LABEL_TARGET, targetLabel, element);
|
||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(targetLabel));
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(targetLabel));
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.trace.report(AMBIGUOUS_LABEL.on(targetLabel));
|
||||
}
|
||||
return thisReceiver;
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package org.jetbrains.jet.lang.types.expressions;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
*/
|
||||
public class OperatorConventions {
|
||||
|
||||
private OperatorConventions() {}
|
||||
|
||||
public static final ImmutableSet<String> NUMBER_CONVERSIONS = ImmutableSet.of(
|
||||
"dbl",
|
||||
"flt",
|
||||
"lng",
|
||||
"sht",
|
||||
"byt",
|
||||
"int"
|
||||
);
|
||||
|
||||
public static final ImmutableMap<IElementType, String> UNARY_OPERATION_NAMES = ImmutableMap.<IElementType, String>builder()
|
||||
.put(JetTokens.PLUSPLUS, "inc")
|
||||
.put(JetTokens.MINUSMINUS, "dec")
|
||||
.put(JetTokens.PLUS, "plus")
|
||||
.put(JetTokens.MINUS, "minus")
|
||||
.put(JetTokens.EXCL, "not")
|
||||
.build();
|
||||
|
||||
public static final ImmutableMap<IElementType, String> BINARY_OPERATION_NAMES = ImmutableMap.<IElementType, String>builder()
|
||||
.put(JetTokens.MUL, "times")
|
||||
.put(JetTokens.PLUS, "plus")
|
||||
.put(JetTokens.MINUS, "minus")
|
||||
.put(JetTokens.DIV, "div")
|
||||
.put(JetTokens.PERC, "mod")
|
||||
.put(JetTokens.ARROW, "arrow")
|
||||
.put(JetTokens.RANGE, "rangeTo")
|
||||
.build();
|
||||
|
||||
public static final ImmutableSet<IElementType> COMPARISON_OPERATIONS = ImmutableSet.<IElementType>of(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ);
|
||||
public static final ImmutableSet<IElementType> EQUALS_OPERATIONS = ImmutableSet.<IElementType>of(JetTokens.EQEQ, JetTokens.EXCLEQ);
|
||||
|
||||
public static final ImmutableSet<IElementType> IN_OPERATIONS = ImmutableSet.<IElementType>of(JetTokens.IN_KEYWORD, JetTokens.NOT_IN);
|
||||
public static final ImmutableMap<IElementType, String> ASSIGNMENT_OPERATIONS = ImmutableMap.<IElementType, String>builder()
|
||||
.put(JetTokens.MULTEQ, "timesAssign")
|
||||
.put(JetTokens.DIVEQ, "divAssign")
|
||||
.put(JetTokens.PERCEQ, "modAssign")
|
||||
.put(JetTokens.PLUSEQ, "plusAssign")
|
||||
.put(JetTokens.MINUSEQ, "minusAssign")
|
||||
.build();
|
||||
|
||||
public static final ImmutableMap<IElementType, IElementType> ASSIGNMENT_OPERATION_COUNTERPARTS = ImmutableMap.<IElementType, IElementType>builder()
|
||||
.put(JetTokens.MULTEQ, JetTokens.MUL)
|
||||
.put(JetTokens.DIVEQ, JetTokens.DIV)
|
||||
.put(JetTokens.PERCEQ, JetTokens.PERC)
|
||||
.put(JetTokens.PLUSEQ, JetTokens.PLUS)
|
||||
.put(JetTokens.MINUSEQ, JetTokens.MINUS)
|
||||
.build();
|
||||
|
||||
@Nullable
|
||||
public static String getNameForOperationSymbol(@NotNull IElementType token) {
|
||||
String name = UNARY_OPERATION_NAMES.get(token);
|
||||
if (name != null) return name;
|
||||
name = BINARY_OPERATION_NAMES.get(token);
|
||||
if (name != null) return name;
|
||||
name = ASSIGNMENT_OPERATIONS.get(token);
|
||||
if (name != null) return name;
|
||||
if (COMPARISON_OPERATIONS.contains(token)) return "compareTo";
|
||||
if (EQUALS_OPERATIONS.contains(token)) return "equals";
|
||||
if (IN_OPERATIONS.contains(token)) return "contains";
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
package org.jetbrains.jet.util.lazy;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
package org.jetbrains.jet.util.lazy;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.jetbrains.jet.lang.types;
|
||||
package org.jetbrains.jet.util.lazy;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -18,7 +18,7 @@ import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.expressions.JetTypeInferrerServices;
|
||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTyperServices;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
|
||||
import java.io.File;
|
||||
@@ -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);
|
||||
JetTypeInferrerServices typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext());
|
||||
ExpressionTyperServices typeInferrerServices = JetSemanticServices.createSemanticServices(getProject()).getTypeInferrerServices(new BindingTraceContext());
|
||||
|
||||
OverloadResolutionResults<FunctionDescriptor> functions = typeInferrerServices.getCallResolver().resolveExactSignature(
|
||||
classDescriptor.getMemberScope(typeArguments), ReceiverDescriptor.NO_RECEIVER, name, parameterTypeList);
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.jetbrains.jet.lang.resolve.scopes.*;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.expressions.JetTypeInferrer;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
|
||||
@@ -493,14 +492,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).getType(scopeWithImports, jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).getType(scopeWithImports, jetExpression, TypeUtils.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).safeGetType(scopeWithImports, jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).safeGetType(scopeWithImports, jetExpression, TypeUtils.NO_EXPECTED_TYPE);
|
||||
assertTrue("Error type expected but " + type + " returned", ErrorUtils.isErrorType(type));
|
||||
}
|
||||
|
||||
@@ -523,7 +522,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).getType(addImports(scope), jetExpression, JetTypeInferrer.NO_EXPECTED_TYPE);
|
||||
JetType type = semanticServices.getTypeInferrerServices(JetTestUtils.DUMMY_TRACE).getType(addImports(scope), jetExpression, TypeUtils.NO_EXPECTED_TYPE);
|
||||
JetType expectedType = expectedTypeStr == null ? null : makeType(expectedTypeStr);
|
||||
assertEquals(expectedType, type);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user