Skip to content

Commit bab5aa7

Browse files
committed
Merge branch 'main' into coverage
2 parents d38d43e + 5447b00 commit bab5aa7

4 files changed

Lines changed: 48 additions & 5 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pluginGroup = com.github.xepozz.testo
44
pluginName = Testo
55
pluginRepositoryUrl = https://github.com/j-plugins/testo-plugin
66
# SemVer format -> https://semver.org
7-
pluginVersion = 2026.2.0
7+
pluginVersion = 2026.2.1
88

99
# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
1010
pluginSinceBuild = 243

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ opentest4j = "1.3.0"
77
changelog = "2.5.0"
88
intelliJPlatform = "2.16.0"
99
kotlin = "2.3.20"
10-
kover = "0.9.4"
10+
kover = "0.9.8"
1111
qodana = "2025.3.2"
1212

1313
[libraries]

src/main/kotlin/com/github/xepozz/testo/mixin.kt

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.github.xepozz.testo
22

33
import com.github.xepozz.testo.tests.TestoTestDescriptor
4+
import com.intellij.openapi.diagnostic.Logger
5+
import com.intellij.openapi.progress.ProcessCanceledException
6+
import com.intellij.openapi.roots.ProjectFileIndex
47
import com.intellij.psi.PsiElement
58
import com.intellij.psi.PsiFile
69
import com.intellij.psi.util.PsiTreeUtil
@@ -12,6 +15,8 @@ import com.jetbrains.php.lang.psi.elements.ClassReference
1215
import com.jetbrains.php.lang.psi.elements.NewExpression
1316
import com.jetbrains.php.lang.psi.elements.PhpClass
1417

18+
private val LOG = Logger.getInstance("#com.github.xepozz.testo.mixin")
19+
1520
fun PsiElement.isTestoExecutable() = isTestoFunction() || isTestoMethod() || isTestoBench()
1621

1722
fun PsiElement.isTestoBench() = when(this) {
@@ -54,9 +59,28 @@ fun PsiElement.isTestoClass() = when (this) {
5459
else -> false
5560
}
5661

57-
fun PsiFile.isTestoFile() = when (this) {
58-
is PhpFile -> TestoTestDescriptor.isTestClassName(name.substringBeforeLast(".")) || isTestoClassFile() || isTestoFunctionFile() || isTestBenchFile() || isTestoConfigFile()
59-
else -> false
62+
fun PsiFile.isTestoFile(): Boolean {
63+
if (this !is PhpFile) return false
64+
val vFile = virtualFile ?: return false
65+
if (!vFile.isValid) return false
66+
67+
val fileIndex = ProjectFileIndex.getInstance(project)
68+
if (!fileIndex.isInContent(vFile)) return false
69+
if (fileIndex.isExcluded(vFile)) return false
70+
if (fileIndex.isUnderIgnored(vFile)) return false
71+
72+
return try {
73+
TestoTestDescriptor.isTestClassName(name.substringBeforeLast("."))
74+
|| isTestoClassFile()
75+
|| isTestoFunctionFile()
76+
|| isTestBenchFile()
77+
|| isTestoConfigFile()
78+
} catch (e: ProcessCanceledException) {
79+
throw e
80+
} catch (e: Throwable) {
81+
LOG.warn("Failed to determine whether ${vFile.path} is a Testo file", e)
82+
false
83+
}
6084
}
6185

6286
fun PhpFile.isTestoConfigFile() = PsiTreeUtil.findChildrenOfType(this, ClassReference::class.java)

src/test/kotlin/com/github/xepozz/testo/MixinPsiTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.github.xepozz.testo
22

3+
import com.intellij.openapi.application.WriteAction
34
import com.intellij.psi.util.PsiTreeUtil
45
import com.intellij.testFramework.TestDataPath
56
import com.intellij.testFramework.fixtures.BasePlatformTestCase
@@ -155,6 +156,24 @@ class MixinPsiTest : BasePlatformTestCase() {
155156
assertTrue("File containing test class should be a Testo file", psiFile.isTestoFile())
156157
}
157158

159+
fun testIsTestoFile_invalidVirtualFile_returnsFalse() {
160+
val psiFile = myFixture.configureByText(
161+
"DeletedTest.php",
162+
"""<?php class DeletedTest { public function testSomething(): void {} }"""
163+
) as PhpFile
164+
165+
assertTrue("Precondition: file should initially be detected as a Testo file", psiFile.isTestoFile())
166+
167+
val vFile = psiFile.virtualFile!!
168+
WriteAction.runAndWait<Throwable> { vFile.delete(this) }
169+
170+
assertFalse("VirtualFile should be invalid after deletion", vFile.isValid)
171+
assertFalse(
172+
"isTestoFile must return false when the underlying VirtualFile is invalid",
173+
psiFile.isTestoFile()
174+
)
175+
}
176+
158177
// ---- isTestoExecutable ----
159178

160179
fun testIsTestoExecutable_testMethod() {

0 commit comments

Comments
 (0)