Skip to content

Commit d38d43e

Browse files
committed
feat: add Testo coverage engine and program runner integration
1 parent 9623f74 commit d38d43e

5 files changed

Lines changed: 137 additions & 1 deletion

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ platformPlugins=com.jetbrains.php:243.25659.59,com.jetbrains.hackathon.indices.v
1919
# Example: platformBundledPlugins = com.intellij.java
2020
platformBundledPlugins =
2121
# Example: platformBundledModules = intellij.spellchecker
22-
platformBundledModules =
22+
platformBundledModules = intellij.platform.coverage
2323

2424
# Gradle Releases -> https://github.com/gradle/gradle/releases
2525
gradleVersion = 9.3.0
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.github.xepozz.testo.coverage
2+
3+
import com.github.xepozz.testo.tests.run.TestoRunConfiguration
4+
import com.intellij.coverage.CoverageFileProvider
5+
import com.intellij.coverage.CoverageRunner
6+
import com.intellij.coverage.CoverageSuite
7+
import com.intellij.execution.configurations.RunConfigurationBase
8+
import com.intellij.execution.configurations.coverage.CoverageEnabledConfiguration
9+
import com.jetbrains.php.phpunit.coverage.PhpCoverageSuite
10+
import com.jetbrains.php.phpunit.coverage.PhpUnitCoverageEngine
11+
import com.jetbrains.php.phpunit.coverage.PhpUnitCoverageRunner
12+
13+
14+
class TestoCoverageEnabledConfiguration(
15+
configuration: TestoRunConfiguration
16+
) : CoverageEnabledConfiguration(configuration, CoverageRunner.getInstance(PhpUnitCoverageRunner::class.java)) {
17+
override fun coverageFileNameSeparator(): String = "@"
18+
19+
// Testo writes the Clover report to a path hardcoded inside the project's `testo.php`
20+
// (see `new CloverReport(__DIR__ . '/runtime/clover.xml')`). Until Testo exposes a
21+
// `--coverage-clover=<path>` CLI flag, we mirror that convention so the IDE reads
22+
// coverage from the same place Testo writes it.
23+
override fun getCoverageFilePath(): String =
24+
configuration.project.basePath?.let { "$it/runtime/clover.xml" } ?: super.getCoverageFilePath()!!
25+
}
26+
27+
class TestoCoverageEngine : PhpUnitCoverageEngine() {
28+
override fun isApplicableTo(conf: RunConfigurationBase<*>) = conf is TestoRunConfiguration
29+
30+
override fun createCoverageEnabledConfiguration(conf: RunConfigurationBase<*>) =
31+
TestoCoverageEnabledConfiguration(conf as TestoRunConfiguration)
32+
33+
override fun createCoverageSuite(
34+
covRunner: CoverageRunner,
35+
name: String,
36+
coverageDataFileProvider: CoverageFileProvider,
37+
config: CoverageEnabledConfiguration
38+
): CoverageSuite? {
39+
if (config is TestoCoverageEnabledConfiguration) {
40+
return PhpCoverageSuite(
41+
name,
42+
config.configuration.project,
43+
covRunner,
44+
coverageDataFileProvider,
45+
config.createTimestamp()
46+
)
47+
}
48+
49+
return null
50+
}
51+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.github.xepozz.testo.coverage
2+
3+
import com.github.xepozz.testo.tests.run.TestoRunConfiguration
4+
import com.intellij.execution.configurations.RunProfile
5+
import com.intellij.execution.configurations.RunProfileState
6+
import com.intellij.execution.runners.ExecutionEnvironment
7+
import com.jetbrains.php.config.commandLine.PhpCommandSettings
8+
import com.jetbrains.php.config.interpreters.PhpInterpreter
9+
import com.jetbrains.php.debug.xdebug.options.XdebugConfigurationOptionsManager
10+
import com.jetbrains.php.phpunit.coverage.PhpCoverageRunner
11+
import com.jetbrains.php.phpunit.coverage.PhpUnitCoverageEngine.CoverageEngine
12+
import com.jetbrains.php.run.PhpConfigurationOption
13+
import com.jetbrains.php.run.PhpRunConfigurationHolder
14+
15+
open class TestoCoverageProgramRunner : PhpCoverageRunner() {
16+
companion object {
17+
const val EXECUTOR_ID: String = "Coverage"
18+
const val RUNNER_ID: String = "TestoCoverageRunner"
19+
}
20+
21+
override fun canRun(executorId: String, profile: RunProfile) =
22+
executorId == EXECUTOR_ID && profile is TestoRunConfiguration
23+
24+
override fun createCoverageArguments(targetCoverage: String?) = mutableListOf("--coverage")
25+
26+
override fun getRunnerId(): String = RUNNER_ID
27+
28+
override fun createState(
29+
env: ExecutionEnvironment,
30+
interpreter: PhpInterpreter,
31+
runConfigurationHolder: PhpRunConfigurationHolder<*>,
32+
coverageArguments: MutableList<String>,
33+
localCoverage: String,
34+
targetCoverage: String
35+
): RunProfileState? {
36+
val runConfiguration = runConfigurationHolder.runConfiguration as TestoRunConfiguration
37+
38+
val command = createTestoCoverageCommand(
39+
runConfiguration,
40+
interpreter,
41+
coverageArguments,
42+
localCoverage,
43+
targetCoverage,
44+
)
45+
46+
runConfiguration.checkConfiguration()
47+
return runConfiguration.getState(env, command, null)
48+
}
49+
50+
fun createTestoCoverageCommand(
51+
runConfiguration: TestoRunConfiguration,
52+
interpreter: PhpInterpreter,
53+
coverageArguments: List<String>,
54+
localCoverage: String,
55+
targetCoverage: String
56+
): PhpCommandSettings {
57+
val command = runConfiguration.createCommand(
58+
interpreter,
59+
mutableMapOf<String, String>(),
60+
coverageArguments.toMutableList(),
61+
true,
62+
)
63+
64+
val options = when (runConfiguration.testoSettings.getTestoRunnerSettings().coverageEngine) {
65+
CoverageEngine.XDEBUG -> XdebugConfigurationOptionsManager
66+
.getConfigurationOptionsProvider(runConfiguration.project, interpreter)
67+
.enableCoverage()
68+
.createXdebugConfigurations()
69+
70+
CoverageEngine.PCOV -> listOf(PhpConfigurationOption("pcov.enabled", 1))
71+
else -> throw IllegalArgumentException("Unsupported coverage engine.")
72+
}
73+
command.addConfigurationOptions(options)
74+
setAdditionalMapping(localCoverage, targetCoverage, command)
75+
76+
return command
77+
}
78+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<idea-plugin>
2+
<extensions defaultExtensionNs="com.intellij">
3+
<coverageEngine implementation="com.github.xepozz.testo.coverage.TestoCoverageEngine"/>
4+
<programRunner implementation="com.github.xepozz.testo.coverage.TestoCoverageProgramRunner"/>
5+
</extensions>
6+
</idea-plugin>

src/main/resources/META-INF/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
<depends>com.intellij.modules.platform</depends>
88
<depends>com.jetbrains.php</depends>
9+
<depends optional="true" config-file="coverage.xml">com.intellij.modules.coverage</depends>
910

1011
<resource-bundle>messages.TestoBundle</resource-bundle>
1112

0 commit comments

Comments
 (0)