changes in 'PseudocodeTraverser' interface

This commit is contained in:
Svetlana Isakova
2012-05-26 17:01:07 +04:00
parent 8acfa20a02
commit a79ea0c86b
3 changed files with 139 additions and 128 deletions
@@ -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;
}