changes in 'PseudocodeTraverser' interface
This commit is contained in:
@@ -24,7 +24,7 @@ import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.*;
|
||||
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges;
|
||||
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*;
|
||||
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitializers;
|
||||
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseStatus;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
@@ -189,14 +189,14 @@ public class JetFlowInformationProvider {
|
||||
|
||||
Map<Instruction, Edges<Map<VariableDescriptor,VariableInitializers>>> initializers = pseudocodeData.getVariableInitializers();
|
||||
final Set<VariableDescriptor> declaredVariables = pseudocodeData.getDeclaredVariables(pseudocode);
|
||||
PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(true, pseudocode, initializers, true, new PseudocodeTraverser.InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableInitializers>>() {
|
||||
PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableInitializers>>() {
|
||||
@Override
|
||||
public void execute(@NotNull Instruction instruction,
|
||||
@Nullable Map<VariableDescriptor, VariableInitializers> in,
|
||||
@Nullable Map<VariableDescriptor, VariableInitializers> out) {
|
||||
assert in != null && out != null;
|
||||
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true,
|
||||
trace.getBindingContext());
|
||||
trace.getBindingContext());
|
||||
if (variableDescriptor == null) return;
|
||||
if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return;
|
||||
VariableInitializers outInitializers = out.get(variableDescriptor);
|
||||
@@ -356,7 +356,9 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor);
|
||||
boolean insideSelfAccessors = PsiTreeUtil.isAncestor(property, element, false);
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor) && !insideSelfAccessors) { // not to generate error in accessors of abstract properties, there is one: declared accessor of abstract property
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor) &&
|
||||
!insideSelfAccessors) { // not to generate error in accessors of abstract properties, there is one: declared accessor of abstract property
|
||||
|
||||
if (((PropertyDescriptor) variableDescriptor).getModality() == Modality.ABSTRACT) {
|
||||
trace.report(NO_BACKING_FIELD_ABSTRACT_PROPERTY.on(element));
|
||||
}
|
||||
@@ -412,8 +414,9 @@ public class JetFlowInformationProvider {
|
||||
// "Unused variable" & "unused value" analyses
|
||||
|
||||
public void markUnusedVariables() {
|
||||
Map<Instruction, Edges<Map<VariableDescriptor, VariableUseStatus>>> variableStatusData = pseudocodeData.getVariableStatusData();
|
||||
PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(true, pseudocode, variableStatusData, false, new PseudocodeTraverser.InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseStatus>>() {
|
||||
Map<Instruction, Edges<Map<VariableDescriptor, VariableUseStatus>>> variableStatusData = pseudocodeData.getVariableUseStatusData();
|
||||
InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseStatus>> variableStatusAnalyzeStrategy =
|
||||
new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseStatus>>() {
|
||||
@Override
|
||||
public void execute(@NotNull Instruction instruction,
|
||||
@Nullable Map<VariableDescriptor, VariableUseStatus> in,
|
||||
@@ -422,7 +425,7 @@ public class JetFlowInformationProvider {
|
||||
assert in != null && out != null;
|
||||
Set<VariableDescriptor> declaredVariables = pseudocodeData.getDeclaredVariables(instruction.getOwner());
|
||||
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false,
|
||||
trace.getBindingContext());
|
||||
trace.getBindingContext());
|
||||
if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) ||
|
||||
!DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return;
|
||||
VariableUseStatus variableUseStatus = in.get(variableDescriptor);
|
||||
@@ -438,8 +441,7 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
else if (element instanceof JetPostfixExpression) {
|
||||
IElementType operationToken =
|
||||
((JetPostfixExpression) element).getOperationReference().getReferencedNameElementType();
|
||||
IElementType operationToken = ((JetPostfixExpression) element).getOperationReference().getReferencedNameElementType();
|
||||
if (operationToken == JetTokens.PLUSPLUS || operationToken == JetTokens.MINUSMINUS) {
|
||||
trace.report(Errors.UNUSED_CHANGED_VALUE.on(element, element));
|
||||
}
|
||||
@@ -458,28 +460,19 @@ public class JetFlowInformationProvider {
|
||||
else if (element instanceof JetParameter) {
|
||||
PsiElement psiElement = element.getParent().getParent();
|
||||
if (psiElement instanceof JetFunction) {
|
||||
boolean isMain = (psiElement instanceof JetNamedFunction) &&
|
||||
JetMainDetector.isMain((JetNamedFunction) psiElement);
|
||||
//todo
|
||||
if (psiElement instanceof JetFunctionLiteral) {
|
||||
//psiElement = psiElement.getParent();
|
||||
return;
|
||||
}
|
||||
DeclarationDescriptor descriptor =
|
||||
trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
||||
boolean isMain = (psiElement instanceof JetNamedFunction) && JetMainDetector.isMain((JetNamedFunction) psiElement);
|
||||
if (psiElement instanceof JetFunctionLiteral) return;
|
||||
DeclarationDescriptor descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
||||
assert descriptor instanceof FunctionDescriptor : psiElement.getText();
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
if (!isMain &&
|
||||
!functionDescriptor.getModality().isOverridable() &&
|
||||
functionDescriptor.getOverriddenDescriptors().isEmpty()) {
|
||||
if (!isMain && !functionDescriptor.getModality().isOverridable() && functionDescriptor.getOverriddenDescriptors().isEmpty()) {
|
||||
trace.report(Errors.UNUSED_PARAMETER.on((JetParameter) element, variableDescriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (variableUseStatus == VariableUseStatus.ONLY_WRITTEN_NEVER_READ && element instanceof JetProperty) {
|
||||
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
|
||||
.on((JetNamedDeclaration) element, variableDescriptor));
|
||||
else if (variableUseStatus == VariableUseStatus.ONLY_WRITTEN_NEVER_READ &&element instanceof JetProperty) {
|
||||
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor));
|
||||
}
|
||||
else if (variableUseStatus == VariableUseStatus.LAST_WRITTEN && element instanceof JetProperty) {
|
||||
JetExpression initializer = ((JetProperty) element).getInitializer();
|
||||
@@ -489,9 +482,9 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
PseudocodeTraverser.traverse(pseudocode, false, true, variableStatusData, variableStatusAnalyzeStrategy);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -499,8 +492,8 @@ public class JetFlowInformationProvider {
|
||||
|
||||
public void markUnusedLiteralsInBlock() {
|
||||
assert pseudocode != null;
|
||||
PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(
|
||||
pseudocode, true, new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() {
|
||||
PseudocodeTraverser.traverse(
|
||||
pseudocode, true, new InstructionAnalyzeStrategy() {
|
||||
@Override
|
||||
public void execute(@NotNull Instruction instruction) {
|
||||
if (!(instruction instanceof ReadValueInstruction)) return;
|
||||
|
||||
@@ -37,50 +37,46 @@ public class PseudocodeTraverser {
|
||||
return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction();
|
||||
}
|
||||
|
||||
public static <D> Map<Instruction, Edges<D>> collectInformationFromInstructionGraph(
|
||||
boolean lookInside,
|
||||
boolean directOrder,
|
||||
@NotNull Pseudocode pseudocode,
|
||||
@NotNull D initialDataValue,
|
||||
@NotNull D initialDataValueForEnterInstruction,
|
||||
public static <D> Map<Instruction, Edges<D>> collectInformation(
|
||||
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
|
||||
@NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction,
|
||||
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy) {
|
||||
Map<Instruction, Edges<D>> dataMap = Maps.newLinkedHashMap();
|
||||
initializeDataMap(lookInside, dataMap, pseudocode, initialDataValue);
|
||||
dataMap.put(getStartInstruction(pseudocode, directOrder),
|
||||
Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction));
|
||||
|
||||
Map<Instruction, Edges<D>> edgesMap = Maps.newLinkedHashMap();
|
||||
initializeEdgesMap(pseudocode, lookInside, edgesMap, initialDataValue);
|
||||
edgesMap.put(getStartInstruction(pseudocode, directOrder), Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction));
|
||||
|
||||
boolean[] changed = new boolean[1];
|
||||
changed[0] = true;
|
||||
while (changed[0]) {
|
||||
changed[0] = false;
|
||||
traverseSubGraph(lookInside, pseudocode, dataMap, instructionDataMergeStrategy, Collections.<Instruction>emptyList(), directOrder, changed, false);
|
||||
collectInformationFromSubgraph(pseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy,
|
||||
Collections.<Instruction>emptyList(), changed, false);
|
||||
}
|
||||
return dataMap;
|
||||
return edgesMap;
|
||||
}
|
||||
|
||||
private static <D> void initializeDataMap(
|
||||
boolean lookInside,
|
||||
@NotNull Map<Instruction, Edges<D>> dataMap, @NotNull Pseudocode pseudocode,
|
||||
private static <D> void initializeEdgesMap(
|
||||
@NotNull Pseudocode pseudocode, boolean lookInside,
|
||||
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
||||
@NotNull D initialDataValue) {
|
||||
List<Instruction> instructions = pseudocode.getInstructions();
|
||||
Edges<D> initialEdge = Edges.create(initialDataValue, initialDataValue);
|
||||
for (Instruction instruction : instructions) {
|
||||
dataMap.put(instruction, initialEdge);
|
||||
edgesMap.put(instruction, initialEdge);
|
||||
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
|
||||
initializeDataMap(lookInside, dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue);
|
||||
initializeEdgesMap(((LocalDeclarationInstruction) instruction).getBody(), lookInside, edgesMap, initialDataValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static <D> void traverseSubGraph(
|
||||
boolean lookInside,
|
||||
@NotNull Pseudocode pseudocode,
|
||||
@NotNull Map<Instruction, Edges<D>> dataMap,
|
||||
private static <D> void collectInformationFromSubgraph(
|
||||
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
|
||||
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
||||
@NotNull InstructionDataMergeStrategy<D> instructionDataMergeStrategy,
|
||||
@NotNull Collection<Instruction> previousSubGraphInstructions,
|
||||
boolean directOrder,
|
||||
boolean[] changed,
|
||||
boolean isLocal) {
|
||||
boolean[] changed, boolean isLocal) {
|
||||
|
||||
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
|
||||
Instruction startInstruction = getStartInstruction(pseudocode, directOrder);
|
||||
|
||||
@@ -101,22 +97,24 @@ public class PseudocodeTraverser {
|
||||
|
||||
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
|
||||
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
|
||||
traverseSubGraph(lookInside, subroutinePseudocode, dataMap ,instructionDataMergeStrategy, previousInstructions, directOrder, changed, true);
|
||||
collectInformationFromSubgraph(subroutinePseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy,
|
||||
previousInstructions,
|
||||
changed, true);
|
||||
Instruction lastInstruction = directOrder ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction();
|
||||
Edges<D> previousValue = dataMap.get(instruction);
|
||||
Edges<D> newValue = dataMap.get(lastInstruction);
|
||||
Edges<D> previousValue = edgesMap.get(instruction);
|
||||
Edges<D> newValue = edgesMap.get(lastInstruction);
|
||||
if (!previousValue.equals(newValue)) {
|
||||
changed[0] = true;
|
||||
dataMap.put(instruction, newValue);
|
||||
edgesMap.put(instruction, newValue);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Edges<D> previousDataValue = dataMap.get(instruction);
|
||||
Edges<D> previousDataValue = edgesMap.get(instruction);
|
||||
|
||||
Collection<D> incomingEdgesData = Sets.newHashSet();
|
||||
|
||||
for (Instruction previousInstruction : allPreviousInstructions) {
|
||||
Edges<D> previousData = dataMap.get(previousInstruction);
|
||||
Edges<D> previousData = edgesMap.get(previousInstruction);
|
||||
if (previousData != null) {
|
||||
incomingEdgesData.add(previousData.out);
|
||||
}
|
||||
@@ -124,36 +122,36 @@ public class PseudocodeTraverser {
|
||||
Edges<D> mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData);
|
||||
if (!mergedData.equals(previousDataValue)) {
|
||||
changed[0] = true;
|
||||
dataMap.put(instruction, mergedData);
|
||||
edgesMap.put(instruction, mergedData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void traverseAndAnalyzeInstructionGraph(
|
||||
@NotNull Pseudocode pseudocode,
|
||||
boolean directOrder,
|
||||
SimpleInstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) {
|
||||
public static void traverse(
|
||||
@NotNull Pseudocode pseudocode, boolean directOrder,
|
||||
InstructionAnalyzeStrategy instructionAnalyzeStrategy) {
|
||||
|
||||
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
|
||||
for (Instruction instruction : instructions) {
|
||||
if (instruction instanceof LocalDeclarationInstruction) {
|
||||
traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), directOrder, instructionDataAnalyzeStrategy);
|
||||
traverse(((LocalDeclarationInstruction) instruction).getBody(), directOrder, instructionAnalyzeStrategy);
|
||||
}
|
||||
instructionDataAnalyzeStrategy.execute(instruction);
|
||||
instructionAnalyzeStrategy.execute(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
public static <D> void traverseAndAnalyzeInstructionGraph(
|
||||
boolean lookInside,
|
||||
@NotNull Pseudocode pseudocode,
|
||||
@NotNull Map<Instruction, Edges<D>> dataMap,
|
||||
boolean directOrder,
|
||||
public static <D> void traverse(
|
||||
@NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside,
|
||||
@NotNull Map<Instruction, Edges<D>> edgesMap,
|
||||
@NotNull InstructionDataAnalyzeStrategy<D> instructionDataAnalyzeStrategy) {
|
||||
|
||||
List<Instruction> instructions = directOrder ? pseudocode.getInstructions() : pseudocode.getReversedInstructions();
|
||||
for (Instruction instruction : instructions) {
|
||||
if (lookInside && instruction instanceof LocalDeclarationInstruction) {
|
||||
traverseAndAnalyzeInstructionGraph(lookInside, ((LocalDeclarationInstruction) instruction).getBody(), dataMap, directOrder, instructionDataAnalyzeStrategy);
|
||||
traverse(((LocalDeclarationInstruction) instruction).getBody(), directOrder, lookInside, edgesMap,
|
||||
instructionDataAnalyzeStrategy);
|
||||
}
|
||||
Edges<D> edges = dataMap.get(instruction);
|
||||
Edges<D> edges = edgesMap.get(instruction);
|
||||
instructionDataAnalyzeStrategy.execute(instruction, edges != null ? edges.in : null, edges != null ? edges.out : null);
|
||||
}
|
||||
}
|
||||
@@ -166,7 +164,7 @@ public class PseudocodeTraverser {
|
||||
void execute(@NotNull Instruction instruction, @Nullable D enterData, @Nullable D exitData);
|
||||
}
|
||||
|
||||
public interface SimpleInstructionDataAnalyzeStrategy {
|
||||
public interface InstructionAnalyzeStrategy {
|
||||
void execute(@NotNull Instruction instruction);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.Edges;
|
||||
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;
|
||||
@@ -57,11 +57,12 @@ public class PseudocodeVariablesData {
|
||||
return pseudocode;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<VariableDescriptor> getUsedVariables(@NotNull Pseudocode pseudocode) {
|
||||
Set<VariableDescriptor> usedVariables = usedVariablesInEachDeclaration.get(pseudocode);
|
||||
if (usedVariables == null) {
|
||||
final Set<VariableDescriptor> result = Sets.newHashSet();
|
||||
PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, true, new PseudocodeTraverser.SimpleInstructionDataAnalyzeStrategy() {
|
||||
PseudocodeTraverser.traverse(pseudocode, true, new InstructionAnalyzeStrategy() {
|
||||
@Override
|
||||
public void execute(@NotNull Instruction instruction) {
|
||||
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, false,
|
||||
@@ -77,6 +78,7 @@ public class PseudocodeVariablesData {
|
||||
return usedVariables;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<VariableDescriptor> getDeclaredVariables(@NotNull Pseudocode pseudocode) {
|
||||
Set<VariableDescriptor> declaredVariables = declaredVariablesInEachDeclaration.get(pseudocode);
|
||||
if (declaredVariables == null) {
|
||||
@@ -108,22 +110,24 @@ public class PseudocodeVariablesData {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> getVariableInitializers(Pseudocode pseudocode) {
|
||||
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> getVariableInitializers(@NotNull Pseudocode pseudocode) {
|
||||
|
||||
Set<VariableDescriptor> usedVariables = getUsedVariables(pseudocode);
|
||||
Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode);
|
||||
final Map<VariableDescriptor, VariableInitializers> initialMapForStartInstruction = prepareInitialMapForStartInstruction(usedVariables, declaredVariables);
|
||||
Map<VariableDescriptor, VariableInitializers> initialMap = Collections.emptyMap();
|
||||
final Map<VariableDescriptor, VariableInitializers> initialMapForStartInstruction = prepareInitializersMapForStartInstruction(
|
||||
usedVariables, declaredVariables);
|
||||
|
||||
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> variableInitializersMap = PseudocodeTraverser.collectInformationFromInstructionGraph(false, true, pseudocode,
|
||||
Collections.<VariableDescriptor, VariableInitializers>emptyMap(), initialMapForStartInstruction,
|
||||
new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitializers>>() {
|
||||
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> variableInitializersMap = PseudocodeTraverser.collectInformation(
|
||||
pseudocode, /* directOrder = */ true, /* lookInside = */ false,
|
||||
initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitializers>>() {
|
||||
@Override
|
||||
public Edges<Map<VariableDescriptor, VariableInitializers>> execute(
|
||||
@NotNull Instruction instruction,
|
||||
@NotNull Collection<Map<VariableDescriptor, VariableInitializers>> incomingEdgesData) {
|
||||
@NotNull Instruction instruction, @NotNull Collection<Map<VariableDescriptor, VariableInitializers>> incomingEdgesData) {
|
||||
|
||||
Map<VariableDescriptor, VariableInitializers> enterInstructionData = mergeIncomingEdgesData(incomingEdgesData);
|
||||
Map<VariableDescriptor, VariableInitializers> exitInstructionData = addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData);
|
||||
Map<VariableDescriptor, VariableInitializers> enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData);
|
||||
Map<VariableDescriptor, VariableInitializers> exitInstructionData =
|
||||
addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData);
|
||||
return Edges.create(enterInstructionData, exitInstructionData);
|
||||
}
|
||||
});
|
||||
@@ -144,7 +148,11 @@ public class PseudocodeVariablesData {
|
||||
return variableInitializersMap;
|
||||
}
|
||||
|
||||
private Map<VariableDescriptor, VariableInitializers> prepareInitialMapForStartInstruction(Collection<VariableDescriptor> usedVariables, Collection<VariableDescriptor> declaredVariables) {
|
||||
@NotNull
|
||||
private Map<VariableDescriptor, VariableInitializers> prepareInitializersMapForStartInstruction(
|
||||
@NotNull Collection<VariableDescriptor> usedVariables,
|
||||
@NotNull Collection<VariableDescriptor> declaredVariables) {
|
||||
|
||||
Map<VariableDescriptor, VariableInitializers> initialMapForStartInstruction = Maps.newHashMap();
|
||||
VariableInitializers isInitializedForExternalVariable = new VariableInitializers(true);
|
||||
VariableInitializers isNotInitializedForDeclaredVariable = new VariableInitializers(false);
|
||||
@@ -160,7 +168,10 @@ public class PseudocodeVariablesData {
|
||||
return initialMapForStartInstruction;
|
||||
}
|
||||
|
||||
private Map<VariableDescriptor, VariableInitializers> mergeIncomingEdgesData(Collection<Map<VariableDescriptor, VariableInitializers>> incomingEdgesData) {
|
||||
@NotNull
|
||||
private Map<VariableDescriptor, VariableInitializers> mergeIncomingEdgesDataForInitializers(
|
||||
@NotNull Collection<Map<VariableDescriptor, VariableInitializers>> incomingEdgesData) {
|
||||
|
||||
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
|
||||
for (Map<VariableDescriptor, VariableInitializers> edgeData : incomingEdgesData) {
|
||||
variablesInScope.addAll(edgeData.keySet());
|
||||
@@ -180,7 +191,10 @@ public class PseudocodeVariablesData {
|
||||
return enterInstructionData;
|
||||
}
|
||||
|
||||
private Map<VariableDescriptor, VariableInitializers> addVariableInitializerFromCurrentInstructionIfAny(Instruction instruction, Map<VariableDescriptor, VariableInitializers> enterInstructionData) {
|
||||
@NotNull
|
||||
private Map<VariableDescriptor, VariableInitializers> addVariableInitializerFromCurrentInstructionIfAny(
|
||||
@NotNull Instruction instruction, @NotNull Map<VariableDescriptor, VariableInitializers> enterInstructionData) {
|
||||
|
||||
if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) {
|
||||
return enterInstructionData;
|
||||
}
|
||||
@@ -214,49 +228,55 @@ public class PseudocodeVariablesData {
|
||||
// variable use
|
||||
|
||||
@NotNull
|
||||
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseStatus>>> getVariableStatusData() {
|
||||
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseStatus>>> getVariableUseStatusData() {
|
||||
if (variableStatusMap == null) {
|
||||
Map<VariableDescriptor, VariableUseStatus> sinkInstructionData = Maps.newHashMap();
|
||||
for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) {
|
||||
sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED);
|
||||
}
|
||||
variableStatusMap = PseudocodeTraverser.collectInformationFromInstructionGraph(true, false, pseudocode,
|
||||
Collections.<VariableDescriptor, VariableUseStatus>emptyMap(), sinkInstructionData,
|
||||
new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseStatus>>() {
|
||||
@Override
|
||||
public Edges<Map<VariableDescriptor, VariableUseStatus>> execute(@NotNull Instruction instruction, @NotNull Collection<Map<VariableDescriptor, VariableUseStatus>> incomingEdgesData) {
|
||||
Map<VariableDescriptor, VariableUseStatus> enterResult = Maps.newHashMap();
|
||||
for (Map<VariableDescriptor, VariableUseStatus> edgeData : incomingEdgesData) {
|
||||
for (Map.Entry<VariableDescriptor, VariableUseStatus> entry : edgeData.entrySet()) {
|
||||
VariableDescriptor variableDescriptor = entry.getKey();
|
||||
VariableUseStatus variableUseStatus = entry.getValue();
|
||||
enterResult.put(variableDescriptor, variableUseStatus.merge(enterResult.get(variableDescriptor)));
|
||||
}
|
||||
}
|
||||
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, bindingContext);
|
||||
if (variableDescriptor == null || (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) {
|
||||
return Edges.create(enterResult, enterResult);
|
||||
}
|
||||
Map<VariableDescriptor, VariableUseStatus> exitResult = Maps.newHashMap(enterResult);
|
||||
if (instruction instanceof ReadValueInstruction) {
|
||||
exitResult.put(variableDescriptor, VariableUseStatus.LAST_READ);
|
||||
}
|
||||
else {
|
||||
VariableUseStatus variableUseStatus = enterResult.get(variableDescriptor);
|
||||
if (variableUseStatus == null) variableUseStatus = VariableUseStatus.UNUSED;
|
||||
switch (variableUseStatus) {
|
||||
case UNUSED:
|
||||
case ONLY_WRITTEN_NEVER_READ:
|
||||
exitResult.put(variableDescriptor, VariableUseStatus.ONLY_WRITTEN_NEVER_READ);
|
||||
break;
|
||||
case LAST_WRITTEN:
|
||||
case LAST_READ:
|
||||
exitResult.put(variableDescriptor, VariableUseStatus.LAST_WRITTEN);
|
||||
}
|
||||
}
|
||||
return Edges.create(enterResult, exitResult);
|
||||
Map<VariableDescriptor, VariableUseStatus> sinkInstructionData = Maps.newHashMap();
|
||||
for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) {
|
||||
sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED);
|
||||
}
|
||||
});
|
||||
InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseStatus>> collectVariableUseStatusStrategy = new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseStatus>>() {
|
||||
@Override
|
||||
public Edges<Map<VariableDescriptor, VariableUseStatus>> execute(@NotNull Instruction instruction,
|
||||
@NotNull Collection<Map<VariableDescriptor, VariableUseStatus>> incomingEdgesData) {
|
||||
|
||||
Map<VariableDescriptor, VariableUseStatus> enterResult = Maps.newHashMap();
|
||||
for (Map<VariableDescriptor, VariableUseStatus> edgeData : incomingEdgesData) {
|
||||
for (Map.Entry<VariableDescriptor, VariableUseStatus> entry : edgeData.entrySet()) {
|
||||
VariableDescriptor variableDescriptor = entry.getKey();
|
||||
VariableUseStatus variableUseStatus = entry.getValue();
|
||||
enterResult.put(variableDescriptor, variableUseStatus.merge(enterResult.get(variableDescriptor)));
|
||||
}
|
||||
}
|
||||
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true,
|
||||
bindingContext);
|
||||
if (variableDescriptor == null ||
|
||||
(!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) {
|
||||
return Edges.create(enterResult, enterResult);
|
||||
}
|
||||
Map<VariableDescriptor, VariableUseStatus> exitResult = Maps.newHashMap(enterResult);
|
||||
if (instruction instanceof ReadValueInstruction) {
|
||||
exitResult.put(variableDescriptor, VariableUseStatus.LAST_READ);
|
||||
}
|
||||
else {
|
||||
VariableUseStatus variableUseStatus = enterResult.get(variableDescriptor);
|
||||
if (variableUseStatus == null) {
|
||||
variableUseStatus = VariableUseStatus.UNUSED;
|
||||
}
|
||||
switch (variableUseStatus) {
|
||||
case UNUSED:
|
||||
case ONLY_WRITTEN_NEVER_READ:
|
||||
exitResult.put(variableDescriptor, VariableUseStatus.ONLY_WRITTEN_NEVER_READ);
|
||||
break;
|
||||
case LAST_WRITTEN:
|
||||
case LAST_READ:
|
||||
exitResult.put(variableDescriptor, VariableUseStatus.LAST_WRITTEN);
|
||||
}
|
||||
}
|
||||
return Edges.create(enterResult, exitResult);
|
||||
}
|
||||
};
|
||||
variableStatusMap = PseudocodeTraverser.collectInformation(pseudocode, false, true,
|
||||
Collections.<VariableDescriptor, VariableUseStatus>emptyMap(), sinkInstructionData, collectVariableUseStatusStrategy);
|
||||
}
|
||||
return variableStatusMap;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user