Skip to content
This repository was archived by the owner on Oct 24, 2025. It is now read-only.

Commit 6b647ea

Browse files
Merge pull request #43 from JetBrains-Research/php-small-fixes
Php small fixes
2 parents bee0af8 + fea1827 commit 6b647ea

File tree

6 files changed

+79
-17
lines changed

6 files changed

+79
-17
lines changed

build.gradle.kts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,24 @@ allprojects {
2424
repositories {
2525
mavenCentral()
2626
maven(url = "https://packages.jetbrains.team/maven/p/astminer/astminer")
27+
maven("https://packages.jetbrains.team/maven/p/big-code/bigcode")
2728
}
2829

2930
dependencies {
3031
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.7.21")
3132
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1")
3233
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
3334
implementation("it.unimi.dsi:fastutil:8.5.9")
35+
implementation("org.jetbrains.research:plugin-utilities-core:1.0") {
36+
exclude("org.slf4j", "slf4j-simple")
37+
exclude("org.slf4j", "slf4j-api")
38+
exclude("org.slf4j", "slf4j")
39+
}
3440

3541
testImplementation(platform("org.junit:junit-bom:5.9.0"))
3642
testImplementation("org.junit.jupiter:junit-jupiter:5.9.0")
3743

3844
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.18.1")
39-
40-
implementation("${getProperty("utilitiesProjectName")}:plugin-utilities-core") {
41-
version {
42-
branch = getProperty("utilitiesBranch")
43-
}
44-
exclude("org.slf4j", "slf4j-simple")
45-
exclude("org.slf4j", "slf4j-api")
46-
exclude("org.slf4j", "slf4j")
47-
}
4845
}
4946

5047
configurations.all {

psiminer-cli/build.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ tasks {
1515
args = listOfNotNull("psiminer", dataset, output, config)
1616
jvmArgs = listOf(
1717
"-Djava.awt.headless=true", "-Djdk.module.illegalAccess.silent=true",
18-
"--add-exports", "java.base/jdk.internal.vm=ALL-UNNAMED", "-Xmx32G"
18+
"--add-exports", "java.base/jdk.internal.vm=ALL-UNNAMED", "-Xmx32G",
19+
"-Didea.is.internal=false", "-Dlog4j.configurationFile=psiminer-cli/src/main/resources/log4j.properties"
1920
)
2021
maxHeapSize = "32g"
2122
}

psiminer-cli/src/main/resources/log4j.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Define the root logger with appender file
2-
log4j.rootLogger=WARN, FILE
2+
log4j.rootLogger=SEVERE, FILE
33

44
# Define the file appender
55
log4j.appender.FILE=org.apache.log4j.FileAppender

psiminer-core/src/main/kotlin/psi/graphs/edgeProviders/php/PhpControlFlowEdgeProvider.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package psi.graphs.edgeProviders.php
33
import com.intellij.psi.PsiElement
44
import com.intellij.psi.controlFlow.*
55
import com.jetbrains.php.codeInsight.controlFlow.PhpControlFlow
6-
import com.jetbrains.php.codeInsight.controlFlow.instructions.PhpExitPointInstruction
76
import com.jetbrains.php.codeInsight.controlFlow.instructions.PhpInstruction
87
import com.jetbrains.php.lang.psi.elements.ControlStatement
98
import com.jetbrains.php.lang.psi.elements.PhpReturn
@@ -77,7 +76,6 @@ class PhpControlFlowEdgeProvider : EdgeProvider(
7776

7877
private fun provideEdgesForInstruction(
7978
index: Int,
80-
instructions: List<PhpInstruction>,
8179
elements: List<PsiElement?>,
8280
successors: Array<out Set<Int>>,
8381
nextNonBranchingInstructions: Array<out Set<Int>>,
@@ -101,19 +99,19 @@ class PhpControlFlowEdgeProvider : EdgeProvider(
10199
newEdges.add(Edge(element, toElement, EdgeType.ControlElement))
102100
}
103101
}
104-
if (element is PhpReturn || isTerminalInstruction(index, instructions, successors)) {
102+
if (isTerminalInstruction(index, elements, successors)) {
105103
addReturnsToEdge(element, elements, newEdges)
106104
}
107105
return newEdges
108106
}
109107

110108
private fun isTerminalInstruction(
111109
index: Int,
112-
instructions: List<PhpInstruction>,
110+
elements: List<PsiElement?>,
113111
successors: Array<out Set<Int>>,
114112
): Boolean =
115113
successors[index].isEmpty() ||
116-
successors[index].map { instructions[it] }.any { it is PhpExitPointInstruction }
114+
successors[index].map { elements[it] }.all { it == null }
117115

118116
private fun addReturnsToEdge(
119117
element: PsiElement,
@@ -139,7 +137,7 @@ class PhpControlFlowEdgeProvider : EdgeProvider(
139137
val nextNonBranchingInstructions = computeNextNonBranchingInstructions(instructions, elements, successors)
140138
instructions.indices.forEach { index ->
141139
newEdges.addAll(
142-
provideEdgesForInstruction(index, instructions, elements, successors, nextNonBranchingInstructions)
140+
provideEdgesForInstruction(index, elements, successors, nextNonBranchingInstructions)
143141
)
144142
}
145143
}

psiminer-core/src/test/kotlin/psi/graphs/edgeProviders/php/PhpControlFlowEdgeProviderTest.kt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,34 @@ internal class PhpControlFlowEdgeProviderTest : PhpGraphTest("PhpFlowMethods") {
6464
}
6565
}
6666

67+
@ParameterizedTest
68+
@ValueSource(
69+
strings = [
70+
"straightWriteMethod",
71+
"multipleReturns",
72+
"forWithReturn"
73+
]
74+
)
75+
fun `test returns extraction from PHP methods`(methodName: String) {
76+
val psiRoot = getMethod(methodName)
77+
val graphMiner = PhpGraphMiner()
78+
ReadAction.run<Exception> {
79+
val codeGraph = graphMiner.mine(psiRoot)
80+
val controlFlowEdges =
81+
codeGraph.edges.withType(EdgeType.ReturnsTo).flatMap { (_, edges) -> edges.forward() }
82+
assertContainsElements(
83+
countIncomingEdges(controlFlowEdges).entries,
84+
correctNumberOfReturnsToEdges.incoming[methodName]?.entries
85+
?: throw CorrectValueNotProvidedException(methodName, "returnsTo")
86+
)
87+
assertContainsElements(
88+
countOutgoingEdges(controlFlowEdges).entries,
89+
correctNumberOfReturnsToEdges.outgoing[methodName]?.entries
90+
?: throw CorrectValueNotProvidedException(methodName, "returnsTo")
91+
)
92+
}
93+
}
94+
6795
companion object {
6896

6997
val correctNumberOfControlFlowEdges = CorrectNumberOfIncomingAndOutgoingEdges(
@@ -131,5 +159,33 @@ internal class PhpControlFlowEdgeProviderTest : PhpGraphTest("PhpFlowMethods") {
131159
)
132160
)
133161
)
162+
163+
val correctNumberOfReturnsToEdges = CorrectNumberOfIncomingAndOutgoingEdges(
164+
incoming = mapOf(
165+
"straightWriteMethod" to mapOf(
166+
Vertex("MethodImpl: straightWriteMethod", Pair(0, 20)) to 1
167+
),
168+
"multipleReturns" to mapOf(
169+
Vertex("MethodImpl: multipleReturns", Pair(0, 20)) to 3
170+
),
171+
"forWithReturn" to mapOf(
172+
Vertex("MethodImpl: forWithReturn", Pair(0, 20)) to 2
173+
)
174+
),
175+
outgoing = mapOf(
176+
"straightWriteMethod" to mapOf(
177+
Vertex("VariableImpl: c", Pair(4, 8)) to 1
178+
),
179+
"multipleReturns" to mapOf(
180+
Vertex("PhpExpressionImpl: 0", Pair(4, 19)) to 1,
181+
Vertex("PhpExpressionImpl: 1", Pair(8, 23)) to 1,
182+
Vertex("PhpExpressionImpl: 2", Pair(11, 15)) to 1
183+
),
184+
"forWithReturn" to mapOf(
185+
Vertex("Return", Pair(4, 16)) to 1,
186+
Vertex("VariableImpl: e", Pair(7, 8)) to 1,
187+
)
188+
)
189+
)
134190
}
135191
}

psiminer-core/src/test/resources/data/php/PhpFlowMethods.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,14 @@ public function multipleReturns(): int
8282
}
8383
return 2;
8484
}
85+
86+
public function forWithReturn()
87+
{
88+
for ($i = 0; $i < 2; $i++) {
89+
if ($i == 1) {
90+
return;
91+
}
92+
}
93+
$e = 5;
94+
}
8595
}

0 commit comments

Comments
 (0)