Skip to content

Commit

Permalink
feat(goto): Navigate between test and implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
olivernybroe committed Aug 17, 2020
1 parent 2e69ec0 commit f1b63ac
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

## [Unreleased]
### Added
- Add support for showing pest version
- Added support for showing pest version
- Added support for navigation between tests and test subject

### Changed

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

pluginGroup = com.pestphp
pluginName = PEST PHP
pluginVersion = 0.3.3
pluginVersion = 0.4.0-alpha.1
pluginSinceBuild = 201
pluginUntilBuild = null

Expand Down
49 changes: 49 additions & 0 deletions src/main/kotlin/com/pestphp/pest/goto/PestTestFinder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.pestphp.pest.goto

import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.testIntegration.TestFinder
import com.intellij.util.indexing.FileBasedIndex
import com.jetbrains.php.PhpIndex
import com.jetbrains.php.lang.psi.elements.PhpClass
import com.pestphp.pest.indexers.PestTestIndex
import com.pestphp.pest.isPestTestFile
import java.util.ArrayList

class PestTestFinder : TestFinder {
override fun findClassesForTest(element: PsiElement): MutableCollection<PhpClass> {
return PhpIndex.getInstance(element.project)
.getClassesByNameInScope(
element.containingFile.name.removeSuffix("Test.php"),
GlobalSearchScope.projectScope(element.project)
)
}

override fun findSourceElement(from: PsiElement): PsiElement? {
return from.containingFile
}

override fun isTest(element: PsiElement): Boolean {
return element.containingFile.isPestTestFile()
}

override fun findTestsForClass(element: PsiElement): MutableCollection<PsiElement> {
val phpClass = PsiTreeUtil.getNonStrictParentOfType(element, PhpClass::class.java) ?: return arrayListOf()

return FileBasedIndex.getInstance().getAllKeys(
PestTestIndex.key,
element.project
).filter { it.contains(phpClass.name) }
.flatMap {
FileBasedIndex.getInstance().getContainingFiles(
PestTestIndex.key,
it,
GlobalSearchScope.projectScope(element.project)
)
}
.map { PsiManager.getInstance(element.project).findFile(it)!! }
.toCollection(ArrayList())
}
}
52 changes: 52 additions & 0 deletions src/main/kotlin/com/pestphp/pest/indexers/PestTestIndex.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.pestphp.pest.indexers

import com.intellij.util.indexing.DataIndexer
import com.intellij.util.indexing.FileBasedIndex
import com.intellij.util.indexing.FileContent
import com.intellij.util.indexing.ID
import com.intellij.util.indexing.ScalarIndexExtension
import com.intellij.util.io.EnumeratorStringDescriptor
import com.intellij.util.io.KeyDescriptor
import com.jetbrains.php.lang.psi.stubs.indexes.PhpConstantNameIndex
import com.pestphp.pest.isPestTestFile
import gnu.trove.THashMap

class PestTestIndex : ScalarIndexExtension<String>() {
override fun getName(): ID<String, Void> {
return key
}

override fun getVersion(): Int {
return 0
}

override fun dependsOnFileContent(): Boolean {
return true
}

override fun getIndexer(): DataIndexer<String, Void, FileContent> {
return DataIndexer { inputData ->
val file = inputData.psiFile

if (!file.isPestTestFile()) {
return@DataIndexer mapOf()
}

val map = THashMap<String, Void>()
map[file.name] = null
return@DataIndexer map
}
}

override fun getInputFilter(): FileBasedIndex.InputFilter {
return PhpConstantNameIndex.PHP_INPUT_FILTER
}

override fun getKeyDescriptor(): KeyDescriptor<String> {
return EnumeratorStringDescriptor.INSTANCE
}

companion object {
val key = ID.create<String, Void>("php.pest")
}
}
2 changes: 2 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
<iconProvider implementation="com.pestphp.pest.PestIconProvider"/>

<projectService serviceImplementation="com.pestphp.pest.PestSettings"/>
<testFinder implementation="com.pestphp.pest.goto.PestTestFinder"/>
<fileBasedIndex implementation="com.pestphp.pest.indexers.PestTestIndex"/>
</extensions>

<extensions defaultExtensionNs="com.jetbrains.php">
Expand Down
43 changes: 43 additions & 0 deletions src/test/kotlin/com/pestphp/pest/goto/PestTestFinderTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.pestphp.pest.goto

import com.jetbrains.php.lang.psi.PhpFile
import com.jetbrains.php.lang.psi.PhpPsiUtil
import com.pestphp.pest.tests.PestLightCodeFixture
import junit.framework.TestCase

class PestTestFinderTest : PestLightCodeFixture() {
override fun getTestDataPath(): String? {
return "src/test/resources/com/pestphp/pest/goto/PestTestFinder"
}

fun testPestTestIsTest() {
val file = myFixture.configureByFile("test/App/UserTest.php")

val testElement = file.firstChild.lastChild.firstChild

assertTrue(PestTestFinder().isTest(testElement))
}

fun testFileIsTest() {
val file = myFixture.configureByFile("test/App/UserTest.php")

assertTrue(PestTestFinder().isTest(file))
}

fun testRandomElementIsTest() {
val file = myFixture.configureByFile("test/App/UserTest.php")

assertTrue(PestTestFinder().isTest(file.firstChild.children.random()))
}

fun testCanFindSourceElement() {
val file = myFixture.configureByFile("App/User.php")

TestCase.assertSame(
file,
PestTestFinder().findSourceElement(
PhpPsiUtil.findAllClasses(file as PhpFile).first().methods.first()
)
)
}
}
41 changes: 41 additions & 0 deletions src/test/kotlin/com/pestphp/pest/indexers/PestTestIndexTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.pestphp.pest.indexers

import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.indexing.FileBasedIndex
import com.pestphp.pest.tests.PestLightCodeFixture
import junit.framework.TestCase

class PestTestIndexTest : PestLightCodeFixture() {
override fun getTestDataPath(): String? {
return "src/test/resources/com/pestphp/pest/indexers/PestTestIndexTest"
}

fun testPestTestFileIsIndexed() {
val file = myFixture.configureByFile("FileWithPestTest.php")

val indexes = FileBasedIndex.getInstance().getAllKeys(PestTestIndex.key, project)

val files = FileBasedIndex.getInstance().getContainingFiles(
PestTestIndex.key,
indexes.first(),
GlobalSearchScope.projectScope(project)
)

assertNotNull(file.virtualFile)
assertContainsElements(files, file.virtualFile)
}

fun testPhpFileIsNotIndexed() {
val file = myFixture.configureByFile("FileWithoutPestTest.php")

val indexes = FileBasedIndex.getInstance().getAllKeys(PestTestIndex.key, project)

val files = FileBasedIndex.getInstance().getContainingFiles(
PestTestIndex.key,
indexes.first(),
GlobalSearchScope.projectScope(project)
)

assertDoesntContain(files, file.virtualFile)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace App;

class User {
public function getName(): String
{
return "Oliver Nybroe";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

test("Can get user's name", function () {
$user = new \App\User();

$this->asserEquals("Oliver Nybroe", $user->getName());
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

test('basic', function () {
$this->assertTrue(true);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

echo "works";

0 comments on commit f1b63ac

Please sign in to comment.