Skip to content

Commit

Permalink
Merge pull request #66 from adelf/this-fields-completion
Browse files Browse the repository at this point in the history
$this beforeEach declared fields + $this static&protected methods completion
  • Loading branch information
olivernybroe authored Sep 8, 2020
2 parents 9a8e9f9 + b1ec79a commit 8288123
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
- Added support for navigation between tests and test subject ([#53](https://github.com/pestphp/pest-intellij/pull/53))
- Added error reporting to GitHub issues ([#55](https://github.com/pestphp/pest-intellij/pull/55))
- Added inspection for duplicate test names in same file. ([#56](https://github.com/pestphp/pest-intellij/pull/56))
- Added completions for static and protected $this methods. ([#66](https://github.com/pestphp/pest-intellij/pull/66))
- Added completions $this fields declared in beforeEach functions. ([#66](https://github.com/pestphp/pest-intellij/pull/66))

### Changed

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.pestphp.pest.completion

import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionProvider
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.util.ProcessingContext
import com.jetbrains.php.PhpIndex
import com.jetbrains.php.completion.PhpVariantsUtil
import com.jetbrains.php.lang.psi.elements.FieldReference
import com.jetbrains.php.lang.psi.elements.Variable
import com.pestphp.pest.isAnyPestFunction
import com.pestphp.pest.isThisVariableInPest

class InternalMembersCompletionProvider : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
val fieldReference = parameters.position.parent as? FieldReference ?: return

val variable = fieldReference.classReference as? Variable ?: return

if (!variable.isThisVariableInPest { it.isAnyPestFunction() }) return

val phpIndex = PhpIndex.getInstance(fieldReference.project)
val classes = phpIndex.completeType(fieldReference.project, variable.type, null).types
.filter { it.startsWith("\\") }
.flatMap {
phpIndex.getAnyByFQN(it)
}

classes.flatMap { phpClass ->
phpClass.methods.filter { it.access.isProtected || (!it.access.isPrivate && it.isStatic) }
}.forEach {
result.addElement(PhpVariantsUtil.getLookupItem(it, null))
}

classes.flatMap { phpClass ->
phpClass.fields.filter { it.modifier.isProtected }
}.forEach {
result.addElement(PhpVariantsUtil.getLookupItem(it, null))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.pestphp.pest.completion

import com.intellij.codeInsight.completion.CompletionContributor
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.patterns.PlatformPatterns
import com.jetbrains.php.lang.lexer.PhpTokenTypes
import com.jetbrains.php.lang.psi.elements.FieldReference

class PestCompletionContributor : CompletionContributor() {
init {
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement()
.withElementType(PhpTokenTypes.IDENTIFIER)
.withParent(FieldReference::class.java),
InternalMembersCompletionProvider()
)

extend(
CompletionType.BASIC,
PlatformPatterns.psiElement()
.withElementType(PhpTokenTypes.IDENTIFIER)
.withParent(FieldReference::class.java),
ThisFieldsCompletionProvider()
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.pestphp.pest.completion

import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionProvider
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler
import com.intellij.openapi.editor.Editor
import com.intellij.psi.PsiElement
import com.intellij.psi.util.elementType
import com.intellij.util.ProcessingContext
import com.jetbrains.php.PhpIcons
import com.jetbrains.php.lang.lexer.PhpTokenTypes
import com.jetbrains.php.lang.psi.elements.FieldReference
import com.jetbrains.php.lang.psi.elements.Variable
import com.pestphp.pest.getAllBeforeThisAssignments
import com.pestphp.pest.isAnyPestFunction
import com.pestphp.pest.isThisVariableInPest

class ThisFieldsCompletionProvider : CompletionProvider<CompletionParameters>(), GotoDeclarationHandler {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
val fieldReference = parameters.position.parent as? FieldReference ?: return

val variable = fieldReference.classReference as? Variable ?: return

if (!variable.isThisVariableInPest { it.isAnyPestFunction() }) return

return (fieldReference.containingFile ?: return).getAllBeforeThisAssignments()
.mapNotNull { it.variable?.name }
.forEach {
result.addElement(LookupElementBuilder.create(it).withIcon(PhpIcons.FIELD))
}
}

override fun getGotoDeclarationTargets(
sourceElement: PsiElement?,
offset: Int,
editor: Editor?
): Array<PsiElement> {
if (sourceElement?.elementType != PhpTokenTypes.IDENTIFIER) {
return PsiElement.EMPTY_ARRAY
}

val fieldReference = sourceElement?.parent as? FieldReference
?: return PsiElement.EMPTY_ARRAY

if (fieldReference.classReference?.isThisVariableInPest { it.isAnyPestFunction() } != true) {
return PsiElement.EMPTY_ARRAY
}

return (fieldReference.containingFile ?: return PsiElement.EMPTY_ARRAY).getAllBeforeThisAssignments()
.filter { it.variable?.name == fieldReference.name }
.mapNotNull { it.variable }
.toTypedArray()
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/com/pestphp/pest/goto/PestTestFinder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class PestTestFinder : TestFinder {
GlobalSearchScope.projectScope(element.project)
)
}
.map { PsiManager.getInstance(element.project).findFile(it)!! }
.mapNotNull { PsiManager.getInstance(element.project).findFile(it) }
.toCollection(ArrayList())
}
}
3 changes: 3 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
displayName="Duplicate test name"
implementationClass="com.pestphp.pest.inspections.DuplicateTestNameInspection"
/>

<completion.contributor implementationClass="com.pestphp.pest.completion.PestCompletionContributor" language="PHP"/>
<gotoDeclarationHandler implementation="com.pestphp.pest.completion.ThisFieldsCompletionProvider"/>
</extensions>

<extensions defaultExtensionNs="com.jetbrains.php">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.pestphp.pest.tests.types

class ThisFieldCompletionTest : BaseTypeTest() {
override fun setUp() {
super.setUp()

myFixture.copyDirectoryToProject("thisField", "tests")
}

fun testFieldCompletions() {
myFixture.configureByFile("tests/beforeEachCompletion.php")

assertCompletion("foo")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ class ThisTypeTest : BaseTypeTest() {
}

private fun assertThisCompletion() {
assertCompletion("expectException", "expectExceptionCode")
assertCompletion("expectException", "expectExceptionCode", "someProtectedMethod", "someStaticMethod", "protectedField")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace PHPUnit\Framework;

abstract class TestCase {
protected $protectedField;

/**
* @param string $exception
*/
Expand All @@ -12,4 +14,8 @@ public function expectException($exception) {}
* @param int|string $code
*/
public function expectExceptionCode($code){}

protected function someProtectedMethod(){}

public static function someStaticMethod(){}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

beforeEach(function () {
$this->foo = 1;
});

it('has home', function () {
$this-><caret>
});

0 comments on commit 8288123

Please sign in to comment.