diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index a271bf70c6f..cc6166b160f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -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>> initializers = pseudocodeData.getVariableInitializers(); final Set declaredVariables = pseudocodeData.getDeclaredVariables(pseudocode); - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(true, pseudocode, initializers, true, new PseudocodeTraverser.InstructionDataAnalyzeStrategy>() { + PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy>() { @Override public void execute(@NotNull Instruction instruction, @Nullable Map in, @Nullable Map 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>> variableStatusData = pseudocodeData.getVariableStatusData(); - PseudocodeTraverser.traverseAndAnalyzeInstructionGraph(true, pseudocode, variableStatusData, false, new PseudocodeTraverser.InstructionDataAnalyzeStrategy>() { + Map>> variableStatusData = pseudocodeData.getVariableUseStatusData(); + InstructionDataAnalyzeStrategy> variableStatusAnalyzeStrategy = + new InstructionDataAnalyzeStrategy>() { @Override public void execute(@NotNull Instruction instruction, @Nullable Map in, @@ -422,7 +425,7 @@ public class JetFlowInformationProvider { assert in != null && out != null; Set 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; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java index e8010b4d31a..b0a8e4884eb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -37,50 +37,46 @@ public class PseudocodeTraverser { return directOrder ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } - public static Map> collectInformationFromInstructionGraph( - boolean lookInside, - boolean directOrder, - @NotNull Pseudocode pseudocode, - @NotNull D initialDataValue, - @NotNull D initialDataValueForEnterInstruction, + public static Map> collectInformation( + @NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside, + @NotNull D initialDataValue, @NotNull D initialDataValueForEnterInstruction, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy) { - Map> dataMap = Maps.newLinkedHashMap(); - initializeDataMap(lookInside, dataMap, pseudocode, initialDataValue); - dataMap.put(getStartInstruction(pseudocode, directOrder), - Edges.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); + + Map> 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.emptyList(), directOrder, changed, false); + collectInformationFromSubgraph(pseudocode, directOrder, lookInside, edgesMap, instructionDataMergeStrategy, + Collections.emptyList(), changed, false); } - return dataMap; + return edgesMap; } - private static void initializeDataMap( - boolean lookInside, - @NotNull Map> dataMap, @NotNull Pseudocode pseudocode, + private static void initializeEdgesMap( + @NotNull Pseudocode pseudocode, boolean lookInside, + @NotNull Map> edgesMap, @NotNull D initialDataValue) { List instructions = pseudocode.getInstructions(); Edges 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 void traverseSubGraph( - boolean lookInside, - @NotNull Pseudocode pseudocode, - @NotNull Map> dataMap, + private static void collectInformationFromSubgraph( + @NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside, + @NotNull Map> edgesMap, @NotNull InstructionDataMergeStrategy instructionDataMergeStrategy, @NotNull Collection previousSubGraphInstructions, - boolean directOrder, - boolean[] changed, - boolean isLocal) { + boolean[] changed, boolean isLocal) { + List 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 previousValue = dataMap.get(instruction); - Edges newValue = dataMap.get(lastInstruction); + Edges previousValue = edgesMap.get(instruction); + Edges newValue = edgesMap.get(lastInstruction); if (!previousValue.equals(newValue)) { changed[0] = true; - dataMap.put(instruction, newValue); + edgesMap.put(instruction, newValue); } continue; } - Edges previousDataValue = dataMap.get(instruction); + Edges previousDataValue = edgesMap.get(instruction); Collection incomingEdgesData = Sets.newHashSet(); for (Instruction previousInstruction : allPreviousInstructions) { - Edges previousData = dataMap.get(previousInstruction); + Edges previousData = edgesMap.get(previousInstruction); if (previousData != null) { incomingEdgesData.add(previousData.out); } @@ -124,36 +122,36 @@ public class PseudocodeTraverser { Edges 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 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 void traverseAndAnalyzeInstructionGraph( - boolean lookInside, - @NotNull Pseudocode pseudocode, - @NotNull Map> dataMap, - boolean directOrder, + public static void traverse( + @NotNull Pseudocode pseudocode, boolean directOrder, boolean lookInside, + @NotNull Map> edgesMap, @NotNull InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { + List 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 edges = dataMap.get(instruction); + Edges 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); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java index 9247f6d1189..c75e869cfe3 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -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 getUsedVariables(@NotNull Pseudocode pseudocode) { Set usedVariables = usedVariablesInEachDeclaration.get(pseudocode); if (usedVariables == null) { final Set 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 getDeclaredVariables(@NotNull Pseudocode pseudocode) { Set declaredVariables = declaredVariablesInEachDeclaration.get(pseudocode); if (declaredVariables == null) { @@ -108,22 +110,24 @@ public class PseudocodeVariablesData { } @NotNull - private Map>> getVariableInitializers(Pseudocode pseudocode) { + private Map>> getVariableInitializers(@NotNull Pseudocode pseudocode) { Set usedVariables = getUsedVariables(pseudocode); Set declaredVariables = getDeclaredVariables(pseudocode); - final Map initialMapForStartInstruction = prepareInitialMapForStartInstruction(usedVariables, declaredVariables); + Map initialMap = Collections.emptyMap(); + final Map initialMapForStartInstruction = prepareInitializersMapForStartInstruction( + usedVariables, declaredVariables); - Map>> variableInitializersMap = PseudocodeTraverser.collectInformationFromInstructionGraph(false, true, pseudocode, - Collections.emptyMap(), initialMapForStartInstruction, - new PseudocodeTraverser.InstructionDataMergeStrategy>() { + Map>> variableInitializersMap = PseudocodeTraverser.collectInformation( + pseudocode, /* directOrder = */ true, /* lookInside = */ false, + initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy>() { @Override public Edges> execute( - @NotNull Instruction instruction, - @NotNull Collection> incomingEdgesData) { + @NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { - Map enterInstructionData = mergeIncomingEdgesData(incomingEdgesData); - Map exitInstructionData = addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); + Map enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData); + Map exitInstructionData = + addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData); return Edges.create(enterInstructionData, exitInstructionData); } }); @@ -144,7 +148,11 @@ public class PseudocodeVariablesData { return variableInitializersMap; } - private Map prepareInitialMapForStartInstruction(Collection usedVariables, Collection declaredVariables) { + @NotNull + private Map prepareInitializersMapForStartInstruction( + @NotNull Collection usedVariables, + @NotNull Collection declaredVariables) { + Map initialMapForStartInstruction = Maps.newHashMap(); VariableInitializers isInitializedForExternalVariable = new VariableInitializers(true); VariableInitializers isNotInitializedForDeclaredVariable = new VariableInitializers(false); @@ -160,7 +168,10 @@ public class PseudocodeVariablesData { return initialMapForStartInstruction; } - private Map mergeIncomingEdgesData(Collection> incomingEdgesData) { + @NotNull + private Map mergeIncomingEdgesDataForInitializers( + @NotNull Collection> incomingEdgesData) { + Set variablesInScope = Sets.newHashSet(); for (Map edgeData : incomingEdgesData) { variablesInScope.addAll(edgeData.keySet()); @@ -180,7 +191,10 @@ public class PseudocodeVariablesData { return enterInstructionData; } - private Map addVariableInitializerFromCurrentInstructionIfAny(Instruction instruction, Map enterInstructionData) { + @NotNull + private Map addVariableInitializerFromCurrentInstructionIfAny( + @NotNull Instruction instruction, @NotNull Map enterInstructionData) { + if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) { return enterInstructionData; } @@ -214,49 +228,55 @@ public class PseudocodeVariablesData { // variable use @NotNull - public Map>> getVariableStatusData() { + public Map>> getVariableUseStatusData() { if (variableStatusMap == null) { - Map sinkInstructionData = Maps.newHashMap(); - for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) { - sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED); - } - variableStatusMap = PseudocodeTraverser.collectInformationFromInstructionGraph(true, false, pseudocode, - Collections.emptyMap(), sinkInstructionData, - new PseudocodeTraverser.InstructionDataMergeStrategy>() { - @Override - public Edges> execute(@NotNull Instruction instruction, @NotNull Collection> incomingEdgesData) { - Map enterResult = Maps.newHashMap(); - for (Map edgeData : incomingEdgesData) { - for (Map.Entry 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 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 sinkInstructionData = Maps.newHashMap(); + for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) { + sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED); } - }); + InstructionDataMergeStrategy> collectVariableUseStatusStrategy = new InstructionDataMergeStrategy>() { + @Override + public Edges> execute(@NotNull Instruction instruction, + @NotNull Collection> incomingEdgesData) { + + Map enterResult = Maps.newHashMap(); + for (Map edgeData : incomingEdgesData) { + for (Map.Entry 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 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.emptyMap(), sinkInstructionData, collectVariableUseStatusStrategy); } return variableStatusMap; }