Skip to content

Commit 4a29149

Browse files
authored
enhance api completion
1 parent 7da1793 commit 4a29149

File tree

8 files changed

+350
-73
lines changed

8 files changed

+350
-73
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.github.oldmegit.goframehelper.apiTagValueUtil
2+
3+
object Method : TagValue {
4+
override val list: Map<String, String>
5+
get() = mapOf(
6+
"get" to "",
7+
"put" to "",
8+
"post" to "",
9+
"patch" to "",
10+
"delete" to "",
11+
"options" to "",
12+
"head" to "",
13+
)
14+
15+
override val separator: String
16+
get() = ","
17+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.github.oldmegit.goframehelper.apiTagValueUtil
2+
3+
object Mime : TagValue {
4+
override val list: Map<String, String>
5+
get() = mapOf(
6+
"multipart/form-data" to "",
7+
"application/json" to "",
8+
"application/x-www-form-urlencoded" to "",
9+
)
10+
11+
override val separator: String
12+
get() = ","
13+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.github.oldmegit.goframehelper.apiTagValueUtil
2+
3+
interface TagValue {
4+
val list: Map<String, String>
5+
val separator: String
6+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.github.oldmegit.goframehelper.apiTagValueUtil
2+
3+
import com.github.oldmegit.goframehelper.data.GfValidationBundle
4+
5+
object Validation : TagValue {
6+
override val list: Map<String, String>
7+
get() = mapOf(
8+
"bail" to getTail("bail"),
9+
"ci" to getTail("ci"),
10+
"foreach" to getTail("foreach"),
11+
"required" to getTail("required"),
12+
"required-if" to getTail("required-if"),
13+
"required-unless" to getTail("required-unless"),
14+
"required-with" to getTail("required-with"),
15+
"required-with-all" to getTail("required-with-all"),
16+
"required-without" to getTail("required-without"),
17+
"required-without-all" to getTail("required-without-all"),
18+
"date" to getTail("date"),
19+
"datetime" to getTail("datetime"),
20+
"date-format" to getTail("date-format"),
21+
"before" to getTail("before"),
22+
"before-equal" to getTail("before-equal"),
23+
"after" to getTail("after"),
24+
"after-equal" to getTail("after-equal"),
25+
"array" to getTail("array"),
26+
"enums" to getTail("enums"),
27+
"email" to getTail("email"),
28+
"phone" to getTail("phone"),
29+
"phone-loose" to getTail("phone-loose"),
30+
"telephone" to getTail("telephone"),
31+
"passport" to getTail("passport"),
32+
"password" to getTail("password"),
33+
"password2" to getTail("password2"),
34+
"password3" to getTail("password3"),
35+
"postcode" to getTail("postcode"),
36+
"resident-id" to getTail("resident-id"),
37+
"bank-card" to getTail("bank-card"),
38+
"qq" to getTail("qq"),
39+
"ip" to getTail("ip"),
40+
"ipv4" to getTail("ipv4"),
41+
"ipv6" to getTail("ipv6"),
42+
"mac" to getTail("mac"),
43+
"url" to getTail("url"),
44+
"domain" to getTail("domain"),
45+
"size" to getTail("size"),
46+
"length" to getTail("length"),
47+
"min-length" to getTail("min-length"),
48+
"max-length" to getTail("max-length"),
49+
"between" to getTail("between"),
50+
"min" to getTail("min"),
51+
"json" to getTail("json"),
52+
"integer" to getTail("integer"),
53+
"float" to getTail("float"),
54+
"boolean" to getTail("boolean"),
55+
"same" to getTail("same"),
56+
"different" to getTail("different"),
57+
"eq" to getTail("eq"),
58+
"not-eq" to getTail("not-eq"),
59+
"gt" to getTail("gt"),
60+
"gte" to getTail("gte"),
61+
"lt" to getTail("lt"),
62+
"lte" to getTail("lte"),
63+
"in" to getTail("in"),
64+
"not-in" to getTail("not-in"),
65+
"regex" to getTail("regex"),
66+
"not-regex" to getTail("not-regex"),
67+
)
68+
69+
override val separator: String
70+
get() = ","
71+
72+
private fun getTail(key: String): String {
73+
return GfValidationBundle.getMessage(key)
74+
}
75+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.github.oldmegit.goframehelper.data
2+
3+
import com.intellij.DynamicBundle
4+
import java.util.function.Supplier
5+
6+
object GfValidationBundle : DynamicBundle("message.GfValidationBundle") {
7+
override fun getMessage(key: String, vararg params: Any?): String {
8+
return super.getMessage(key, *params)
9+
}
10+
11+
override fun getLazyMessage(key: String, vararg params: Any?): Supplier<String> {
12+
return super.getLazyMessage(key, *params)
13+
}
14+
}
Lines changed: 107 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,47 @@
11
package com.github.oldmegit.goframehelper.provider
22

3+
import com.github.oldmegit.goframehelper.apiTagValueUtil.*
4+
import com.github.oldmegit.goframehelper.apiTagValueUtil.TagValue
35
import com.github.oldmegit.goframehelper.gf.Gf
46
import com.goide.psi.GoAnonymousFieldDefinition
57
import com.goide.psi.GoFieldDefinition
68
import com.goide.psi.GoStructType
9+
import com.intellij.codeInsight.completion.CompletionUtilCore
710
import com.intellij.codeInsight.lookup.LookupElementBuilder
8-
import com.intellij.openapi.util.TextRange
911
import com.intellij.psi.PsiElement
1012

1113
class ApiTagProvider: GfProvider() {
14+
private val valueObject = mapOf<String, TagValue>(
15+
"method" to Method,
16+
"v" to Validation,
17+
"mime" to Mime,
18+
)
19+
1220
override fun addCompletionsEvent() {
1321
// only struct name containing "Req" or "Res" can need code completion
1422
if (!isValidStruct()) {
1523
return
1624
}
1725

1826
if (positionIsTagKey()) {
19-
codeCompletionTagKey()
27+
keyCodeCompletion()
28+
} else {
29+
valueCodeCompletion()
2030
}
2131
}
2232

2333
override fun isValidFolder(): Boolean {
2434
return Gf.isApiFile(position.project, parameters.originalFile.virtualFile)
2535
}
2636

37+
private fun getStructType(): PsiElement? {
38+
val structType = position.parent.parent.parent.parent
39+
if (structType is GoStructType) {
40+
return structType
41+
}
42+
return null
43+
}
44+
2745
private fun isValidStruct(): Boolean {
2846
val structType = getStructType()
2947
if (structType == null) {
@@ -35,97 +53,113 @@ class ApiTagProvider: GfProvider() {
3553
return lastStr == "Req" || lastStr == "Res"
3654
}
3755

38-
private fun codeCompletionTagKey(text: String, tailText: String) {
39-
result.addElement(
40-
LookupElementBuilder.create(text)
41-
.withInsertHandler { ctx, _ ->
42-
ctx.document.insertString(ctx.tailOffset, ":\"\"")
43-
ctx.editor.caretModel.moveToOffset(ctx.editor.caretModel.offset + 2)
44-
}
45-
.withIcon(Gf.icon)
46-
.withTailText(" $tailText", true)
47-
)
56+
private fun getFiledPsiElement(): PsiElement? {
57+
val fieldDefinition = position.parent.parent.parent.firstChild
58+
if (fieldDefinition is GoFieldDefinition || fieldDefinition is GoAnonymousFieldDefinition) {
59+
return fieldDefinition
60+
}
61+
return null
4862
}
4963

50-
// check position is tag key
51-
private fun positionIsTagKey(): Boolean {
52-
val rawText = position.text
53-
if (!rawText.contains("\"")) {
54-
return true
55-
}
56-
val offset = parameters.offset
57-
var textRange = TextRange(offset - 2, offset)
58-
var text = parameters.editor.document.getText(textRange)
59-
if (text != "\" ") {
60-
return false
64+
private fun getFieldName(): String {
65+
val name = getFiledPsiElement()?.text
66+
if (name != null) {
67+
return name
6168
}
62-
textRange = TextRange(offset - 3, offset)
63-
text = parameters.editor.document.getText(textRange)
64-
return text != ":\" "
69+
return ""
6570
}
6671

67-
private fun codeCompletionTagKey() {
72+
private fun getFieldNameTag() : Map<String, String> {
6873
// get filed name
6974
val filedName = getFieldName()
75+
val m = hashMapOf<String, String>()
76+
m.putAll(Gf.openApiTag)
7077

7178
if (filedName == "g.Meta") {
72-
for ((text, tailText) in Gf.openApiTagGMeta) {
73-
codeCompletionTagKey(text, tailText)
74-
}
79+
m.putAll(Gf.openApiTagGMeta)
7580
} else {
76-
for ((text, tailText) in Gf.openApiTagNormal) {
77-
codeCompletionTagKey(text, tailText)
78-
}
81+
m.putAll(Gf.openApiTagNormal)
7982
}
8083

81-
for ((text, tailText) in Gf.openApiTag) {
82-
codeCompletionTagKey(text, tailText)
83-
}
84+
return m
85+
}
86+
87+
// check position is tag key
88+
private fun positionIsTagKey(): Boolean {
89+
val rawText = position.text
90+
val tagValuePattern = String.format("\\w+:\"[^\"]*?%s.*?\"", CompletionUtilCore.DUMMY_IDENTIFIER_TRIMMED)
91+
val regex = Regex(tagValuePattern)
92+
return !rawText.contains(regex)
8493
}
8594

86-
// check position is tag value
87-
// private fun positionIsTagValue(tagKey: String): Boolean {
88-
// val text = position.text
89-
// val tagKeyMark = "$tagKey:\""
90-
// val tagStart = text.indexOf(tagKeyMark)
91-
// val tagEnd = text.indexOf("\"", tagStart + tagKeyMark.length)
92-
// val offset = parameters.offset
93-
// val textRange = position.textRange
94-
// val stringOffset = offset - textRange.startOffset
95-
//
96-
// val vTextRange = TextRange(tagStart, tagEnd)
97-
// return textRange.contains(offset) && vTextRange.contains(stringOffset)
98-
// }
99-
//
100-
// private fun codeCompletionTagValue(text: String, tailText: String) {
101-
// result.addElement(
102-
// LookupElementBuilder.create(text)
103-
// .withIcon(Gf.icon)
104-
// .withTailText(" $tailText", true)
105-
// )
106-
// }
95+
// tag key code completion
96+
private fun keyCodeCompletion() {
97+
val text = position.text.replace("`", "")
98+
val textArr = text.split(CompletionUtilCore.DUMMY_IDENTIFIER)
99+
var prefix = textArr[0]
107100

108-
private fun getStructType(): PsiElement? {
109-
val structType = position.parent.parent.parent.parent
110-
if (structType is GoStructType) {
111-
return structType
101+
if (prefix.endsWith(" ")) {
102+
prefix = ""
112103
}
113-
return null
114-
}
115104

116-
private fun getFiledPsiElement(): PsiElement? {
117-
val fieldDefinition = position.parent.parent.parent.firstChild
118-
if (fieldDefinition is GoFieldDefinition || fieldDefinition is GoAnonymousFieldDefinition) {
119-
return fieldDefinition
105+
val lastSpaceIndex = prefix.lastIndexOf(" ")
106+
val lastPrefixOfTag = prefix.substring(lastSpaceIndex + 1)
107+
val tagList = getFieldNameTag()
108+
109+
for ((k, v) in tagList) {
110+
if (k.startsWith(lastPrefixOfTag)) {
111+
keyAddElement(prefix + k.removePrefix(lastPrefixOfTag), k , v)
112+
}
120113
}
121-
return null
122114
}
123115

124-
private fun getFieldName(): String {
125-
val name = getFiledPsiElement()?.text
126-
if (name != null) {
127-
return name
116+
// add tag key element
117+
private fun keyAddElement(lookupString: String, text: String, tail: String = "") {
118+
result.addElement(
119+
LookupElementBuilder.create(lookupString)
120+
.withInsertHandler { ctx, _ ->
121+
ctx.document.insertString(ctx.tailOffset, ":\"\"")
122+
ctx.editor.caretModel.moveToOffset(ctx.editor.caretModel.offset + 2)
123+
}
124+
.withIcon(Gf.icon)
125+
.withTailText(" $tail", true)
126+
.withPresentableText(text)
127+
)
128+
}
129+
130+
private fun valueCodeCompletion() {
131+
val text = position.text.replace("`", "")
132+
val textArr = text.split(CompletionUtilCore.DUMMY_IDENTIFIER)
133+
val prefix = textArr[0]
134+
135+
val patten = "\\w+(?=:\")"
136+
val regex = patten.toRegex()
137+
val keyList = regex.findAll(prefix)
138+
val current = keyList.last().value
139+
val tagValue = valueObject[current] ?: return
140+
val list = tagValue.list
141+
val separator = tagValue.separator
142+
143+
var valueStartIndex = prefix.lastIndexOf(separator)
144+
if (valueStartIndex == -1) {
145+
valueStartIndex = prefix.lastIndexOf("\"")
128146
}
129-
return ""
147+
val valuePrefixOfTag = prefix.substring(valueStartIndex + 1).lowercase()
148+
149+
for ((k, v) in list) {
150+
if (k.startsWith(valuePrefixOfTag)) {
151+
valueAddElement(prefix + k.removePrefix(valuePrefixOfTag), k, v)
152+
}
153+
}
154+
}
155+
156+
// add tag value element
157+
private fun valueAddElement(lookupString: String, text: String, tail: String = "") {
158+
result.addElement(
159+
LookupElementBuilder.create(lookupString)
160+
.withIcon(Gf.icon)
161+
.withTailText(" $tail", true)
162+
.withPresentableText(text)
163+
)
130164
}
131165
}

0 commit comments

Comments
 (0)