rewrote PseudocodeVariableDataCollector to kotlin
This commit is contained in:
@@ -101,6 +101,7 @@ public class PseudocodeTraverser {
|
||||
}
|
||||
|
||||
public interface InstructionDataMergeStrategy<D> {
|
||||
@NotNull
|
||||
Edges<D> execute(@NotNull Instruction instruction, @NotNull Collection<D> incomingEdgesData);
|
||||
}
|
||||
|
||||
@@ -113,7 +114,9 @@ public class PseudocodeTraverser {
|
||||
}
|
||||
|
||||
public static class Edges<T> {
|
||||
@NotNull
|
||||
public final T in;
|
||||
@NotNull
|
||||
public final T out;
|
||||
|
||||
Edges(@NotNull T in, @NotNull T out) {
|
||||
@@ -121,6 +124,7 @@ public class PseudocodeTraverser {
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> Edges<T> create(@NotNull T in, @NotNull T out) {
|
||||
return new Edges<T>(in, out);
|
||||
}
|
||||
|
||||
+90
-79
@@ -14,119 +14,130 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.cfg;
|
||||
package org.jetbrains.jet.lang.cfg
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Instruction;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Instruction
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*
|
||||
|
||||
import java.util.*;
|
||||
import java.util.*
|
||||
|
||||
public class PseudocodeVariableDataCollector extends PseudocodeTraverser {
|
||||
private final BindingContext bindingContext;
|
||||
public class PseudocodeVariableDataCollector(private val bindingContext: BindingContext) : PseudocodeTraverser() {
|
||||
|
||||
public PseudocodeVariableDataCollector(@NotNull BindingContext context) {
|
||||
bindingContext = context;
|
||||
suppress("UNCHECKED_CAST")
|
||||
public fun <D> collectDataJ(
|
||||
pseudocode: Pseudocode,
|
||||
traversalOrder: TraversalOrder,
|
||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<MutableMap<VariableDescriptor, D>>
|
||||
): MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>> {
|
||||
//see KT-4605
|
||||
return collectData(
|
||||
pseudocode, traversalOrder,
|
||||
instructionDataMergeStrategy as InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
|
||||
) as MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>>
|
||||
}
|
||||
|
||||
public <D> Map<Instruction, Edges<Map<VariableDescriptor, D>>> collectData(
|
||||
@NotNull Pseudocode pseudocode,
|
||||
@NotNull TraversalOrder traversalOrder,
|
||||
@NotNull InstructionDataMergeStrategy<Map<VariableDescriptor, D>> instructionDataMergeStrategy
|
||||
) {
|
||||
Map<VariableDescriptor, D> initialDataValue = Collections.emptyMap();
|
||||
Map<Instruction, Edges<Map<VariableDescriptor, D>>> edgesMap = Maps.newLinkedHashMap();
|
||||
initializeEdgesMap(pseudocode, edgesMap, initialDataValue);
|
||||
edgesMap.put(getStartInstruction(pseudocode, traversalOrder), Edges.create(initialDataValue, initialDataValue));
|
||||
public fun <D> collectData(
|
||||
pseudocode: Pseudocode,
|
||||
traversalOrder: TraversalOrder,
|
||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
|
||||
): Map<Instruction, Edges<Map<VariableDescriptor, D>>> {
|
||||
val initialDataValue : Map<VariableDescriptor, D> = Collections.emptyMap<VariableDescriptor, D>()
|
||||
val edgesMap = LinkedHashMap<Instruction, Edges<Map<VariableDescriptor, D>>>()
|
||||
initializeEdgesMap(pseudocode, edgesMap, initialDataValue)
|
||||
edgesMap.put(getStartInstruction(pseudocode, traversalOrder),
|
||||
Edges.create(initialDataValue, initialDataValue))
|
||||
|
||||
boolean[] changed = new boolean[1];
|
||||
changed[0] = true;
|
||||
val changed = BooleanArray(1)
|
||||
changed[0] = true
|
||||
while (changed[0]) {
|
||||
changed[0] = false;
|
||||
collectDataFromSubgraph(pseudocode, traversalOrder, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS, edgesMap,
|
||||
instructionDataMergeStrategy, Collections.<Instruction>emptyList(), changed, false);
|
||||
changed[0] = false
|
||||
collectDataFromSubgraph(
|
||||
pseudocode, traversalOrder, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS, edgesMap,
|
||||
instructionDataMergeStrategy, Collections.emptyList<Instruction>(), changed, false)
|
||||
}
|
||||
return edgesMap;
|
||||
return edgesMap
|
||||
}
|
||||
|
||||
private static <M> void initializeEdgesMap(
|
||||
@NotNull Pseudocode pseudocode,
|
||||
@NotNull Map<Instruction, Edges<M>> edgesMap,
|
||||
@NotNull M initialDataValue
|
||||
private fun <M> initializeEdgesMap(
|
||||
pseudocode: Pseudocode,
|
||||
edgesMap: MutableMap<Instruction, Edges<M>>,
|
||||
initialDataValue: M
|
||||
) {
|
||||
List<Instruction> instructions = pseudocode.getInstructions();
|
||||
Edges<M> initialEdge = Edges.create(initialDataValue, initialDataValue);
|
||||
for (Instruction instruction : instructions) {
|
||||
edgesMap.put(instruction, initialEdge);
|
||||
if (shouldLookInside(instruction, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS)) {
|
||||
initializeEdgesMap(((LocalFunctionDeclarationInstruction) instruction).getBody(), edgesMap, initialDataValue);
|
||||
val instructions = pseudocode.getInstructions()
|
||||
val initialEdge = Edges.create(initialDataValue, initialDataValue)
|
||||
for (instruction in instructions) {
|
||||
edgesMap.put(instruction, initialEdge)
|
||||
if (PseudocodeTraverser.shouldLookInside(instruction, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS)) {
|
||||
initializeEdgesMap(((instruction as LocalFunctionDeclarationInstruction)).getBody(), edgesMap, initialDataValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private <D> void collectDataFromSubgraph(
|
||||
@NotNull Pseudocode pseudocode,
|
||||
@NotNull TraversalOrder traversalOrder,
|
||||
@NotNull LookInsideStrategy lookInside,
|
||||
@NotNull Map<Instruction, Edges<Map<VariableDescriptor, D>>> edgesMap,
|
||||
@NotNull InstructionDataMergeStrategy<Map<VariableDescriptor, D>> instructionDataMergeStrategy,
|
||||
@NotNull Collection<Instruction> previousSubGraphInstructions,
|
||||
boolean[] changed,
|
||||
boolean isLocal
|
||||
private fun <D> collectDataFromSubgraph(
|
||||
pseudocode: Pseudocode,
|
||||
traversalOrder: TraversalOrder,
|
||||
lookInside: LookInsideStrategy,
|
||||
edgesMap: MutableMap<Instruction, Edges<Map<VariableDescriptor, D>>>,
|
||||
instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>,
|
||||
previousSubGraphInstructions: Collection<Instruction>,
|
||||
changed: BooleanArray,
|
||||
isLocal: Boolean
|
||||
) {
|
||||
List<Instruction> instructions = getInstructions(pseudocode, traversalOrder);
|
||||
Instruction startInstruction = getStartInstruction(pseudocode, traversalOrder);
|
||||
val instructions = getInstructions(pseudocode, traversalOrder)
|
||||
val startInstruction = getStartInstruction(pseudocode, traversalOrder)
|
||||
|
||||
for (Instruction instruction : instructions) {
|
||||
boolean isStart = isStartInstruction(instruction, traversalOrder);
|
||||
if (!isLocal && isStart) continue;
|
||||
for (instruction in instructions) {
|
||||
val isStart = isStartInstruction(instruction, traversalOrder)
|
||||
if (!isLocal && isStart)
|
||||
continue
|
||||
|
||||
Collection<Instruction> allPreviousInstructions;
|
||||
Collection<Instruction> previousInstructions = getPreviousInstruction(instruction, traversalOrder);
|
||||
val allPreviousInstructions: MutableCollection<Instruction>
|
||||
val previousInstructions = getPreviousInstruction(instruction, traversalOrder)
|
||||
|
||||
if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) {
|
||||
allPreviousInstructions = Lists.newArrayList(previousInstructions);
|
||||
allPreviousInstructions.addAll(previousSubGraphInstructions);
|
||||
allPreviousInstructions = ArrayList(previousInstructions)
|
||||
allPreviousInstructions.addAll(previousSubGraphInstructions)
|
||||
}
|
||||
else {
|
||||
allPreviousInstructions = previousInstructions;
|
||||
allPreviousInstructions = previousInstructions
|
||||
}
|
||||
|
||||
if (shouldLookInside(instruction, lookInside)) {
|
||||
LocalFunctionDeclarationInstruction functionInstruction = (LocalFunctionDeclarationInstruction) instruction;
|
||||
Pseudocode subroutinePseudocode = functionInstruction.getBody();
|
||||
collectDataFromSubgraph(subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy,
|
||||
previousInstructions,
|
||||
changed, true);
|
||||
Instruction lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder);
|
||||
Edges<Map<VariableDescriptor, D>> previousValue = edgesMap.get(instruction);
|
||||
Edges<Map<VariableDescriptor, D>> newValue = edgesMap.get(lastInstruction);
|
||||
if (!previousValue.equals(newValue)) {
|
||||
changed[0] = true;
|
||||
edgesMap.put(instruction, newValue);
|
||||
val functionInstruction = (instruction as LocalFunctionDeclarationInstruction)
|
||||
val subroutinePseudocode = functionInstruction.getBody()
|
||||
collectDataFromSubgraph(
|
||||
subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy,
|
||||
previousInstructions, changed, true)
|
||||
val lastInstruction = getLastInstruction(subroutinePseudocode, traversalOrder)
|
||||
val previousValue = edgesMap.get(instruction)
|
||||
val newValue = edgesMap.get(lastInstruction)
|
||||
if (previousValue != newValue && newValue != null) {
|
||||
changed[0] = true
|
||||
edgesMap.put(instruction, newValue)
|
||||
}
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
Edges<Map<VariableDescriptor, D>> previousDataValue = edgesMap.get(instruction);
|
||||
val previousDataValue = edgesMap.get(instruction)
|
||||
|
||||
Collection<Map<VariableDescriptor, D>> incomingEdgesData = Sets.newHashSet();
|
||||
val incomingEdgesData = HashSet<Map<VariableDescriptor, D>>()
|
||||
|
||||
for (Instruction previousInstruction : allPreviousInstructions) {
|
||||
Edges<Map<VariableDescriptor, D>> previousData = edgesMap.get(previousInstruction);
|
||||
for (previousInstruction in allPreviousInstructions) {
|
||||
val previousData = edgesMap.get(previousInstruction)
|
||||
if (previousData != null) {
|
||||
incomingEdgesData.add(previousData.out);
|
||||
incomingEdgesData.add(previousData.out)
|
||||
}
|
||||
}
|
||||
Edges<Map<VariableDescriptor, D>> mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData);
|
||||
val mergedData = instructionDataMergeStrategy.execute(instruction, incomingEdgesData)
|
||||
if (!mergedData.equals(previousDataValue)) {
|
||||
changed[0] = true;
|
||||
edgesMap.put(instruction, mergedData);
|
||||
changed[0] = true
|
||||
edgesMap.put(instruction, mergedData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,9 +135,10 @@ public class PseudocodeVariablesData {
|
||||
|
||||
final Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode, true);
|
||||
|
||||
return new PseudocodeVariableDataCollector(bindingContext).collectData(
|
||||
return new PseudocodeVariableDataCollector(bindingContext).collectDataJ(
|
||||
pseudocode, FORWARD,
|
||||
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Edges<Map<VariableDescriptor, VariableInitState>> execute(
|
||||
@NotNull Instruction instruction,
|
||||
@@ -150,7 +151,8 @@ public class PseudocodeVariablesData {
|
||||
addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData, declaredVariables);
|
||||
return Edges.create(enterInstructionData, exitInstructionData);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static VariableInitState getDefaultValueForInitializers(
|
||||
@@ -229,9 +231,10 @@ public class PseudocodeVariablesData {
|
||||
|
||||
@NotNull
|
||||
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
|
||||
return new PseudocodeVariableDataCollector(bindingContext).collectData(
|
||||
return new PseudocodeVariableDataCollector(bindingContext).collectDataJ(
|
||||
pseudocode, BACKWARD,
|
||||
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Edges<Map<VariableDescriptor, VariableUseState>> execute(
|
||||
@NotNull Instruction instruction,
|
||||
|
||||
Reference in New Issue
Block a user