Skip to content

Commit 10cd518

Browse files
committed
feat: rewrite routing reference system
1 parent b66b1f0 commit 10cd518

File tree

13 files changed

+277
-70
lines changed

13 files changed

+277
-70
lines changed

src/main/kotlin/com/github/tempest/framework/TempestFrameworkClasses.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.github.tempest.framework
22

33
object TempestFrameworkClasses {
44
const val ConsoleCommand = "\\Tempest\\Console\\ConsoleCommand"
5+
const val FUNCTION_URI = "\\Tempest\\uri"
56

67
const val ROUTER_GET = "\\Tempest\\Router\\Get"
78
const val ROUTER_POST = "\\Tempest\\Router\\Post"
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.github.tempest.framework.common.index
2+
3+
import com.intellij.util.io.DataExternalizer
4+
import java.io.ByteArrayInputStream
5+
import java.io.ByteArrayOutputStream
6+
import java.io.DataInput
7+
import java.io.DataOutput
8+
import java.io.IOException
9+
import java.io.ObjectInput
10+
import java.io.ObjectInputStream
11+
import java.io.ObjectOutput
12+
import java.io.ObjectOutputStream
13+
14+
class ObjectStreamDataExternalizer<T : Any> : DataExternalizer<T> {
15+
@Throws(IOException::class)
16+
override fun save(out: DataOutput, value: T?) {
17+
val stream = ByteArrayOutputStream()
18+
val output: ObjectOutput = ObjectOutputStream(stream)
19+
20+
output.writeObject(value)
21+
22+
out.writeInt(stream.size())
23+
out.write(stream.toByteArray())
24+
}
25+
26+
@Throws(IOException::class)
27+
override fun read(`in`: DataInput): T? {
28+
val bufferSize = `in`.readInt()
29+
val buffer = ByteArray(bufferSize)
30+
`in`.readFully(buffer, 0, bufferSize)
31+
32+
val stream = ByteArrayInputStream(buffer)
33+
val input: ObjectInput = ObjectInputStream(stream)
34+
35+
var `object`: T? = null
36+
try {
37+
`object` = input.readObject() as T
38+
} catch (ignored: ClassNotFoundException) {
39+
} catch (ignored: ClassCastException) {
40+
}
41+
42+
return `object`
43+
}
44+
}

src/main/kotlin/com/github/tempest/framework/common/utils/StringUtils.kt

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

src/main/kotlin/com/github/tempest/framework/php/mixin.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.github.tempest.framework.php
33
import com.github.tempest.framework.TempestFrameworkClasses
44
import com.intellij.openapi.util.text.StringUtil
55
import com.intellij.psi.util.PsiTreeUtil
6+
import com.jetbrains.php.PhpIndex
67
import com.jetbrains.php.lang.psi.PhpFile
78
import com.jetbrains.php.lang.psi.elements.Method
89
import com.jetbrains.php.lang.psi.elements.Variable
@@ -24,4 +25,12 @@ fun Method.getConsoleCommandName(): String? {
2425
?.argument
2526
?.value
2627
?.run { StringUtil.unquoteString(this) }
27-
}
28+
}
29+
30+
fun PhpIndex.getMethodsByFQN(fqn:String): Collection<Method> {
31+
val (className, methodName) = fqn.split('.')
32+
return this
33+
.getClassesByFQN(className)
34+
.mapNotNull{ it.findMethodByName(methodName) }
35+
}
36+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.github.tempest.framework.router
2+
3+
object StringUtils {
4+
fun findRouterParameters(text: String): List<MatchResult> =
5+
Regex("\\{([^:\\/}]+)(?::([^}]+))?(?:[}\\/]|$)")
6+
.findAll(text)
7+
.toList()
8+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.github.tempest.framework.router.index
2+
3+
import java.io.Serializable
4+
5+
data class Route(
6+
val pattern: String,
7+
val action: String,
8+
val method: String,
9+
val parameters: Set<RouteParameter>,
10+
) : Serializable
11+
12+
data class RouteParameter(
13+
val name: String,
14+
val pattern: String,
15+
) : Serializable
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.github.tempest.framework.router.index
2+
3+
import com.intellij.openapi.project.Project
4+
import com.intellij.psi.search.GlobalSearchScope
5+
import com.intellij.util.indexing.FileBasedIndex
6+
7+
object RouterIndexUtils {
8+
fun getAllRoutes(project: Project): Collection<Route> {
9+
val fileBasedIndex = FileBasedIndex.getInstance()
10+
11+
return fileBasedIndex
12+
.getAllKeys(RoutesListIndex.key, project)
13+
.flatMap { fileBasedIndex.getValues(RoutesListIndex.key, it, GlobalSearchScope.allScope(project)) }
14+
.filterNotNull()
15+
}
16+
17+
fun getRoute(pattern: String, project: Project): Collection<Route> {
18+
val fileBasedIndex = FileBasedIndex.getInstance()
19+
20+
return fileBasedIndex
21+
.getValues(RoutesListIndex.key, pattern, GlobalSearchScope.allScope(project))
22+
.filterNotNull()
23+
}
24+
}

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

Lines changed: 0 additions & 53 deletions
This file was deleted.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.github.tempest.framework.router.index
2+
3+
import com.github.tempest.framework.TempestFrameworkClasses
4+
import com.github.tempest.framework.TempestFrameworkUtil
5+
import com.github.tempest.framework.common.index.AbstractIndex
6+
import com.github.tempest.framework.common.index.ObjectStreamDataExternalizer
7+
import com.github.tempest.framework.router.StringUtils
8+
import com.intellij.openapi.util.text.StringUtil
9+
import com.intellij.psi.util.PsiTreeUtil
10+
import com.intellij.util.indexing.DataIndexer
11+
import com.intellij.util.indexing.FileBasedIndex
12+
import com.intellij.util.indexing.FileContent
13+
import com.intellij.util.indexing.ID
14+
import com.jetbrains.php.lang.PhpFileType
15+
import com.jetbrains.php.lang.psi.elements.Method
16+
import com.jetbrains.php.lang.psi.elements.PhpAttribute
17+
18+
private typealias RoutesListIndexType = Route
19+
20+
/**
21+
* Stores uri -> methods association
22+
*/
23+
class RoutesListIndex : AbstractIndex<RoutesListIndexType>() {
24+
companion object {
25+
val key = ID.create<String, RoutesListIndexType>("Tempest.Routes.List")
26+
}
27+
28+
override fun getVersion() = 2
29+
30+
override fun getName() = key
31+
32+
override fun getValueExternalizer() = ObjectStreamDataExternalizer<RoutesListIndexType>()
33+
34+
override fun getInputFilter() = FileBasedIndex.InputFilter {
35+
it.fileType == PhpFileType.INSTANCE &&
36+
!it.name.endsWith(TempestFrameworkUtil.TEMPLATE_SUFFIX)
37+
}
38+
39+
override fun getIndexer() = DataIndexer<String, RoutesListIndexType, FileContent> { inputData ->
40+
inputData
41+
.psiFile
42+
.let { PsiTreeUtil.findChildrenOfType(it, PhpAttribute::class.java) }
43+
.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 }
74+
}
75+
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.github.tempest.framework.router.references
22

33
import com.github.tempest.framework.TempestFrameworkClasses
4-
import com.github.tempest.framework.common.utils.StringUtils
54
import com.github.tempest.framework.php.patterns.AttributeFqnCondition
5+
import com.github.tempest.framework.router.StringUtils
66
import com.intellij.openapi.util.TextRange
77
import com.intellij.patterns.PlatformPatterns
88
import com.intellij.patterns.StandardPatterns
@@ -38,11 +38,12 @@ class RouteParametersReferenceContributor : PsiReferenceContributor() {
3838
val parameters = method.parameters
3939
if (parameters.isEmpty()) return emptyArray()
4040

41-
return StringUtils.findTextBetweenParenthesis(element.text)
42-
.map { alias ->
41+
return StringUtils.findRouterParameters(element.text)
42+
.mapNotNull { alias ->
43+
val nameGroup = alias.groups[1] ?: return@mapNotNull null
4344
val rangeInElement = TextRange(
44-
alias.range.first + 1,
45-
alias.range.last
45+
nameGroup.range.first,
46+
nameGroup.range.last+1
4647
)
4748

4849
val parameter = method.getParameter(alias.groupValues[1])

0 commit comments

Comments
 (0)