KT-1645 Propose members according to smart casts
#KT-1645 fixed
This commit is contained in:
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.DeferredType;
|
||||
@@ -32,7 +33,6 @@ import org.jetbrains.jet.util.Box;
|
||||
import org.jetbrains.jet.util.slicedmap.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.jet.util.slicedmap.RewritePolicy.DO_NOTHING;
|
||||
|
||||
@@ -63,6 +63,9 @@ public interface BindingContext {
|
||||
/** A scope where type of expression has been resolved */
|
||||
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice();
|
||||
|
||||
/** Collected during analyze, used in IDE in auto-cast completion */
|
||||
WritableSlice<JetExpression, DataFlowInfo> NON_DEFAULT_EXPRESSION_DATA_FLOW = Slices.createSimpleSlice();
|
||||
|
||||
WritableSlice<JetExpression, Boolean> VARIABLE_REASSIGNMENT = Slices.createSimpleSetSlice();
|
||||
WritableSlice<ValueParameterDescriptor, Boolean> AUTO_CREATED_IT = Slices.createSimpleSetSlice();
|
||||
WritableSlice<JetExpression, DeclarationDescriptor> VARIABLE_ASSIGNMENT = Slices.createSimpleSlice();
|
||||
|
||||
@@ -358,7 +358,9 @@ public class BodyResolver {
|
||||
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
|
||||
JetTypeReference typeReference = call.getTypeReference();
|
||||
if (typeReference != null) {
|
||||
callResolver.resolveFunctionCall(trace, scopeForSupertypeInitializers, CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, dataFlowInfo);
|
||||
callResolver.resolveFunctionCall(trace, scopeForSupertypeInitializers,
|
||||
CallMaker.makeCall(ReceiverDescriptor.NO_RECEIVER, null, call),
|
||||
NO_EXPECTED_TYPE, dataFlowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,10 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemSolution;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemWithPriorities;
|
||||
import org.jetbrains.jet.lang.resolve.calls.inference.DebugConstraintResolutionListener;
|
||||
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;
|
||||
@@ -42,8 +45,7 @@ import javax.inject.Inject;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.AUTOCAST;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLUTION_SCOPE;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.ResolutionStatus.*;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_CANDIDATE;
|
||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCallImpl.MAP_TO_RESULT;
|
||||
@@ -255,6 +257,10 @@ public class CallResolver {
|
||||
context.trace.record(ResolutionDebugInfo.RESOLUTION_DEBUG_INFO, context.call.getCallElement(), debugInfo);
|
||||
context.trace.record(RESOLUTION_SCOPE, context.call.getCalleeExpression(), context.scope);
|
||||
|
||||
if (context.dataFlowInfo.hasTypeInfoConstraints()) {
|
||||
context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, context.call.getCalleeExpression(), context.dataFlowInfo);
|
||||
}
|
||||
|
||||
debugInfo.set(ResolutionDebugInfo.TASKS, prioritizedTasks);
|
||||
|
||||
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
|
||||
|
||||
+6
-2
@@ -36,7 +36,10 @@ public class AutoCastUtils {
|
||||
/**
|
||||
* @return variants @param receiverToCast may be cast to according to @param dataFlowInfo, @param receiverToCast itself is NOT included
|
||||
*/
|
||||
public static List<ReceiverDescriptor> getAutoCastVariants(@NotNull final BindingContext bindingContext, @NotNull final DataFlowInfo dataFlowInfo, @NotNull ReceiverDescriptor receiverToCast) {
|
||||
public static List<ReceiverDescriptor> getAutoCastVariants(
|
||||
@NotNull final BindingContext bindingContext,
|
||||
@NotNull final DataFlowInfo dataFlowInfo, @NotNull ReceiverDescriptor receiverToCast
|
||||
) {
|
||||
return receiverToCast.accept(new ReceiverDescriptorVisitor<List<ReceiverDescriptor>, Object>() {
|
||||
@Override
|
||||
public List<ReceiverDescriptor> visitNoReceiver(ReceiverDescriptor noReceiver, Object data) {
|
||||
@@ -72,7 +75,8 @@ public class AutoCastUtils {
|
||||
// else if (expression instanceof JetThisExpression) {
|
||||
// return castThis(dataFlowInfo, receiver);
|
||||
// }
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(receiver.getExpression(),receiver.getType(), bindingContext);
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(receiver.getExpression(),receiver.getType(),
|
||||
bindingContext);
|
||||
List<ReceiverDescriptor> result = Lists.newArrayList();
|
||||
for (JetType possibleType : dataFlowInfo.getPossibleTypes(dataFlowValue)) {
|
||||
result.add(new AutoCastReceiver(receiver, possibleType, dataFlowValue.isStableIdentifier()));
|
||||
|
||||
+7
-1
@@ -50,7 +50,9 @@ public class DataFlowInfo {
|
||||
}
|
||||
};
|
||||
|
||||
public static DataFlowInfo EMPTY = new DataFlowInfo(ImmutableMap.<DataFlowValue, Nullability>of(), Multimaps.newListMultimap(Collections.<DataFlowValue, Collection<JetType>>emptyMap(), CommonSuppliers.<JetType>getArrayListSupplier()));
|
||||
public static DataFlowInfo EMPTY = new DataFlowInfo(
|
||||
ImmutableMap.<DataFlowValue, Nullability>of(),
|
||||
Multimaps.newListMultimap(Collections.<DataFlowValue, Collection<JetType>>emptyMap(), CommonSuppliers.<JetType>getArrayListSupplier()));
|
||||
|
||||
private final ImmutableMap<DataFlowValue, Nullability> nullabilityInfo;
|
||||
/** Also immutable */
|
||||
@@ -195,6 +197,10 @@ public class DataFlowInfo {
|
||||
return new DataFlowInfo(ImmutableMap.copyOf(builder), newTypeInfo);
|
||||
}
|
||||
|
||||
public boolean hasTypeInfoConstraints() {
|
||||
return !typeInfo.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//public class DataFlowInfo {
|
||||
|
||||
+8
@@ -617,6 +617,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
temporaryTrace.commit();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Uncommitted changes in temp context
|
||||
context.trace.record(RESOLUTION_SCOPE, nameExpression, context.scope);
|
||||
if (context.dataFlowInfo.hasTypeInfoConstraints()) {
|
||||
context.trace.record(NON_DEFAULT_EXPRESSION_DATA_FLOW, nameExpression, context.dataFlowInfo);
|
||||
}
|
||||
|
||||
ExpressionTypingContext newContext = receiver.exists()
|
||||
? context.replaceScope(receiver.getType().getMemberScope())
|
||||
: context;
|
||||
@@ -624,6 +631,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
if (jetType == null) {
|
||||
context.trace.report(UNRESOLVED_REFERENCE.on(nameExpression));
|
||||
}
|
||||
|
||||
return jetType;
|
||||
}
|
||||
else if (selectorExpression instanceof JetQualifiedExpression) {
|
||||
|
||||
+5
-2
@@ -59,7 +59,8 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
JetPattern pattern = expression.getPattern();
|
||||
if (pattern != null) {
|
||||
WritableScopeImpl scopeToExtend = newWritableScopeImpl(context).setDebugName("Scope extended in 'is'");
|
||||
DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, false, scopeToExtend, context, DataFlowValueFactory.INSTANCE.createDataFlowValue(leftHandSide, knownType, context.trace.getBindingContext()));
|
||||
DataFlowValue dataFlowValue = DataFlowValueFactory.INSTANCE.createDataFlowValue(leftHandSide, knownType, context.trace.getBindingContext());
|
||||
DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, false, scopeToExtend, context, dataFlowValue);
|
||||
context.patternsToDataFlowInfo.put(pattern, newDataFlowInfo);
|
||||
context.patternsToBoundVariableLists.put(pattern, scopeToExtend.getDeclaredVariables());
|
||||
}
|
||||
@@ -175,7 +176,9 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
return newDataFlowInfo[0];
|
||||
}
|
||||
|
||||
private DataFlowInfo checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType, final boolean conditionExpected, @NotNull final WritableScope scopeToExtend, final ExpressionTypingContext context, @NotNull final DataFlowValue... subjectVariables) {
|
||||
private DataFlowInfo checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType, final boolean conditionExpected,
|
||||
@NotNull final WritableScope scopeToExtend, final ExpressionTypingContext context, @NotNull final DataFlowValue... subjectVariables
|
||||
) {
|
||||
final Ref<DataFlowInfo> result = new Ref<DataFlowInfo>(context.dataFlowInfo);
|
||||
pattern.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user