Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 27 additions & 3 deletions src/main/kotlin/com/github/xepozz/testo/mixin.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.github.xepozz.testo

import com.github.xepozz.testo.tests.TestoTestDescriptor
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.roots.ProjectFileIndex
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiTreeUtil
Expand All @@ -12,6 +15,8 @@ import com.jetbrains.php.lang.psi.elements.ClassReference
import com.jetbrains.php.lang.psi.elements.NewExpression
import com.jetbrains.php.lang.psi.elements.PhpClass

private val LOG = Logger.getInstance("#com.github.xepozz.testo.mixin")

fun PsiElement.isTestoExecutable() = isTestoFunction() || isTestoMethod() || isTestoBench()

fun PsiElement.isTestoBench() = when(this) {
Expand Down Expand Up @@ -54,9 +59,28 @@ fun PsiElement.isTestoClass() = when (this) {
else -> false
}

fun PsiFile.isTestoFile() = when (this) {
is PhpFile -> TestoTestDescriptor.isTestClassName(name.substringBeforeLast(".")) || isTestoClassFile() || isTestoFunctionFile() || isTestBenchFile() || isTestoConfigFile()
else -> false
fun PsiFile.isTestoFile(): Boolean {
if (this !is PhpFile) return false
val vFile = virtualFile ?: return false
if (!vFile.isValid) return false

val fileIndex = ProjectFileIndex.getInstance(project)
if (!fileIndex.isInContent(vFile)) return false
if (fileIndex.isExcluded(vFile)) return false
if (fileIndex.isUnderIgnored(vFile)) return false

return try {
TestoTestDescriptor.isTestClassName(name.substringBeforeLast("."))
|| isTestoClassFile()
|| isTestoFunctionFile()
|| isTestBenchFile()
|| isTestoConfigFile()
} catch (e: ProcessCanceledException) {
throw e
} catch (e: Throwable) {
LOG.warn("Failed to determine whether ${vFile.path} is a Testo file", e)
false
}
}

fun PhpFile.isTestoConfigFile() = PsiTreeUtil.findChildrenOfType(this, ClassReference::class.java)
Expand Down
19 changes: 19 additions & 0 deletions src/test/kotlin/com/github/xepozz/testo/MixinPsiTest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.xepozz.testo

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

fun testIsTestoFile_invalidVirtualFile_returnsFalse() {
val psiFile = myFixture.configureByText(
"DeletedTest.php",
"""<?php class DeletedTest { public function testSomething(): void {} }"""
) as PhpFile

assertTrue("Precondition: file should initially be detected as a Testo file", psiFile.isTestoFile())

val vFile = psiFile.virtualFile!!
WriteAction.runAndWait<Throwable> { vFile.delete(this) }

assertFalse("VirtualFile should be invalid after deletion", vFile.isValid)
assertFalse(
"isTestoFile must return false when the underlying VirtualFile is invalid",
psiFile.isTestoFile()
)
}

// ---- isTestoExecutable ----

fun testIsTestoExecutable_testMethod() {
Expand Down
Loading