Skip to content

Commit 36a69fe

Browse files
committed
refactor: make ProceduralMultiPath from List<ProceduralPath>
1 parent 3588519 commit 36a69fe

File tree

13 files changed

+98
-69
lines changed

13 files changed

+98
-69
lines changed

insight/src/main/kotlin/spp/jetbrains/insight/InsightKeys.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import spp.protocol.insight.InsightValue
2525
*/
2626
object InsightKeys {
2727

28-
val PROCEDURAL_PATHS = SourceKey<List<ProceduralPath>>("PROCEDURAL_PATHS")
28+
val PROCEDURAL_MULTI_PATH = SourceKey<ProceduralMultiPath>("PROCEDURAL_MULTI_PATH")
2929

3030
val FUNCTION_DURATION = SourceKey<InsightValue<Long>>(InsightType.FUNCTION_DURATION.name)
3131
val FUNCTION_DURATION_PREDICTION = SourceKey<InsightValue<Long>>(InsightType.FUNCTION_DURATION_PREDICTION.name)

insight/src/main/kotlin/spp/jetbrains/insight/InsightPassProvider.kt

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import spp.jetbrains.artifact.model.ArtifactElement
2020
import spp.jetbrains.insight.pass.ArtifactPass
2121
import spp.jetbrains.insight.pass.IPass
2222
import spp.jetbrains.insight.pass.ProceduralPathPass
23-
import spp.jetbrains.insight.pass.ProceduralPathSetPass
23+
import spp.jetbrains.insight.pass.ProceduralMultiPathPass
2424
import spp.jetbrains.insight.pass.artifact.CallDurationPass
2525
import spp.jetbrains.insight.pass.artifact.LoadPsiPass
2626
import spp.jetbrains.insight.pass.artifact.RandomConditionalPass
@@ -29,12 +29,12 @@ import spp.jetbrains.insight.pass.path.PathDurationPass
2929
import spp.jetbrains.insight.pass.path.PathProbabilityPass
3030
import spp.jetbrains.insight.pass.path.PruneArtifactsPass
3131
import spp.jetbrains.insight.pass.path.RecursivePathPass
32-
import spp.jetbrains.insight.pass.pathset.SavePsiPathSetPass
33-
import spp.jetbrains.insight.pass.pathset.SimplifyPathSetPass
34-
import spp.jetbrains.insight.pass.pathset.StaticDfaPathSetPass
32+
import spp.jetbrains.insight.pass.multipath.SavePsiMultiPathPass
33+
import spp.jetbrains.insight.pass.multipath.SimplifyMultiPathPass
34+
import spp.jetbrains.insight.pass.multipath.StaticDfaMultiPathPass
3535

3636
/**
37-
* Used to process passes over [ProceduralPath] sets, [ProceduralPath]s, and [ArtifactElement]s.
37+
* Used to process passes over [ProceduralMultiPath]s, [ProceduralPath]s, and [ArtifactElement]s.
3838
*/
3939
class InsightPassProvider {
4040

@@ -52,29 +52,29 @@ class InsightPassProvider {
5252
PathDurationPass(),
5353
RecursivePathPass(),
5454

55-
//path set passes
56-
StaticDfaPathSetPass(),
57-
SimplifyPathSetPass(),
58-
SavePsiPathSetPass()
55+
//multi path passes
56+
StaticDfaMultiPathPass(),
57+
SimplifyMultiPathPass(),
58+
SavePsiMultiPathPass()
5959
)
6060

6161
val FULL = InsightPassProvider().apply {
6262
ALL_PASSES.forEach { registerPass(it) }
6363
}
6464
val FULL_NO_SIMPLIFY = InsightPassProvider().apply {
65-
ALL_PASSES.filter { it !is SimplifyPathSetPass }.forEach { registerPass(it) }
65+
ALL_PASSES.filter { it !is SimplifyMultiPathPass }.forEach { registerPass(it) }
6666
}
6767
}
6868

6969
private val artifactPasses = mutableListOf<ArtifactPass>()
7070
private val pathPasses = mutableListOf<ProceduralPathPass>()
71-
private val pathSetPasses = mutableListOf<ProceduralPathSetPass>()
71+
private val multiPathPasses = mutableListOf<ProceduralMultiPathPass>()
7272

7373
fun registerPass(pass: IPass) {
7474
when (pass) {
7575
is ArtifactPass -> artifactPasses.add(pass)
7676
is ProceduralPathPass -> pathPasses.add(pass)
77-
is ProceduralPathSetPass -> pathSetPasses.add(pass)
77+
is ProceduralMultiPathPass -> multiPathPasses.add(pass)
7878
else -> throw IllegalArgumentException("Unknown pass type: ${pass::class}")
7979
}
8080
}
@@ -88,15 +88,15 @@ class InsightPassProvider {
8888
pathPasses.forEach { it.analyze(path) }
8989
}
9090

91-
fun analyze(pathSet: List<ProceduralPath>): List<ProceduralPath> {
92-
val preProcessedPathSet = pathSetPasses.fold(pathSet) { acc, pass ->
91+
fun analyze(multiPath: ProceduralMultiPath): ProceduralMultiPath {
92+
val preProcessedMultiPath = multiPathPasses.fold(multiPath) { acc, pass ->
9393
pass.preProcess(acc)
9494
}
95-
preProcessedPathSet.map { analyze(it) }
96-
val analyzedPathSetSet = pathSetPasses.fold(preProcessedPathSet) { acc, pass ->
95+
preProcessedMultiPath.map { analyze(it) }
96+
val analyzedMultiPath = multiPathPasses.fold(preProcessedMultiPath) { acc, pass ->
9797
pass.analyze(acc)
9898
}
99-
return pathSetPasses.fold(analyzedPathSetSet) { acc, pass ->
99+
return multiPathPasses.fold(analyzedMultiPath) { acc, pass ->
100100
pass.postProcess(acc)
101101
}
102102
}

insight/src/main/kotlin/spp/jetbrains/insight/ProceduralAnalyzer.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class ProceduralAnalyzer {
3535
*
3636
* @param element the [ArtifactElement] to analyze
3737
*/
38-
fun analyze(element: ArtifactElement): List<ProceduralPath> {
38+
fun analyze(element: ArtifactElement): ProceduralMultiPath {
3939
val parent = mutableListOf<Any>()
4040
walkDown(element, parent)
4141

@@ -48,7 +48,7 @@ class ProceduralAnalyzer {
4848
paths.add(path)
4949
}
5050

51-
return passProvider.analyze(paths)
51+
return passProvider.analyze(ProceduralMultiPath(paths))
5252
}
5353

5454
/**
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Source++, the continuous feedback platform for developers.
3+
* Copyright (C) 2022-2023 CodeBrig, Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package spp.jetbrains.insight
18+
19+
/**
20+
* A collection of [ProceduralPath]s that are all possible paths through a function.
21+
*/
22+
data class ProceduralMultiPath(
23+
val paths: List<ProceduralPath>
24+
) : Iterable<ProceduralPath> {
25+
override fun iterator(): Iterator<ProceduralPath> = paths.iterator()
26+
val size = paths.size
27+
}

insight/src/main/kotlin/spp/jetbrains/insight/pass/ProceduralPathSetPass.kt renamed to insight/src/main/kotlin/spp/jetbrains/insight/pass/ProceduralMultiPathPass.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,13 @@
1616
*/
1717
package spp.jetbrains.insight.pass
1818

19-
import spp.jetbrains.insight.ProceduralPath
19+
import spp.jetbrains.insight.ProceduralMultiPath
2020

2121
/**
22-
* A pass that analyzes a set of [ProceduralPath]s and adds data to them.
22+
* A pass that analyzes a [ProceduralMultiPath].
2323
*/
24-
interface ProceduralPathSetPass : IPass {
25-
fun preProcess(paths: List<ProceduralPath>): List<ProceduralPath> = paths
26-
fun analyze(paths: List<ProceduralPath>): List<ProceduralPath> = paths
27-
fun postProcess(paths: List<ProceduralPath>): List<ProceduralPath> = paths
24+
interface ProceduralMultiPathPass : IPass {
25+
fun preProcess(multiPath: ProceduralMultiPath): ProceduralMultiPath = multiPath
26+
fun analyze(multiPath: ProceduralMultiPath): ProceduralMultiPath = multiPath
27+
fun postProcess(multiPath: ProceduralMultiPath): ProceduralMultiPath = multiPath
2828
}

insight/src/main/kotlin/spp/jetbrains/insight/pass/artifact/CallDurationPass.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ class CallDurationPass : ArtifactPass {
3636

3737
val resolvedFunction = element.getResolvedFunction()
3838
if (resolvedFunction != null) {
39-
val paths = element.getData(InsightKeys.PROCEDURAL_PATHS)
40-
if (paths != null) {
39+
val multiPath = element.getData(InsightKeys.PROCEDURAL_MULTI_PATH)
40+
if (multiPath != null) {
4141
//artifact has already been analyzed, use pre-determined duration (if available)
42-
val duration = paths.mapNotNull {
42+
val duration = multiPath.mapNotNull {
4343
it.getInsights().find { it.type == PATH_DURATION }?.value as Long?
4444
}.ifNotEmpty { sum() }
4545
if (duration != null) {

insight/src/main/kotlin/spp/jetbrains/insight/pass/artifact/LoadPsiPass.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ class LoadPsiPass : ArtifactPass {
3333

3434
val resolvedFunction = element.getResolvedFunction()
3535
if (resolvedFunction != null) {
36-
val paths = resolvedFunction.getUserData(InsightKeys.PROCEDURAL_PATHS.asPsiKey())
37-
if (paths != null) {
38-
element.data[InsightKeys.PROCEDURAL_PATHS] = paths
36+
val multiPath = resolvedFunction.getUserData(InsightKeys.PROCEDURAL_MULTI_PATH.asPsiKey())
37+
if (multiPath != null) {
38+
element.data[InsightKeys.PROCEDURAL_MULTI_PATH] = multiPath
3939
}
4040
}
4141
}

insight/src/main/kotlin/spp/jetbrains/insight/pass/pathset/SavePsiPathSetPass.kt renamed to insight/src/main/kotlin/spp/jetbrains/insight/pass/multipath/SavePsiMultiPathPass.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,20 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
package spp.jetbrains.insight.pass.pathset
17+
package spp.jetbrains.insight.pass.multipath
1818

1919
import spp.jetbrains.insight.InsightKeys
20+
import spp.jetbrains.insight.ProceduralMultiPath
2021
import spp.jetbrains.insight.ProceduralPath
21-
import spp.jetbrains.insight.pass.ProceduralPathSetPass
22+
import spp.jetbrains.insight.pass.ProceduralMultiPathPass
2223

2324
/**
2425
* Saves the [ProceduralPath] set to the root artifact PSI element for later use.
2526
*/
26-
class SavePsiPathSetPass : ProceduralPathSetPass {
27+
class SavePsiMultiPathPass : ProceduralMultiPathPass {
2728

28-
override fun postProcess(paths: List<ProceduralPath>): List<ProceduralPath> {
29-
paths.forEach { it.rootArtifact.putUserData(InsightKeys.PROCEDURAL_PATHS.asPsiKey(), paths) }
30-
return super.postProcess(paths)
29+
override fun postProcess(multiPath: ProceduralMultiPath): ProceduralMultiPath {
30+
multiPath.forEach { it.rootArtifact.putUserData(InsightKeys.PROCEDURAL_MULTI_PATH.asPsiKey(), multiPath) }
31+
return super.postProcess(multiPath)
3132
}
3233
}

insight/src/main/kotlin/spp/jetbrains/insight/pass/pathset/SimplifyPathSetPass.kt renamed to insight/src/main/kotlin/spp/jetbrains/insight/pass/multipath/SimplifyMultiPathPass.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,22 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
package spp.jetbrains.insight.pass.pathset
17+
package spp.jetbrains.insight.pass.multipath
1818

1919
import spp.jetbrains.artifact.model.IfArtifact
2020
import spp.jetbrains.insight.InsightKeys
21+
import spp.jetbrains.insight.ProceduralMultiPath
2122
import spp.jetbrains.insight.ProceduralPath
22-
import spp.jetbrains.insight.pass.ProceduralPathSetPass
23+
import spp.jetbrains.insight.pass.ProceduralMultiPathPass
2324

2425
/**
2526
* Removes paths caused by conditional branches that are never taken.
2627
*/
27-
class SimplifyPathSetPass : ProceduralPathSetPass {
28+
class SimplifyMultiPathPass : ProceduralMultiPathPass {
2829

29-
override fun postProcess(paths: List<ProceduralPath>): List<ProceduralPath> {
30+
override fun postProcess(multiPath: ProceduralMultiPath): ProceduralMultiPath {
3031
val simplifiedPaths = mutableListOf<ProceduralPath>()
31-
for (path in paths) {
32+
for (path in multiPath) {
3233
val possiblePath = path.artifacts.all {
3334
if (it is IfArtifact) {
3435
val probability = it.getData(InsightKeys.CONTROL_STRUCTURE_PROBABILITY)
@@ -43,6 +44,6 @@ class SimplifyPathSetPass : ProceduralPathSetPass {
4344
}
4445
}
4546

46-
return simplifiedPaths
47+
return ProceduralMultiPath(simplifiedPaths)
4748
}
4849
}

insight/src/main/kotlin/spp/jetbrains/insight/pass/pathset/StaticDfaPathSetPass.kt renamed to insight/src/main/kotlin/spp/jetbrains/insight/pass/multipath/StaticDfaMultiPathPass.kt

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
package spp.jetbrains.insight.pass.pathset
17+
package spp.jetbrains.insight.pass.multipath
1818

1919
import com.intellij.codeInspection.dataFlow.interpreter.RunnerResult
2020
import com.intellij.codeInspection.dataFlow.interpreter.StandardDataFlowInterpreter
@@ -33,38 +33,38 @@ import org.jetbrains.kotlin.idea.inspections.dfa.KotlinAnchor
3333
import spp.jetbrains.artifact.model.FunctionArtifact
3434
import spp.jetbrains.artifact.model.IfArtifact
3535
import spp.jetbrains.insight.InsightKeys
36-
import spp.jetbrains.insight.ProceduralPath
37-
import spp.jetbrains.insight.pass.ProceduralPathSetPass
36+
import spp.jetbrains.insight.ProceduralMultiPath
37+
import spp.jetbrains.insight.pass.ProceduralMultiPathPass
3838
import spp.protocol.insight.InsightType
3939
import spp.protocol.insight.InsightValue
4040

41-
class StaticDfaPathSetPass : ProceduralPathSetPass {
41+
class StaticDfaMultiPathPass : ProceduralMultiPathPass {
4242

43-
private val log = logger<StaticDfaPathSetPass>()
43+
private val log = logger<StaticDfaMultiPathPass>()
4444

45-
override fun preProcess(paths: List<ProceduralPath>): List<ProceduralPath> {
46-
val project = paths.first().rootArtifact.project
45+
override fun preProcess(multiPath: ProceduralMultiPath): ProceduralMultiPath {
46+
val project = multiPath.first().rootArtifact.project
4747
val factory = DfaValueFactory(project)
4848
val flow = DataFlowIRProvider.forElement(
49-
(paths.first().rootArtifact as FunctionArtifact).bodyBlock!!.psiElement,
49+
(multiPath.first().rootArtifact as FunctionArtifact).bodyBlock!!.psiElement,
5050
factory
51-
) ?: return paths
51+
) ?: return multiPath
5252

5353
val listener = ConstantConditionDfaListener()
5454
val interpreter = StandardDataFlowInterpreter(flow, listener)
5555
val states = listOf(DfaMemoryStateImpl(factory))
5656
if (interpreter.interpret(states.map { s ->
5757
DfaInstructionState(flow.getInstruction(0), s)
5858
}) != RunnerResult.OK) {
59-
log.warn("Failed to interpret function ${(paths.first().rootArtifact as FunctionArtifact).name}")
59+
log.warn("Failed to interpret function ${(multiPath.first().rootArtifact as FunctionArtifact).name}")
6060
}
6161

6262
listener.constantConditions.forEach {
6363
if (it.key is KotlinAnchor.KotlinExpressionAnchor && it.value != ConstantValue.UNKNOWN) {
6464
val anchor = it.key as KotlinAnchor.KotlinExpressionAnchor
6565
val value = it.value
6666
val expression = anchor.expression
67-
paths.forEach {
67+
multiPath.forEach {
6868
it.artifacts.forEach {
6969
if (it is IfArtifact) {
7070
if (it.condition?.psiElement == expression) {
@@ -85,7 +85,7 @@ class StaticDfaPathSetPass : ProceduralPathSetPass {
8585
val anchor = it.key as JavaExpressionAnchor
8686
val value = it.value
8787
val expression = anchor.expression
88-
paths.forEach {
88+
multiPath.forEach {
8989
it.artifacts.forEach {
9090
if (it is IfArtifact) {
9191
if (it.condition?.psiElement == expression) {
@@ -105,7 +105,7 @@ class StaticDfaPathSetPass : ProceduralPathSetPass {
105105
}
106106
}
107107

108-
return paths
108+
return multiPath
109109
}
110110

111111
enum class ConstantValue {

0 commit comments

Comments
 (0)