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 0e848c6268e..e57e1974596 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeTraverser.java @@ -101,6 +101,7 @@ public class PseudocodeTraverser { } public interface InstructionDataMergeStrategy { + @NotNull Edges execute(@NotNull Instruction instruction, @NotNull Collection incomingEdgesData); } @@ -113,7 +114,9 @@ public class PseudocodeTraverser { } public static class Edges { + @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 Edges create(@NotNull T in, @NotNull T out) { return new Edges(in, out); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt index 8f4efc98e2a..aff66d7afdf 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariableDataCollector.kt @@ -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 collectDataJ( + pseudocode: Pseudocode, + traversalOrder: TraversalOrder, + instructionDataMergeStrategy: InstructionDataMergeStrategy> + ): MutableMap>> { + //see KT-4605 + return collectData( + pseudocode, traversalOrder, + instructionDataMergeStrategy as InstructionDataMergeStrategy> + ) as MutableMap>> } - public Map>> collectData( - @NotNull Pseudocode pseudocode, - @NotNull TraversalOrder traversalOrder, - @NotNull InstructionDataMergeStrategy> instructionDataMergeStrategy - ) { - Map initialDataValue = Collections.emptyMap(); - Map>> edgesMap = Maps.newLinkedHashMap(); - initializeEdgesMap(pseudocode, edgesMap, initialDataValue); - edgesMap.put(getStartInstruction(pseudocode, traversalOrder), Edges.create(initialDataValue, initialDataValue)); + public fun collectData( + pseudocode: Pseudocode, + traversalOrder: TraversalOrder, + instructionDataMergeStrategy: InstructionDataMergeStrategy> + ): Map>> { + val initialDataValue : Map = Collections.emptyMap() + val edgesMap = LinkedHashMap>>() + 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.emptyList(), changed, false); + changed[0] = false + collectDataFromSubgraph( + pseudocode, traversalOrder, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS, edgesMap, + instructionDataMergeStrategy, Collections.emptyList(), changed, false) } - return edgesMap; + return edgesMap } - private static void initializeEdgesMap( - @NotNull Pseudocode pseudocode, - @NotNull Map> edgesMap, - @NotNull M initialDataValue + private fun initializeEdgesMap( + pseudocode: Pseudocode, + edgesMap: MutableMap>, + initialDataValue: M ) { - List instructions = pseudocode.getInstructions(); - Edges 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 void collectDataFromSubgraph( - @NotNull Pseudocode pseudocode, - @NotNull TraversalOrder traversalOrder, - @NotNull LookInsideStrategy lookInside, - @NotNull Map>> edgesMap, - @NotNull InstructionDataMergeStrategy> instructionDataMergeStrategy, - @NotNull Collection previousSubGraphInstructions, - boolean[] changed, - boolean isLocal + private fun collectDataFromSubgraph( + pseudocode: Pseudocode, + traversalOrder: TraversalOrder, + lookInside: LookInsideStrategy, + edgesMap: MutableMap>>, + instructionDataMergeStrategy: InstructionDataMergeStrategy>, + previousSubGraphInstructions: Collection, + changed: BooleanArray, + isLocal: Boolean ) { - List 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 allPreviousInstructions; - Collection previousInstructions = getPreviousInstruction(instruction, traversalOrder); + val allPreviousInstructions: MutableCollection + 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> previousValue = edgesMap.get(instruction); - Edges> 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> previousDataValue = edgesMap.get(instruction); + val previousDataValue = edgesMap.get(instruction) - Collection> incomingEdgesData = Sets.newHashSet(); + val incomingEdgesData = HashSet>() - for (Instruction previousInstruction : allPreviousInstructions) { - Edges> 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> 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) } } } 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 9931c530c7f..5a2391edc10 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/PseudocodeVariablesData.java @@ -135,9 +135,10 @@ public class PseudocodeVariablesData { final Set declaredVariables = getDeclaredVariables(pseudocode, true); - return new PseudocodeVariableDataCollector(bindingContext).collectData( + return new PseudocodeVariableDataCollector(bindingContext).collectDataJ( pseudocode, FORWARD, new InstructionDataMergeStrategy>() { + @NotNull @Override public Edges> 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>> getVariableUseStatusData() { - return new PseudocodeVariableDataCollector(bindingContext).collectData( + return new PseudocodeVariableDataCollector(bindingContext).collectDataJ( pseudocode, BACKWARD, new InstructionDataMergeStrategy>() { + @NotNull @Override public Edges> execute( @NotNull Instruction instruction,