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