generated from JetBrains/intellij-platform-plugin-template
-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for autocompletion after higher order methods and properties
- Loading branch information
Oliver Nybroe
committed
Nov 30, 2020
1 parent
22c8086
commit daf357b
Showing
12 changed files
with
199 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
src/main/kotlin/dev/nybroe/collector/types/HigherOrderTypeProvider.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package dev.nybroe.collector.types | ||
|
||
import com.intellij.openapi.project.DumbService | ||
import com.intellij.openapi.project.Project | ||
import com.intellij.psi.PsiElement | ||
import com.jetbrains.php.PhpIndex | ||
import com.jetbrains.php.lang.psi.elements.FieldReference | ||
import com.jetbrains.php.lang.psi.elements.MethodReference | ||
import com.jetbrains.php.lang.psi.elements.PhpNamedElement | ||
import com.jetbrains.php.lang.psi.resolve.types.PhpType | ||
import com.jetbrains.php.lang.psi.resolve.types.PhpTypeProvider4 | ||
import dev.nybroe.collector.collectionType | ||
import dev.nybroe.collector.isHigherOrderCollection | ||
import gnu.trove.THashSet | ||
|
||
class HigherOrderTypeProvider : PhpTypeProvider4 { | ||
override fun getKey(): Char { | ||
return '\u0171' | ||
} | ||
|
||
override fun getType(psiElement: PsiElement): PhpType? { | ||
if (DumbService.isDumb(psiElement.project)) return null | ||
|
||
// Check that our current element is a field or method reference | ||
// $collection->map->data, $collection->map->data() | ||
val fieldOrMethodReference = psiElement as? FieldReference | ||
?: psiElement as? MethodReference | ||
?: return null | ||
|
||
// Check that parent is a field reference. | ||
// $collection->map | ||
val parentField = fieldOrMethodReference.classReference as? FieldReference ?: return null | ||
|
||
return PhpType().add("#${this.key}${parentField.type}") | ||
} | ||
|
||
override fun complete(s: String, project: Project): PhpType? { | ||
return null | ||
} | ||
|
||
/** | ||
* Here you can extend the signature lookups | ||
* @param expression Signature expression to decode. use PhpIndex.getBySignature() to look up expression internals. | ||
* @param visited Recursion guard: Pass this on into any phpIndex calls having same parameter | ||
* @param depth Recursion guard: Pass this on into any phpIndex calls having same parameter | ||
* @param project well so you can reach the PhpIndex | ||
* @return null if no match | ||
*/ | ||
override fun getBySignature( | ||
expression: String, | ||
visited: MutableSet<String>, | ||
depth: Int, | ||
project: Project | ||
): MutableCollection<out PhpNamedElement>? { | ||
// Decode the expression into a php type | ||
val type = PhpIndex.getInstance(project).completeType( | ||
project, | ||
PhpType().apply { | ||
expression.split('|').filter { it.length != 1 }.forEach { it -> | ||
this.add(it) | ||
} | ||
}, | ||
null | ||
) | ||
|
||
if (!type.isHigherOrderCollection(project)) return null | ||
|
||
return collectionType.types | ||
.flatMap { PhpIndex.getInstance(project).getClassesByFQN(it.toString()) } | ||
.toCollection(THashSet()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
13 changes: 13 additions & 0 deletions
13
src/test/kotlin/dev/nybroe/collector/BaseCollectTestCase.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package dev.nybroe.collector | ||
|
||
import com.intellij.testFramework.fixtures.BasePlatformTestCase | ||
|
||
@Suppress("UnnecessaryAbstractClass") | ||
internal abstract class BaseCollectTestCase : BasePlatformTestCase() { | ||
override fun getTestDataPath(): String = "src/test/resources" | ||
|
||
override fun setUp() { | ||
super.setUp() | ||
myFixture.copyFileToProject("stubs.php") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package dev.nybroe.collector | ||
|
||
import com.jetbrains.php.lang.psi.resolve.types.PhpType | ||
|
||
internal class UtilTest : BaseCollectTestCase() { | ||
fun testIsCollection() { | ||
assertTrue( | ||
PhpType().add( | ||
"\\Illuminate\\Support\\Collection" | ||
).isCollection(project) | ||
) | ||
} | ||
|
||
fun testMixedIsNotCollection() { | ||
assertFalse(PhpType.MIXED.isCollection(project)) | ||
} | ||
|
||
fun testIterableIsNotCollection() { | ||
assertFalse(PhpType.ITERABLE.isCollection(project)) | ||
} | ||
|
||
fun testArrayIsNotCollection() { | ||
assertFalse(PhpType.ARRAY.isCollection(project)) | ||
} | ||
|
||
fun testEmptyIsNotCollection() { | ||
assertFalse(PhpType.EMPTY.isCollection(project)) | ||
} | ||
} |
11 changes: 2 additions & 9 deletions
11
src/test/kotlin/dev/nybroe/collector/inspections/InspectionTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
src/test/kotlin/dev/nybroe/collector/types/HigherOrderTypeProviderTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package dev.nybroe.collector.types | ||
|
||
import dev.nybroe.collector.BaseCollectTestCase | ||
|
||
internal class HigherOrderTypeProviderTest : BaseCollectTestCase() { | ||
fun testHigherOrderPropertyReturnsCollection() { | ||
myFixture.configureByFile( | ||
"types/HigherOrderMethodsTypeProvider/higherOrderProperty.php" | ||
) | ||
|
||
assertCompletion("map", "each") | ||
} | ||
|
||
fun testHigherOrderMethodReturnsCollection() { | ||
myFixture.configureByFile( | ||
"types/HigherOrderMethodsTypeProvider/higherOrderMethod.php" | ||
) | ||
|
||
assertCompletion("map", "each") | ||
} | ||
|
||
private fun assertCompletion(vararg shouldContain: String) { | ||
myFixture.completeBasic() | ||
|
||
val strings = myFixture.lookupElementStrings ?: return fail("empty completion result") | ||
|
||
assertContainsElements(strings, shouldContain.asList()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/test/resources/types/HigherOrderMethodsTypeProvider/higherOrderMethod.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?php | ||
|
||
class HigherOrderMethod { | ||
public function data() { | ||
return 'works'; | ||
} | ||
} | ||
|
||
collect([ | ||
new HigherOrderMethod() | ||
])->map->data()-><caret> |
5 changes: 5 additions & 0 deletions
5
src/test/resources/types/HigherOrderMethodsTypeProvider/higherOrderProperty.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
|
||
collect([ | ||
['data' => 'works'] | ||
])->map->data-><caret> |