diff --git a/.idea/libraries/javaslang.xml b/.idea/libraries/javaslang.xml new file mode 100644 index 00000000000..eb6d0490a08 --- /dev/null +++ b/.idea/libraries/javaslang.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/build.xml b/build.xml index 1da29f3410d..70847c6f596 100644 --- a/build.xml +++ b/build.xml @@ -60,6 +60,7 @@ + @@ -369,6 +370,7 @@ + @@ -728,7 +730,7 @@ - + diff --git a/compiler/compiler.pro b/compiler/compiler.pro index e6a0d6f6c5b..bd2616b7692 100644 --- a/compiler/compiler.pro +++ b/compiler/compiler.pro @@ -49,6 +49,8 @@ messages/**) -dontwarn org.apache.xerces.dom.** -dontwarn org.apache.xerces.util.** -dontwarn org.w3c.dom.ElementTraversal +-dontwarn javaslang.match.annotation.Unapply +-dontwarn javaslang.match.annotation.Patterns -libraryjars '' -libraryjars '' diff --git a/compiler/frontend/frontend.iml b/compiler/frontend/frontend.iml index 9adafdf03de..80953adda4f 100644 --- a/compiler/frontend/frontend.iml +++ b/compiler/frontend/frontend.iml @@ -17,5 +17,6 @@ + \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ConstructorConsistencyChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ConstructorConsistencyChecker.kt index 16fbf6efcdc..000e76c1ac4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ConstructorConsistencyChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ConstructorConsistencyChecker.kt @@ -26,8 +26,8 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.ReadValueInstructio import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder import org.jetbrains.kotlin.cfg.pseudocodeTraverser.traverse import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace @@ -117,7 +117,7 @@ class ConstructorConsistencyChecker private constructor( fun firstUninitializedNotNullProperty() = propertyDescriptors.firstOrNull { !it.type.isMarkedNullable && !KotlinBuiltIns.isPrimitiveType(it.type) && - !it.isLateInit && !(enterData[it]?.definitelyInitialized() ?: false) + !it.isLateInit && !(enterData.getOrNull(it)?.definitelyInitialized() ?: false) } fun handleLeakingThis(expression: KtExpression) { @@ -197,4 +197,4 @@ class ConstructorConsistencyChecker private constructor( else -> expression } } -} \ No newline at end of file +} diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInfo.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInfo.kt index 8c1527fd8a0..f7733349714 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInfo.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInfo.kt @@ -16,36 +16,56 @@ package org.jetbrains.kotlin.cfg +import javaslang.Tuple2 import org.jetbrains.kotlin.descriptors.VariableDescriptor -import java.util.* -open class ControlFlowInfo internal constructor(protected val map: MutableMap = hashMapOf()) : - MutableMap by map { - open fun copy() = ControlFlowInfo(HashMap(map)) +typealias ImmutableMap = javaslang.collection.Map +typealias ImmutableHashMap = javaslang.collection.HashMap - fun retainAll(predicate: (VariableDescriptor) -> Boolean): ControlFlowInfo { - map.keys.retainAll(predicate) - return this +abstract class ControlFlowInfo, D> +internal constructor( + protected val map: ImmutableMap = ImmutableHashMap.empty() +) : ImmutableMap by map { + abstract protected fun copy(newMap: ImmutableMap): S + + override fun put(key: VariableDescriptor, value: D): S = put(key, value, this[key].getOrElse(null as D?)) + + /** + * This overload exists just for sake of optimizations: in some cases we've just retrieved the old value, + * so we don't need to scan through the peristent hashmap again + */ + fun put(key: VariableDescriptor, value: D, oldValue: D?): S { + @Suppress("UNCHECKED_CAST") + // Avoid a copy instance creation if new value is the same + if (value == oldValue) return this as S + return copy(map.put(key, value)) } - override fun equals(other: Any?) = map == (other as? ControlFlowInfo<*>)?.map + fun retainAll(predicate: (VariableDescriptor) -> Boolean): S = copy(map.removeAll(map.keySet().filterNot(predicate))) + + override fun equals(other: Any?) = map == (other as? ControlFlowInfo<*, *>)?.map override fun hashCode() = map.hashCode() override fun toString() = map.toString() } -class InitControlFlowInfo(map: MutableMap = hashMapOf()) : - ControlFlowInfo(map) { - override fun copy() = InitControlFlowInfo(HashMap(map)) +operator fun Tuple2.component1(): T = _1() +operator fun Tuple2<*, T>.component2(): T = _2() + +fun ImmutableMap.getOrNull(k: K): V? = this[k].getOrElse(null as V?) + +class InitControlFlowInfo(map: ImmutableMap = ImmutableHashMap.empty()) : + ControlFlowInfo(map) { + override fun copy(newMap: ImmutableMap) = InitControlFlowInfo(newMap) // this = output of EXHAUSTIVE_WHEN_ELSE instruction // merge = input of MergeInstruction // returns true if definite initialization in when happens here fun checkDefiniteInitializationInWhen(merge: InitControlFlowInfo): Boolean { - for ((key, value) in entries) { + for ((key, value) in iterator()) { if (value.initState == InitState.INITIALIZED_EXHAUSTIVELY && - merge[key]?.initState == InitState.INITIALIZED) { + merge.getOrNull(key)?.initState == InitState.INITIALIZED) { return true } } @@ -53,9 +73,9 @@ class InitControlFlowInfo(map: MutableMap = hashMapOf()) : - ControlFlowInfo(map) { - override fun copy() = UseControlFlowInfo(HashMap(map)) +class UseControlFlowInfo(map: ImmutableMap = ImmutableHashMap.empty()) : + ControlFlowInfo(map) { + override fun copy(newMap: ImmutableMap) = UseControlFlowInfo(newMap) } enum class InitState(private val s: String) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt index d6db2a8a59a..40cff191a29 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/ControlFlowInformationProvider.kt @@ -274,8 +274,8 @@ class ControlFlowInformationProvider private constructor( pseudocode.traverse(TraversalOrder.FORWARD, initializers) { instruction: Instruction, - enterData: Map, - exitData: Map -> + enterData: ImmutableMap, + exitData: ImmutableMap -> val ctxt = VariableInitContext(instruction, reportedDiagnosticMap, enterData, exitData, blockScopeVariableInfo) if (ctxt.variableDescriptor == null) return@traverse @@ -532,7 +532,7 @@ class ControlFlowInformationProvider private constructor( val declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode, false) for (variable in declaredVariables) { if (variable is PropertyDescriptor) { - if (initializers.incoming[variable]?.definitelyInitialized() ?: false) continue + if (initializers.incoming.getOrNull(variable)?.definitelyInitialized() ?: false) continue trace.record(BindingContext.IS_UNINITIALIZED, variable) } } @@ -548,8 +548,8 @@ class ControlFlowInformationProvider private constructor( val usedValueExpressions = hashSetOf() pseudocode.traverse(TraversalOrder.BACKWARD, variableStatusData) { instruction: Instruction, - enterData: Map, - _: Map -> + enterData: ImmutableMap, + _: ImmutableMap -> val ctxt = VariableUseContext(instruction, reportedDiagnosticMap) val declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.owner, false) @@ -560,7 +560,7 @@ class ControlFlowInformationProvider private constructor( || !ExpressionTypingUtils.isLocal(variableDescriptor.containingDeclaration, variableDescriptor)) { return@traverse } - val variableUseState = enterData[variableDescriptor] + val variableUseState = enterData.getOrNull(variableDescriptor) when (instruction) { is WriteValueInstruction -> { if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor) != null) return@traverse @@ -1017,8 +1017,8 @@ class ControlFlowInformationProvider private constructor( private inner class VariableInitContext( instruction: Instruction, map: MutableMap>, - `in`: Map, - out: Map, + `in`: ImmutableMap, + out: ImmutableMap, blockScopeVariableInfo: BlockScopeVariableInfo ) : VariableContext(instruction, map) { internal val enterInitState = initialize(variableDescriptor, blockScopeVariableInfo, `in`) @@ -1027,9 +1027,9 @@ class ControlFlowInformationProvider private constructor( private fun initialize( variableDescriptor: VariableDescriptor?, blockScopeVariableInfo: BlockScopeVariableInfo, - map: Map + map: ImmutableMap ): VariableControlFlowState? { - val state = map[variableDescriptor ?: return null] + val state = map.getOrNull(variableDescriptor ?: return null) if (state != null) return state return PseudocodeVariablesData.getDefaultValueForInitializers(variableDescriptor, instruction, blockScopeVariableInfo) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeTraverser.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeTraverser.kt index 7fbd205157f..69804c1b0c0 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeTraverser.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeTraverser.kt @@ -55,7 +55,7 @@ fun Pseudocode.traverse( } } -fun > Pseudocode.collectData( +fun > Pseudocode.collectData( traversalOrder: TraversalOrder, mergeEdges: (Instruction, Collection) -> Edges, updateEdge: (Instruction, Instruction, I) -> I, @@ -75,7 +75,7 @@ fun > Pseudocode.collectData( return edgesMap } -private fun > Pseudocode.collectDataFromSubgraph( +private fun > Pseudocode.collectDataFromSubgraph( traversalOrder: TraversalOrder, edgesMap: MutableMap>, mergeEdges: (Instruction, Collection) -> Edges, @@ -138,7 +138,7 @@ private fun getPreviousIncludingSubGraphInstructions( return result } -private fun > updateEdgeDataForInstruction( +private fun > updateEdgeDataForInstruction( instruction: Instruction, previousValue: Edges?, newValue: Edges?, edgesMap: MutableMap>, changed: BooleanArray) { if (previousValue != newValue && newValue != null) { changed[0] = true diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariableDataCollector.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariableDataCollector.kt index f24319f0150..cf41eb9447f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariableDataCollector.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariableDataCollector.kt @@ -17,20 +17,17 @@ package org.jetbrains.kotlin.cfg import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode -import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope +import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction import org.jetbrains.kotlin.cfg.pseudocodeTraverser.Edges import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder import org.jetbrains.kotlin.cfg.pseudocodeTraverser.collectData import org.jetbrains.kotlin.cfg.pseudocodeTraverser.traverse -import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContextUtils -import org.jetbrains.kotlin.resolve.calls.tower.getFakeDescriptorForObject -import java.util.ArrayList -import java.util.HashMap +import java.util.* class PseudocodeVariableDataCollector( private val bindingContext: BindingContext, @@ -38,7 +35,7 @@ class PseudocodeVariableDataCollector( ) { val blockScopeVariableInfo = computeBlockScopeVariableInfo(pseudocode) - fun > collectData( + fun > collectData( traversalOrder: TraversalOrder, initialInfo: I, instructionDataMergeStrategy: (Instruction, Collection) -> Edges @@ -51,7 +48,7 @@ class PseudocodeVariableDataCollector( ) } - private fun > filterOutVariablesOutOfScope( + private fun > filterOutVariablesOutOfScope( from: Instruction, to: Instruction, info: I @@ -63,7 +60,7 @@ class PseudocodeVariableDataCollector( // Variables declared in an inner (deeper) scope can't be accessed from an outer scope. // Thus they can be filtered out upon leaving the inner scope. @Suppress("UNCHECKED_CAST") - return info.copy().retainAll { variable -> + return info.retainAll { variable -> val blockScope = blockScopeVariableInfo.declaredIn[variable] // '-1' for variables declared outside this pseudocode val depth = blockScope?.depth ?: -1 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt index 40ecd4f56f3..efb173ceed7 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/PseudocodeVariablesData.kt @@ -20,7 +20,10 @@ import com.google.common.collect.Maps import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeUtil import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction -import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.* +import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicInstruction +import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.MagicKind +import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.ReadValueInstruction +import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.WriteValueInstruction import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction import org.jetbrains.kotlin.cfg.pseudocodeTraverser.Edges import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder @@ -28,7 +31,7 @@ import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.psi.KtProperty import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContextUtils.variableDescriptorForDeclaration -import java.util.Collections +import java.util.* class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingContext: BindingContext) { private val pseudocodeVariableDataCollector: PseudocodeVariableDataCollector @@ -105,39 +108,39 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon blockScopeVariableInfo: BlockScopeVariableInfo): InitControlFlowInfo { if (instruction is MagicInstruction) { if (instruction.kind === MagicKind.EXHAUSTIVE_WHEN_ELSE) { - val exitInstructionData = enterInstructionData.copy() - for ((key, value) in enterInstructionData) { + return enterInstructionData.iterator().fold(enterInstructionData) { + result, (key, value) -> if (!value.definitelyInitialized()) { - exitInstructionData.put(key, VariableControlFlowState.createInitializedExhaustively(value.isDeclared)) + result.put(key, VariableControlFlowState.createInitializedExhaustively(value.isDeclared)) } + else result } - return exitInstructionData } } if (instruction !is WriteValueInstruction && instruction !is VariableDeclarationInstruction) { return enterInstructionData } val variable = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, bindingContext) ?: return enterInstructionData - val exitInstructionData = enterInstructionData.copy() + var exitInstructionData = enterInstructionData if (instruction is WriteValueInstruction) { // if writing to already initialized object if (!PseudocodeUtil.isThisOrNoDispatchReceiver(instruction, bindingContext)) { return enterInstructionData } - val enterInitState = enterInstructionData[variable] + val enterInitState = enterInstructionData.getOrNull(variable) val initializationAtThisElement = VariableControlFlowState.create(instruction.element is KtProperty, enterInitState) - exitInstructionData.put(variable, initializationAtThisElement) + exitInstructionData = exitInstructionData.put(variable, initializationAtThisElement, enterInitState) } else { // instruction instanceof VariableDeclarationInstruction - var enterInitState: VariableControlFlowState? = enterInstructionData[variable] + var enterInitState: VariableControlFlowState? = enterInstructionData.getOrNull(variable) if (enterInitState == null) { enterInitState = getDefaultValueForInitializers(variable, instruction, blockScopeVariableInfo) } if (!enterInitState.mayBeInitialized() || !enterInitState.isDeclared) { val variableDeclarationInfo = VariableControlFlowState.create(enterInitState.initState, isDeclared = true) - exitInstructionData.put(variable, variableDeclarationInfo) + exitInstructionData = exitInstructionData.put(variable, variableDeclarationInfo, enterInitState) } } return exitInstructionData @@ -154,34 +157,35 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon enterResult = incomingEdgesData.single() } else { - enterResult = UseControlFlowInfo() - for (edgeData in incomingEdgesData) { - for ((variableDescriptor, variableUseState) in edgeData) { - enterResult.put(variableDescriptor, variableUseState.merge(enterResult[variableDescriptor])) + enterResult = incomingEdgesData.fold(UseControlFlowInfo()) { result, edgeData -> + edgeData.iterator().fold(result) { + subResult, (variableDescriptor, variableUseState) -> + subResult.put(variableDescriptor, variableUseState.merge(subResult.getOrNull(variableDescriptor))) } } } + val variableDescriptor = PseudocodeUtil.extractVariableDescriptorFromReference(instruction, bindingContext) if (variableDescriptor == null || instruction !is ReadValueInstruction && instruction !is WriteValueInstruction) { Edges(enterResult, enterResult) } else { - val exitResult = enterResult.copy() - if (instruction is ReadValueInstruction) { - exitResult.put(variableDescriptor, VariableUseState.READ) - } - else { - var variableUseState: VariableUseState? = enterResult[variableDescriptor] - if (variableUseState == null) { - variableUseState = VariableUseState.UNUSED + val exitResult = + if (instruction is ReadValueInstruction) { + enterResult.put(variableDescriptor, VariableUseState.READ) } - when (variableUseState) { - VariableUseState.UNUSED, VariableUseState.ONLY_WRITTEN_NEVER_READ -> - exitResult.put(variableDescriptor, VariableUseState.ONLY_WRITTEN_NEVER_READ) - VariableUseState.WRITTEN_AFTER_READ, VariableUseState.READ -> - exitResult.put(variableDescriptor, VariableUseState.WRITTEN_AFTER_READ) + else { + var variableUseState: VariableUseState? = enterResult.getOrNull(variableDescriptor) + if (variableUseState == null) { + variableUseState = VariableUseState.UNUSED + } + when (variableUseState) { + VariableUseState.UNUSED, VariableUseState.ONLY_WRITTEN_NEVER_READ -> + enterResult.put(variableDescriptor, VariableUseState.ONLY_WRITTEN_NEVER_READ) + VariableUseState.WRITTEN_AFTER_READ, VariableUseState.READ -> + enterResult.put(variableDescriptor, VariableUseState.WRITTEN_AFTER_READ) + } } - } Edges(enterResult, exitResult) } } @@ -202,23 +206,25 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon return VariableControlFlowState.create(isInitialized = declaredOutsideThisDeclaration) } + private val EMPTY_INIT_CONTROL_FLOW_INFO = InitControlFlowInfo() + private fun mergeIncomingEdgesDataForInitializers( instruction: Instruction, incomingEdgesData: Collection, blockScopeVariableInfo: BlockScopeVariableInfo ): InitControlFlowInfo { if (incomingEdgesData.size == 1) return incomingEdgesData.single() + if (incomingEdgesData.isEmpty()) return EMPTY_INIT_CONTROL_FLOW_INFO val variablesInScope = linkedSetOf() for (edgeData in incomingEdgesData) { - variablesInScope.addAll(edgeData.keys) + variablesInScope.addAll(edgeData.keySet()) } - val enterInstructionData = InitControlFlowInfo() - for (variable in variablesInScope) { + return variablesInScope.fold(EMPTY_INIT_CONTROL_FLOW_INFO) { result, variable -> var initState: InitState? = null var isDeclared = true for (edgeData in incomingEdgesData) { - val varControlFlowState = edgeData[variable] + val varControlFlowState = edgeData.getOrNull(variable) ?: getDefaultValueForInitializers(variable, instruction, blockScopeVariableInfo) initState = initState?.merge(varControlFlowState.initState) ?: varControlFlowState.initState if (!varControlFlowState.isDeclared) { @@ -228,9 +234,8 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon if (initState == null) { throw AssertionError("An empty set of incoming edges data") } - enterInstructionData.put(variable, VariableControlFlowState.create(initState, isDeclared)) + result.put(variable, VariableControlFlowState.create(initState, isDeclared)) } - return enterInstructionData } } } diff --git a/compiler/tests/compiler-tests.iml b/compiler/tests/compiler-tests.iml index 2c24c8fea38..503171ef57c 100644 --- a/compiler/tests/compiler-tests.iml +++ b/compiler/tests/compiler-tests.iml @@ -35,5 +35,6 @@ + \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/cfg/AbstractDataFlowTest.java b/compiler/tests/org/jetbrains/kotlin/cfg/AbstractDataFlowTest.java index ab23a3a17db..949087bd872 100644 --- a/compiler/tests/org/jetbrains/kotlin/cfg/AbstractDataFlowTest.java +++ b/compiler/tests/org/jetbrains/kotlin/cfg/AbstractDataFlowTest.java @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.cfg; import com.google.common.collect.Lists; import com.intellij.openapi.util.text.StringUtil; +import javaslang.Tuple2; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.cfg.pseudocode.PseudocodeImpl; import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction; @@ -79,21 +80,22 @@ public abstract class AbstractDataFlowTest extends AbstractPseudocodeTest { maxWidth = length; } } + return maxWidth; } @NotNull - private static > String dumpEdgesData(String prefix, @NotNull Edges edges) { + private static > String dumpEdgesData(String prefix, @NotNull Edges edges) { return prefix + " in: " + renderVariableMap(edges.getIncoming()) + " out: " + renderVariableMap(edges.getOutgoing()); } - private static String renderVariableMap(Map map) { + private static String renderVariableMap(javaslang.collection.Map map) { List result = Lists.newArrayList(); - for (Map.Entry entry : map.entrySet()) { - VariableDescriptor variable = entry.getKey(); - S state = entry.getValue(); + for (Tuple2 entry : map) { + VariableDescriptor variable = entry._1; + S state = entry._2; result.add(variable.getName() + "=" + state); } Collections.sort(result); diff --git a/ultimate/.idea/libraries/javaslang.xml b/ultimate/.idea/libraries/javaslang.xml new file mode 100644 index 00000000000..74f4c4a4fb0 --- /dev/null +++ b/ultimate/.idea/libraries/javaslang.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/ultimate/kotlin-ultimate.iml b/ultimate/kotlin-ultimate.iml index a29252602e4..df95c2b7b76 100644 --- a/ultimate/kotlin-ultimate.iml +++ b/ultimate/kotlin-ultimate.iml @@ -30,5 +30,6 @@ + \ No newline at end of file diff --git a/update_dependencies.xml b/update_dependencies.xml index ee3a056dc95..6ea08dd976c 100644 --- a/update_dependencies.xml +++ b/update_dependencies.xml @@ -236,6 +236,9 @@ + + +