removed initial map for start instruction
This commit is contained in:
@@ -268,7 +268,7 @@ public class JetFlowInformationProvider {
|
||||
@Nullable Map<VariableDescriptor, VariableInitState> in,
|
||||
@Nullable Map<VariableDescriptor, VariableInitState> out) {
|
||||
assert in != null && out != null;
|
||||
VariableInitContext ctxt = new VariableInitContext(instruction, reportedDiagnosticMap, in, out);
|
||||
VariableInitContext ctxt = new VariableInitContext(instruction, reportedDiagnosticMap, in, out, declaredVariables);
|
||||
if (ctxt.variableDescriptor == null) return;
|
||||
if (instruction instanceof ReadValueInstruction) {
|
||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||
@@ -843,11 +843,23 @@ public class JetFlowInformationProvider {
|
||||
@NotNull Instruction instruction,
|
||||
@NotNull Map<Instruction, DiagnosticFactory> map,
|
||||
@NotNull Map<VariableDescriptor, VariableInitState> in,
|
||||
@NotNull Map<VariableDescriptor, VariableInitState> out
|
||||
@NotNull Map<VariableDescriptor, VariableInitState> out,
|
||||
@NotNull Set<VariableDescriptor> declaredVariables
|
||||
) {
|
||||
super(instruction, map);
|
||||
enterInitState = variableDescriptor != null ? in.get(variableDescriptor) : null;
|
||||
exitInitState = variableDescriptor != null ? out.get(variableDescriptor) : null;
|
||||
enterInitState = initialize(variableDescriptor, declaredVariables, in);
|
||||
exitInitState = initialize(variableDescriptor, declaredVariables, out);
|
||||
}
|
||||
|
||||
private VariableInitState initialize(
|
||||
VariableDescriptor variableDescriptor,
|
||||
Set<VariableDescriptor> declaredVariables,
|
||||
Map<VariableDescriptor, VariableInitState> map
|
||||
) {
|
||||
if (variableDescriptor == null) return null;
|
||||
VariableInitState state = map.get(variableDescriptor);
|
||||
if (state != null) return state;
|
||||
return PseudocodeVariablesData.getDefaultValueForInitializers(declaredVariables, variableDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,19 +22,14 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.*;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS;
|
||||
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.LookInsideStrategy.SKIP_LOCAL_DECLARATIONS;
|
||||
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.BACKWARD;
|
||||
import static org.jetbrains.jet.lang.cfg.PseudocodeTraverser.TraversalOrder.FORWARD;
|
||||
|
||||
@@ -133,66 +128,43 @@ public class PseudocodeVariablesData {
|
||||
@NotNull
|
||||
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> getVariableInitializers(@NotNull Pseudocode pseudocode) {
|
||||
|
||||
Set<VariableDescriptor> usedVariables = getUsedVariables(pseudocode);
|
||||
Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode, false);
|
||||
final Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode, true);
|
||||
Map<VariableDescriptor, VariableInitState> initialMap = Collections.emptyMap();
|
||||
Map<VariableDescriptor, VariableInitState> initialMapForStartInstruction = prepareInitializersMapForStartInstruction(
|
||||
usedVariables, declaredVariables);
|
||||
|
||||
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializersMap = PseudocodeTraverser.collectData(
|
||||
pseudocode, FORWARD, SKIP_LOCAL_DECLARATIONS,
|
||||
initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
|
||||
@Override
|
||||
public Edges<Map<VariableDescriptor, VariableInitState>> execute(
|
||||
@NotNull Instruction instruction, @NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData) {
|
||||
InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>> instructionDataMergeStrategy =
|
||||
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
|
||||
@Override
|
||||
public Edges<Map<VariableDescriptor, VariableInitState>> execute(
|
||||
@NotNull Instruction instruction,
|
||||
@NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData
|
||||
) {
|
||||
|
||||
Map<VariableDescriptor, VariableInitState> enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData);
|
||||
Map<VariableDescriptor, VariableInitState> exitInstructionData =
|
||||
addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData);
|
||||
return Edges.create(enterInstructionData, exitInstructionData);
|
||||
}
|
||||
});
|
||||
Map<VariableDescriptor, VariableInitState> enterInstructionData =
|
||||
mergeIncomingEdgesDataForInitializers(incomingEdgesData);
|
||||
Map<VariableDescriptor, VariableInitState> exitInstructionData =
|
||||
addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData, declaredVariables);
|
||||
return Edges.create(enterInstructionData, exitInstructionData);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
for (LocalFunctionDeclarationInstruction localFunctionDeclarationInstruction : pseudocode.getLocalDeclarations()) {
|
||||
Pseudocode localPseudocode = localFunctionDeclarationInstruction.getBody();
|
||||
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> initializersForLocalDeclaration = getVariableInitializers(localPseudocode);
|
||||
|
||||
for (Instruction instruction : initializersForLocalDeclaration.keySet()) {
|
||||
//todo
|
||||
if (!variableInitializersMap.containsKey(instruction)) {
|
||||
variableInitializersMap.put(instruction, initializersForLocalDeclaration.get(instruction));
|
||||
}
|
||||
}
|
||||
variableInitializersMap.putAll(initializersForLocalDeclaration);
|
||||
}
|
||||
return variableInitializersMap;
|
||||
return PseudocodeTraverser.collectData(
|
||||
pseudocode, FORWARD, ANALYSE_LOCAL_DECLARATIONS,
|
||||
initialMap, initialMap, instructionDataMergeStrategy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<VariableDescriptor, VariableInitState> prepareInitializersMapForStartInstruction(
|
||||
@NotNull Collection<VariableDescriptor> usedVariables,
|
||||
@NotNull Collection<VariableDescriptor> declaredVariables) {
|
||||
|
||||
Map<VariableDescriptor, VariableInitState> initialMapForStartInstruction = Maps.newHashMap();
|
||||
VariableInitState initializedForExternalVariable = VariableInitState.create(true);
|
||||
VariableInitState notInitializedForDeclaredVariable = VariableInitState.create(false);
|
||||
|
||||
for (VariableDescriptor variable : usedVariables) {
|
||||
if (declaredVariables.contains(variable)) {
|
||||
initialMapForStartInstruction.put(variable, notInitializedForDeclaredVariable);
|
||||
}
|
||||
else {
|
||||
initialMapForStartInstruction.put(variable, initializedForExternalVariable);
|
||||
}
|
||||
}
|
||||
return initialMapForStartInstruction;
|
||||
public static VariableInitState getDefaultValueForInitializers(
|
||||
@NotNull Set<VariableDescriptor> declaredVariables,
|
||||
@NotNull VariableDescriptor variable
|
||||
) {
|
||||
//todo: think of replacing it with "MapWithDefaultValue"
|
||||
boolean isInitialized = !declaredVariables.contains(variable);
|
||||
return VariableInitState.create(isInitialized);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<VariableDescriptor, VariableInitState> mergeIncomingEdgesDataForInitializers(
|
||||
@NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData) {
|
||||
|
||||
@NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData
|
||||
) {
|
||||
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
|
||||
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
|
||||
variablesInScope.addAll(edgeData.keySet());
|
||||
@@ -220,8 +192,10 @@ public class PseudocodeVariablesData {
|
||||
|
||||
@NotNull
|
||||
private Map<VariableDescriptor, VariableInitState> addVariableInitStateFromCurrentInstructionIfAny(
|
||||
@NotNull Instruction instruction, @NotNull Map<VariableDescriptor, VariableInitState> enterInstructionData) {
|
||||
|
||||
@NotNull Instruction instruction,
|
||||
@NotNull Map<VariableDescriptor, VariableInitState> enterInstructionData,
|
||||
@NotNull Set<VariableDescriptor> declaredVariables
|
||||
) {
|
||||
if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) {
|
||||
return enterInstructionData;
|
||||
}
|
||||
@@ -238,6 +212,9 @@ public class PseudocodeVariablesData {
|
||||
}
|
||||
else { // instruction instanceof VariableDeclarationInstruction
|
||||
VariableInitState enterInitState = enterInstructionData.get(variable);
|
||||
if (enterInitState == null) {
|
||||
enterInitState = getDefaultValueForInitializers(declaredVariables, variable);
|
||||
}
|
||||
if (enterInitState == null || !enterInitState.isInitialized || !enterInitState.isDeclared) {
|
||||
boolean isInitialized = enterInitState != null && enterInitState.isInitialized;
|
||||
VariableInitState variableDeclarationInfo = VariableInitState.create(isInitialized, true);
|
||||
@@ -252,9 +229,6 @@ public class PseudocodeVariablesData {
|
||||
@NotNull
|
||||
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
|
||||
Map<VariableDescriptor, VariableUseState> sinkInstructionData = Maps.newHashMap();
|
||||
for (VariableDescriptor usedVariable : getUsedVariables(pseudocode)) {
|
||||
sinkInstructionData.put(usedVariable, VariableUseState.UNUSED);
|
||||
}
|
||||
InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>> collectVariableUseStatusStrategy =
|
||||
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
|
||||
@Override
|
||||
@@ -299,9 +273,9 @@ public class PseudocodeVariablesData {
|
||||
return Edges.create(enterResult, exitResult);
|
||||
}
|
||||
};
|
||||
return PseudocodeTraverser.collectData(pseudocode, BACKWARD, ANALYSE_LOCAL_DECLARATIONS,
|
||||
Collections.<VariableDescriptor, VariableUseState>emptyMap(),
|
||||
sinkInstructionData, collectVariableUseStatusStrategy);
|
||||
return PseudocodeTraverser.collectData(
|
||||
pseudocode, BACKWARD, ANALYSE_LOCAL_DECLARATIONS, Collections.<VariableDescriptor, VariableUseState>emptyMap(),
|
||||
sinkInstructionData, collectVariableUseStatusStrategy);
|
||||
}
|
||||
|
||||
public static class VariableInitState {
|
||||
|
||||
Reference in New Issue
Block a user