Skip to content

Commit 5048058

Browse files
committed
feat: support array creation routes
1 parent 6ae00a6 commit 5048058

File tree

6 files changed

+96
-115
lines changed

6 files changed

+96
-115
lines changed

src/main/kotlin/com/github/tempest/framework/common/completion/CompletionWeighter.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@ class CompletionWeighter : CompletionWeigher() {
88
override fun weigh(
99
element: LookupElement,
1010
location: CompletionLocation
11-
): Comparable<*>? {
12-
println("completion weigher: $element")
13-
return when {
14-
element is TopPriorityLookupElement -> 10
15-
else -> null
16-
}.apply { println("weigh: $this") }
11+
) = when {
12+
element is TopPriorityLookupElement -> 1_000_000
13+
else -> null
1714
}
1815
}

src/main/kotlin/com/github/tempest/framework/router/completion/RouteParameterCompletionContributor.kt

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.github.tempest.framework.router.completion
33
import com.github.tempest.framework.TempestFrameworkClasses
44
import com.github.tempest.framework.common.completion.TopPriorityLookupElement
55
import com.github.tempest.framework.common.insertHandler.InsertTextInsertHandler
6+
import com.github.tempest.framework.router.index.Route
67
import com.github.tempest.framework.router.index.RouterIndexUtils
78
import com.intellij.codeInsight.completion.CompletionContributor
89
import com.intellij.codeInsight.completion.CompletionParameters
@@ -15,8 +16,11 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder
1516
import com.intellij.patterns.PlatformPatterns
1617
import com.intellij.util.ProcessingContext
1718
import com.jetbrains.php.PhpIcons
19+
import com.jetbrains.php.lang.PhpReferenceContributor
20+
import com.jetbrains.php.lang.psi.elements.ArrayCreationExpression
1821
import com.jetbrains.php.lang.psi.elements.ConstantReference
1922
import com.jetbrains.php.lang.psi.elements.FunctionReference
23+
import com.jetbrains.php.lang.psi.elements.Method
2024
import com.jetbrains.php.lang.psi.elements.ParameterList
2125
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression
2226

@@ -52,27 +56,63 @@ class RouteParameterCompletionContributor : CompletionContributor() {
5256
val function = parameterList.parent as? FunctionReference ?: return
5357
if (function.fqn != TempestFrameworkClasses.FUNCTION_URI) return
5458
if (parameterList.parameters.isEmpty()) return
55-
if (parameterList.parameters[0] == element) return
5659

57-
val routePattern = function.parameters[0] as? StringLiteralExpression ?: return
60+
val firstParameter = function.parameters[0]
61+
if (firstParameter == element) return
5862

59-
RouterIndexUtils.getRoutes(routePattern.contents, element.project)
60-
.flatMap { it.parameters }
61-
.map { parameter ->
62-
LookupElementBuilder.create(parameter.name)
63-
.withIcon(PhpIcons.PARAMETER)
64-
.withTailText(" Pattern: ${parameter.pattern}".takeIf { parameter.pattern.isNotEmpty() })
65-
.withTypeText(routePattern.contents)
66-
.withInsertHandler { context, element ->
67-
InsertTextInsertHandler(
68-
": ",
69-
DeclarativeInsertHandler.PopupOptions.MemberLookup
70-
)
71-
.handleInsert(context, element)
63+
when (firstParameter) {
64+
is ArrayCreationExpression -> fromArrayCreation(firstParameter, result)
65+
is StringLiteralExpression -> fromStringLiteral(firstParameter, result)
66+
}
67+
}
68+
69+
private fun fromArrayCreation(
70+
firstParameter: ArrayCreationExpression,
71+
result: CompletionResultSet
72+
) {
73+
PhpReferenceContributor
74+
.getCallbackRefFromArray(firstParameter)
75+
?.resolve()
76+
?.let { it as? Method }
77+
?.attributes
78+
?.filter { it.fqn in TempestFrameworkClasses.ROUTES }
79+
?.mapNotNull { RouterIndexUtils.createRouteFromAttribute(it) }
80+
?.apply { fromRoutes(this, result) }
81+
}
82+
83+
private fun fromStringLiteral(
84+
routePattern: StringLiteralExpression,
85+
result: CompletionResultSet
86+
) {
87+
RouterIndexUtils
88+
.getRoutesByPattern(routePattern.contents, routePattern.project)
89+
.apply { fromRoutes(this, result) }
90+
}
91+
92+
private fun fromRoutes(
93+
routes: Collection<Route>,
94+
result: CompletionResultSet
95+
) {
96+
routes
97+
.flatMap { route ->
98+
route
99+
.parameters
100+
.map { parameter ->
101+
LookupElementBuilder.create(parameter.name)
102+
.withIcon(PhpIcons.PARAMETER)
103+
.withTailText(" Pattern: ${parameter.pattern}".takeIf { parameter.pattern.isNotEmpty() })
104+
.withTypeText(route.pattern)
105+
.withInsertHandler { context, element ->
106+
InsertTextInsertHandler(
107+
": ",
108+
DeclarativeInsertHandler.PopupOptions.MemberLookup
109+
)
110+
.handleInsert(context, element)
111+
}
112+
.let { PrioritizedLookupElement.withPriority(it, 10000.0) }
113+
.let { PrioritizedLookupElement.withExplicitProximity(it, 10000) }
114+
.let { TopPriorityLookupElement(it) }
72115
}
73-
.let { PrioritizedLookupElement.withPriority(it, 10000.0) }
74-
.let { PrioritizedLookupElement.withExplicitProximity(it, 10000) }
75-
.let { TopPriorityLookupElement(it) }
76116
}
77117
.apply { result.addAllElements(this) }
78118
.apply { if (isNotEmpty()) result.stopHere() }

src/main/kotlin/com/github/tempest/framework/router/index/RouterActionsIndex.kt

Lines changed: 0 additions & 56 deletions
This file was deleted.

src/main/kotlin/com/github/tempest/framework/router/index/RouterIndexUtils.kt

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package com.github.tempest.framework.router.index
22

3+
import com.github.tempest.framework.router.StringUtils
34
import com.intellij.openapi.project.Project
5+
import com.intellij.openapi.util.text.StringUtil
46
import com.intellij.psi.search.GlobalSearchScope
57
import com.intellij.util.indexing.FileBasedIndex
8+
import com.jetbrains.php.lang.psi.elements.Method
9+
import com.jetbrains.php.lang.psi.elements.PhpAttribute
610

711
object RouterIndexUtils {
812
fun getAllRoutes(project: Project): Collection<Route> {
@@ -14,11 +18,38 @@ object RouterIndexUtils {
1418
.filterNotNull()
1519
}
1620

17-
fun getRoutes(pattern: String, project: Project): Collection<Route> {
21+
fun getRoutesByPattern(pattern: String, project: Project): Collection<Route> {
1822
val fileBasedIndex = FileBasedIndex.getInstance()
1923

2024
return fileBasedIndex
2125
.getValues(RoutesListIndex.key, pattern, GlobalSearchScope.allScope(project))
2226
.filterNotNull()
2327
}
28+
29+
fun createRouteFromAttribute(attribute: PhpAttribute): Route? {
30+
val httpMethod = attribute.name?.uppercase() ?: return null
31+
val method = attribute.owner as? Method ?: return null
32+
val pattern = attribute.arguments
33+
.firstOrNull { it.name == "uri" || it.name.isEmpty() }
34+
?.argument
35+
?.value
36+
?.let { StringUtil.unquoteString(it) }
37+
?: return null
38+
val parameters = StringUtils
39+
.findRouterParameters(pattern)
40+
.map {
41+
RouteParameter(
42+
it.groupValues[1],
43+
it.groupValues.getOrNull(2) ?: "",
44+
)
45+
}
46+
.toSet()
47+
48+
return Route(
49+
pattern = pattern,
50+
action = method.fqn,
51+
method = httpMethod,
52+
parameters = parameters,
53+
)
54+
}
2455
}

src/main/kotlin/com/github/tempest/framework/router/index/RoutesListIndex.kt

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ import com.github.tempest.framework.TempestFrameworkClasses
44
import com.github.tempest.framework.TempestFrameworkUtil
55
import com.github.tempest.framework.common.index.AbstractIndex
66
import com.github.tempest.framework.common.index.ObjectStreamDataExternalizer
7-
import com.github.tempest.framework.router.StringUtils
8-
import com.intellij.openapi.util.text.StringUtil
97
import com.intellij.psi.util.PsiTreeUtil
108
import com.intellij.util.indexing.DataIndexer
119
import com.intellij.util.indexing.FileBasedIndex
1210
import com.intellij.util.indexing.FileContent
1311
import com.intellij.util.indexing.ID
1412
import com.jetbrains.php.lang.PhpFileType
15-
import com.jetbrains.php.lang.psi.elements.Method
1613
import com.jetbrains.php.lang.psi.elements.PhpAttribute
1714

1815
private typealias RoutesListIndexType = Route
@@ -41,35 +38,7 @@ class RoutesListIndex : AbstractIndex<RoutesListIndexType>() {
4138
.psiFile
4239
.let { PsiTreeUtil.findChildrenOfType(it, PhpAttribute::class.java) }
4340
.filter { it.fqn in TempestFrameworkClasses.ROUTES }
44-
.mapNotNull { attribute ->
45-
val httpMethod = attribute.name?.uppercase() ?: return@mapNotNull null
46-
val method = attribute.owner as? Method ?: return@mapNotNull null
47-
val pattern = attribute.arguments
48-
.firstOrNull { it.name == "uri" || it.name.isEmpty() }
49-
?.argument
50-
?.value
51-
?.let { StringUtil.unquoteString(it) }
52-
?: return@mapNotNull null
53-
val parameters = StringUtils
54-
.findRouterParameters(pattern)
55-
.map {
56-
RouteParameter(
57-
it.groupValues[1],
58-
it.groupValues.getOrNull(2) ?: "",
59-
)
60-
}
61-
.toSet()
62-
63-
Pair(
64-
pattern,
65-
Route(
66-
pattern = pattern,
67-
action = method.fqn,
68-
method = httpMethod,
69-
parameters = parameters,
70-
),
71-
)
72-
}
73-
.associate { it.first to it.second }
41+
.mapNotNull { RouterIndexUtils.createRouteFromAttribute(it) }
42+
.associateBy { it.pattern }
7443
}
7544
}

src/main/kotlin/com/github/tempest/framework/router/references/RouteReference.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class RouteReference(
3535
val phpIndex = PhpIndexImpl.getInstance(project)
3636

3737
return RouterIndexUtils
38-
.getRoutes(myElement.contents, project)
38+
.getRoutesByPattern(myElement.contents, project)
3939
.flatMap { phpIndex.getMethodsByFQN(it.action) }
4040
.let { PsiElementResolveResult.createResults(it) }
4141
}

0 commit comments

Comments
 (0)