Added dot qualifiers for variable analysis
This commit is contained in:
@@ -13,6 +13,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
|||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
@@ -116,14 +117,13 @@ public class JetFlowInformationProvider {
|
|||||||
|
|
||||||
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
|
for (Instruction deadInstruction : pseudocode.getDeadInstructions()) {
|
||||||
if (deadInstruction instanceof JetElementInstruction &&
|
if (deadInstruction instanceof JetElementInstruction &&
|
||||||
// TODO : do {return} while (1 > a)
|
|
||||||
!(deadInstruction instanceof ReadUnitValueInstruction)) {
|
!(deadInstruction instanceof ReadUnitValueInstruction)) {
|
||||||
unreachableElements.add(((JetElementInstruction) deadInstruction).getElement());
|
unreachableElements.add(((JetElementInstruction) deadInstruction).getElement());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void markUninitializedVariables(@NotNull JetElement subroutine, final boolean inAnonymousInitializers, final boolean declaredLocally) {
|
public void markUninitializedVariables(@NotNull JetElement subroutine, final boolean inAnonymousInitializers, final boolean analyzeLocalDeclaration) {
|
||||||
final Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
final Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
assert pseudocode != null;
|
assert pseudocode != null;
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ public class JetFlowInformationProvider {
|
|||||||
|
|
||||||
Map<VariableDescriptor, InitializationPoints> exitInstructionPointsMap = Maps.newHashMap(enterInstructionPointsMap);
|
Map<VariableDescriptor, InitializationPoints> exitInstructionPointsMap = Maps.newHashMap(enterInstructionPointsMap);
|
||||||
if (instruction instanceof WriteValueInstruction) {
|
if (instruction instanceof WriteValueInstruction) {
|
||||||
VariableDescriptor variable = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variable = extractVariableDescriptorIfAny(instruction, false);
|
||||||
InitializationPoints initializationAtThisPoint = new InitializationPoints(((WriteValueInstruction) instruction).getElement());
|
InitializationPoints initializationAtThisPoint = new InitializationPoints(((WriteValueInstruction) instruction).getElement());
|
||||||
exitInstructionPointsMap.put(variable, initializationAtThisPoint);
|
exitInstructionPointsMap.put(variable, initializationAtThisPoint);
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ public class JetFlowInformationProvider {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Collection<VariableDescriptor> usedVariables = collectUsedVariables(pseudocode);
|
Collection<VariableDescriptor> usedVariables = collectUsedVariables(pseudocode);
|
||||||
Collection<VariableDescriptor> declaredVariables = collectDeclaredVariables(subroutine);
|
final Collection<VariableDescriptor> declaredVariables = collectDeclaredVariables(subroutine);
|
||||||
Map<VariableDescriptor, InitializationPoints> initialMapForStartInstruction = prepareInitialMapForStartInstruction(usedVariables, declaredVariables);
|
Map<VariableDescriptor, InitializationPoints> initialMapForStartInstruction = prepareInitialMapForStartInstruction(usedVariables, declaredVariables);
|
||||||
|
|
||||||
traverser.collectInformationFromInstructionGraph(instructionsMergeStrategy,
|
traverser.collectInformationFromInstructionGraph(instructionsMergeStrategy,
|
||||||
@@ -178,10 +178,9 @@ public class JetFlowInformationProvider {
|
|||||||
public void execute(Instruction instruction, @Nullable Map<VariableDescriptor, InitializationPoints> enterData, @Nullable Map<VariableDescriptor, InitializationPoints> exitData) {
|
public void execute(Instruction instruction, @Nullable Map<VariableDescriptor, InitializationPoints> enterData, @Nullable Map<VariableDescriptor, InitializationPoints> exitData) {
|
||||||
assert enterData != null && exitData != null;
|
assert enterData != null && exitData != null;
|
||||||
if (instruction instanceof ReadValueInstruction) {
|
if (instruction instanceof ReadValueInstruction) {
|
||||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false);
|
||||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||||
if (element instanceof JetSimpleNameExpression && variableDescriptor != null &&
|
if (element instanceof JetSimpleNameExpression && variableDescriptor != null && declaredVariables.contains(variableDescriptor)) {
|
||||||
(inAnonymousInitializers || variableDescriptor instanceof LocalVariableDescriptor)) {
|
|
||||||
|
|
||||||
InitializationPoints exitInitializationPoints = exitData.get(variableDescriptor);
|
InitializationPoints exitInitializationPoints = exitData.get(variableDescriptor);
|
||||||
assert exitInitializationPoints != null;
|
assert exitInitializationPoints != null;
|
||||||
@@ -192,15 +191,15 @@ public class JetFlowInformationProvider {
|
|||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!declaredLocally && !isInitialized) {
|
if (!analyzeLocalDeclaration && !isInitialized) {
|
||||||
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
|
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (instruction instanceof WriteValueInstruction) {
|
else if (instruction instanceof WriteValueInstruction) {
|
||||||
JetElement element = ((WriteValueInstruction) instruction).getlValue();
|
JetElement element = ((WriteValueInstruction) instruction).getlValue();
|
||||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true);
|
||||||
if (element instanceof JetSimpleNameExpression && variableDescriptor != null) {
|
if (element instanceof JetExpression && variableDescriptor != null) {
|
||||||
InitializationPoints enterInitializationPoints = enterData.get(variableDescriptor);
|
InitializationPoints enterInitializationPoints = enterData.get(variableDescriptor);
|
||||||
assert enterInitializationPoints != null;
|
assert enterInitializationPoints != null;
|
||||||
InitializationPoints exitInitializationPoints = exitData.get(variableDescriptor);
|
InitializationPoints exitInitializationPoints = exitData.get(variableDescriptor);
|
||||||
@@ -213,16 +212,17 @@ public class JetFlowInformationProvider {
|
|||||||
hasInitializer = false;
|
hasInitializer = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JetSimpleNameExpression expression = (JetSimpleNameExpression) element;
|
JetExpression expression = (JetExpression) element;
|
||||||
if (!declaredLocally && hasInitializer && !variableDescriptor.isVar()) {
|
if (!analyzeLocalDeclaration && hasInitializer && !variableDescriptor.isVar()) {
|
||||||
PsiElement psiElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, variableDescriptor);
|
PsiElement psiElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, variableDescriptor);
|
||||||
JetProperty property = psiElement instanceof JetProperty ? (JetProperty) psiElement : null;
|
JetProperty property = psiElement instanceof JetProperty ? (JetProperty) psiElement : null;
|
||||||
trace.report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor, property == null ? new JetProperty[0] : new JetProperty[] { property }));
|
trace.report(Errors.VAL_REASSIGNMENT.on(expression, variableDescriptor, property == null ? new JetProperty[0] : new JetProperty[] { property }));
|
||||||
}
|
}
|
||||||
if (!declaredLocally && inAnonymousInitializers && variableDescriptor instanceof PropertyDescriptor &&
|
if (expression instanceof JetSimpleNameExpression && !analyzeLocalDeclaration && inAnonymousInitializers &&
|
||||||
!enterInitializationPoints.isInitialized() && exitInitializationPoints.isInitialized()) {
|
variableDescriptor instanceof PropertyDescriptor && !enterInitializationPoints.isInitialized() && exitInitializationPoints.isInitialized()) {
|
||||||
if (expression.getReferencedNameElementType() != JetTokens.FIELD_IDENTIFIER) {
|
JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
|
||||||
trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD.on(expression, variableDescriptor));
|
if (simpleNameExpression.getReferencedNameElementType() != JetTokens.FIELD_IDENTIFIER) {
|
||||||
|
trace.report(Errors.INITIALIZATION_USING_BACKING_FIELD.on(simpleNameExpression, variableDescriptor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,7 +271,7 @@ public class JetFlowInformationProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(Instruction instruction, Void enterData, Void exitData) {
|
public void execute(Instruction instruction, Void enterData, Void exitData) {
|
||||||
if (instruction instanceof ReadValueInstruction) {
|
if (instruction instanceof ReadValueInstruction) {
|
||||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false);
|
||||||
if (variableDescriptor != null && functionVariables.contains(variableDescriptor)) {
|
if (variableDescriptor != null && functionVariables.contains(variableDescriptor)) {
|
||||||
//check that we only invoke this variable
|
//check that we only invoke this variable
|
||||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||||
@@ -285,29 +285,15 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private VariableDescriptor extractVariableDescriptorIfAny(Instruction instruction) {
|
private VariableDescriptor extractVariableDescriptorIfAny(Instruction instruction, boolean onlyReference) {
|
||||||
VariableDescriptor variableDescriptor = null;
|
VariableDescriptor variableDescriptor = null;
|
||||||
if (instruction instanceof ReadValueInstruction) {
|
if (instruction instanceof ReadValueInstruction) {
|
||||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||||
if (element instanceof JetSimpleNameExpression) {
|
variableDescriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), element, onlyReference);
|
||||||
DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
|
|
||||||
if (descriptor instanceof VariableDescriptor) {
|
|
||||||
variableDescriptor = (VariableDescriptor) descriptor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (instruction instanceof WriteValueInstruction) {
|
else if (instruction instanceof WriteValueInstruction) {
|
||||||
DeclarationDescriptor descriptor = null;
|
|
||||||
JetElement lValue = ((WriteValueInstruction) instruction).getlValue();
|
JetElement lValue = ((WriteValueInstruction) instruction).getlValue();
|
||||||
if (lValue instanceof JetProperty || lValue instanceof JetParameter) {
|
variableDescriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), lValue, onlyReference);
|
||||||
descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, lValue);
|
|
||||||
}
|
|
||||||
else if (lValue instanceof JetSimpleNameExpression) {
|
|
||||||
descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) lValue);
|
|
||||||
}
|
|
||||||
if (descriptor instanceof VariableDescriptor) {
|
|
||||||
variableDescriptor = (VariableDescriptor) descriptor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return variableDescriptor;
|
return variableDescriptor;
|
||||||
}
|
}
|
||||||
@@ -317,7 +303,7 @@ public class JetFlowInformationProvider {
|
|||||||
JetControlFlowGraphTraverser.<Void>create(pseudocode, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
|
JetControlFlowGraphTraverser.<Void>create(pseudocode, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public void execute(Instruction instruction, Void enterData, Void exitData) {
|
public void execute(Instruction instruction, Void enterData, Void exitData) {
|
||||||
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false);
|
||||||
if (variableDescriptor != null) {
|
if (variableDescriptor != null) {
|
||||||
usedVariables.add(variableDescriptor);
|
usedVariables.add(variableDescriptor);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -19,4 +21,21 @@ public class BindingContextUtils {
|
|||||||
return bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declarationDescriptor);
|
return bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declarationDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static VariableDescriptor extractVariableDescriptorIfAny(BindingContext bindingContext, JetElement element, boolean onlyReference) {
|
||||||
|
DeclarationDescriptor descriptor = null;
|
||||||
|
if (!onlyReference && (element instanceof JetProperty || element instanceof JetParameter)) {
|
||||||
|
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||||
|
}
|
||||||
|
else if (element instanceof JetSimpleNameExpression) {
|
||||||
|
descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
|
||||||
|
}
|
||||||
|
else if (element instanceof JetQualifiedExpression) {
|
||||||
|
descriptor = extractVariableDescriptorIfAny(bindingContext, ((JetQualifiedExpression) element).getSelectorExpression(), onlyReference);
|
||||||
|
}
|
||||||
|
if (descriptor instanceof VariableDescriptor) {
|
||||||
|
return (VariableDescriptor) descriptor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
@@ -305,4 +305,18 @@ fun foo() {
|
|||||||
<!UNRESOLVED_REFERENCE!>$b<!> = 3
|
<!UNRESOLVED_REFERENCE!>$b<!> = 3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------
|
||||||
|
// dot qualifiers
|
||||||
|
class M() {
|
||||||
|
val x = 11
|
||||||
|
var y = 12
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(m : M) {
|
||||||
|
<!VAL_REASSIGNMENT!>m.x<!> = 23
|
||||||
|
m.y = 23
|
||||||
|
<!VAL_REASSIGNMENT!>m.x<!>++
|
||||||
|
m.y--
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user