Skip to content

Commit 14916c1

Browse files
committed
working
1 parent fd426c4 commit 14916c1

File tree

6 files changed

+248
-82
lines changed

6 files changed

+248
-82
lines changed

src/main/kotlin/org/tabooproject/development/Utils.kt

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
package org.tabooproject.development
22

3-
import com.intellij.psi.PsiDirectory
4-
import com.intellij.psi.PsiElement
5-
import com.intellij.psi.PsiFile
6-
import com.intellij.psi.PsiReference
3+
import com.intellij.openapi.module.ModuleUtilCore
4+
import com.intellij.openapi.roots.OrderEnumerator
5+
import com.intellij.psi.*
6+
import com.intellij.psi.util.PsiTreeUtil
77
import okhttp3.OkHttpClient
88
import okhttp3.Request
9+
import org.jetbrains.kotlin.descriptors.ClassDescriptor
10+
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
911
import org.jetbrains.kotlin.psi.KtAnnotated
12+
import org.jetbrains.kotlin.psi.KtCallExpression
13+
import org.jetbrains.kotlin.psi.KtFile
14+
import org.jetbrains.kotlin.psi.KtImportDirective
15+
import org.jetbrains.kotlin.resolve.BindingContext
16+
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
17+
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
18+
import org.jetbrains.kotlin.utils.IDEAPluginsCompatibilityAPI
1019
import java.io.IOException
1120
import java.net.InetSocketAddress
1221
import java.net.Proxy
@@ -89,4 +98,15 @@ fun readFromUrl(url: String): String? {
8998
.takeIf { it.isSuccessful } ?: throw IOException("Failed to get $url")
9099

91100
return response.body?.string()
101+
}
102+
103+
fun PsiClass.getContainingPackageName(): String? {
104+
val containingPackage = containingClass
105+
return containingPackage?.qualifiedName
106+
}
107+
108+
private fun isPackageInProject(file: PsiFile, packageName: String): Boolean {
109+
val module = ModuleUtilCore.findModuleForPsiElement(file) ?: return false
110+
val orderEnumerator = OrderEnumerator.orderEntries(module).recursively().librariesOnly().classes()
111+
return orderEnumerator.urls.any { it.contains(packageName.replace('.', '/')) }
92112
}

src/main/kotlin/org/tabooproject/development/completion/InfoFuncCompletion.kt

Lines changed: 0 additions & 77 deletions
This file was deleted.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package org.tabooproject.development.completion
2+
3+
import com.intellij.codeInsight.completion.*
4+
import com.intellij.codeInsight.lookup.AutoCompletionPolicy
5+
import com.intellij.codeInsight.lookup.LookupElementBuilder
6+
import com.intellij.openapi.project.Project
7+
import com.intellij.patterns.PlatformPatterns
8+
import com.intellij.patterns.PsiJavaPatterns
9+
import com.intellij.psi.*
10+
import com.intellij.psi.search.FilenameIndex
11+
import com.intellij.psi.search.GlobalSearchScope
12+
import com.intellij.psi.search.SearchScope
13+
import com.intellij.psi.util.PsiTreeUtil
14+
import com.intellij.util.ProcessingContext
15+
import org.jetbrains.kotlin.descriptors.ClassDescriptor
16+
import org.jetbrains.kotlin.idea.caches.resolve.analyze
17+
import org.jetbrains.kotlin.psi.*
18+
import org.jetbrains.kotlin.resolve.BindingContext
19+
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
20+
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
21+
22+
class InvokeMethodReflectCompletion: CompletionContributor() {
23+
24+
init {
25+
extend(
26+
null,
27+
PlatformPatterns.psiElement().inside(KtLiteralStringTemplateEntry::class.java),
28+
InvokeMethodReflectCompletionProvider()
29+
)
30+
}
31+
}
32+
33+
class InvokeMethodReflectCompletionProvider : CompletionProvider<CompletionParameters>() {
34+
override fun addCompletions(
35+
parameters: CompletionParameters,
36+
context: ProcessingContext,
37+
result: CompletionResultSet
38+
) {
39+
40+
val element = parameters.position
41+
val parent = element.parent
42+
43+
if (parent is KtLiteralStringTemplateEntry) {
44+
val currentElement: KtCallExpression = PsiTreeUtil.findFirstParent(parent) {
45+
it is KtCallExpression
46+
} as? KtCallExpression ?: return
47+
48+
val calleeExpression = currentElement.calleeExpression
49+
val calleeText = calleeExpression?.text
50+
51+
var testEle: PsiElement = calleeExpression!!
52+
while (true) {
53+
testEle = testEle.parent ?: break
54+
println(testEle::class.java.name)
55+
println(testEle.text)
56+
}
57+
58+
if (calleeText == "invokeMethod") {
59+
val qualifiedExpression = PsiTreeUtil.findFirstParent(calleeExpression) {
60+
it is KtDotQualifiedExpression
61+
} as? KtDotQualifiedExpression
62+
val receiverExpression = qualifiedExpression?.receiverExpression
63+
val bindingContext = receiverExpression?.analyze(BodyResolveMode.PARTIAL)
64+
val type = bindingContext?.get(BindingContext.EXPRESSION_TYPE_INFO, receiverExpression)?.type
65+
val classDescriptor = type?.constructor?.declarationDescriptor as? ClassDescriptor
66+
val fqName = classDescriptor?.fqNameSafe?.asString() ?: return
67+
68+
val clazz = JavaPsiFacade.getInstance(calleeExpression.project)
69+
.findClass(fqName, GlobalSearchScope.allScope(calleeExpression.project)) ?: run {
70+
return
71+
}
72+
73+
val methods = HashSet<String>()
74+
clazz.findMethods(methods)
75+
methods.forEach { method ->
76+
result.addElement(LookupElementBuilder.create(method))
77+
}
78+
}
79+
}
80+
}
81+
82+
private fun PsiClass.findMethods(methods: MutableSet<String>): MutableSet<String> {
83+
this.methods.forEach { methods += it.name }
84+
this.interfaces.forEach { interfaceClass ->
85+
interfaceClass.findMethods(methods)
86+
}
87+
this.supers.forEach { superClass ->
88+
superClass.findMethods(methods)
89+
}
90+
91+
return methods
92+
}
93+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package org.tabooproject.development.completion
2+
3+
import com.intellij.codeInsight.completion.*
4+
import com.intellij.codeInsight.lookup.LookupElementBuilder
5+
import com.intellij.lang.java.JavaLanguage
6+
import com.intellij.psi.PsiDocumentManager
7+
import com.intellij.psi.util.PsiTreeUtil
8+
import com.intellij.psi.util.PsiUtilCore
9+
import com.intellij.util.PlatformIcons
10+
import org.jetbrains.kotlin.idea.KotlinLanguage
11+
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
12+
import org.jetbrains.kotlin.psi.KtFile
13+
import org.jetbrains.kotlin.psi.KtImportDirective
14+
import org.jetbrains.kotlin.psi.KtPsiFactory
15+
import org.jetbrains.kotlin.resolve.ImportPath
16+
17+
18+
class LogFuncCompletion: CompletionContributor() {
19+
20+
override fun fillCompletionVariants(parameters: CompletionParameters, result: CompletionResultSet) {
21+
if (parameters.completionType != CompletionType.BASIC) {
22+
return
23+
}
24+
25+
val position = parameters.position
26+
27+
if (!PsiUtilCore.findLanguageFromElement(position).isKindOf(KotlinLanguage.INSTANCE)) {
28+
return
29+
}
30+
31+
// 确保前面是个对象, 否则不提供打印
32+
(position.parent.parent as? KtDotQualifiedExpression)?.receiverExpression ?: return
33+
34+
// 添加日志助手
35+
result.addElement(
36+
PrioritizedLookupElement.withPriority(
37+
generate("info", "打印日志"),
38+
-1000.0,
39+
),
40+
)
41+
result.addElement(
42+
PrioritizedLookupElement.withPriority(
43+
generate("warning", "打印警告日志"),
44+
-1001.0,
45+
),
46+
)
47+
result.addElement(
48+
PrioritizedLookupElement.withPriority(
49+
generate("severe", "打印错误日志"),
50+
-1002.0,
51+
),
52+
)
53+
}
54+
55+
private fun generate(name: String, description: String): LookupElementBuilder {
56+
return LookupElementBuilder.create(name)
57+
.withIcon(PlatformIcons.METHOD_ICON)
58+
.withTailText(" $description ", true)
59+
.withInsertHandler handler@{ context, _ ->
60+
val editor = context.editor
61+
val startOffset = context.startOffset
62+
val tailOffset = context.tailOffset
63+
val element = context.file.findElementAt(startOffset)
64+
if (element != null) {
65+
val parent = element.parent.parent
66+
67+
val ktFile = element.containingFile as? KtFile ?: return@handler
68+
69+
if (parent != null) {
70+
try {
71+
val objectText = parent.text.let {
72+
val index = it.indexOfLast { c -> c == '.' }
73+
it.substring(0, index)
74+
}
75+
context.document.replaceString(
76+
parent.textRange.startOffset,
77+
tailOffset,
78+
"info($objectText)"
79+
)
80+
editor.caretModel
81+
.moveToOffset(parent.textRange.startOffset + 5 + objectText.length)
82+
83+
PsiDocumentManager.getInstance(element.project).commitDocument(context.document)
84+
} catch (e: Exception) {
85+
e.printStackTrace()
86+
}
87+
88+
// 检查和引入info包
89+
val import =
90+
PsiTreeUtil.findChildrenOfType(ktFile, KtImportDirective::class.java)
91+
val hasImport =
92+
import.any { it.importPath?.pathStr == "taboolib.common.platform.function.${name}" }
93+
if (!hasImport) {
94+
val factory = KtPsiFactory(context.project)
95+
val importDirective =
96+
factory.createImportDirective(ImportPath.fromString("taboolib.common.platform.function.${name}"))
97+
ktFile.importList?.add(importDirective)
98+
}
99+
}
100+
}
101+
}
102+
}
103+
104+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.tabooproject.development.completion
2+
3+
import com.intellij.codeInsight.completion.CompletionConfidence
4+
import com.intellij.codeInsight.completion.SkipAutopopupInStrings
5+
import com.intellij.psi.PsiElement
6+
import com.intellij.psi.PsiFile
7+
import com.intellij.util.ThreeState
8+
import org.jetbrains.kotlin.idea.intentions.loopToCallChain.sequence.CompositeCondition
9+
10+
class TabooLiteralConfidence: CompletionConfidence() {
11+
12+
override fun shouldSkipAutopopup(contextElement: PsiElement, psiFile: PsiFile, offset: Int): ThreeState {
13+
return if (SkipAutopopupInStrings.isInStringLiteral(contextElement)) {
14+
ThreeState.NO
15+
} else {
16+
ThreeState.UNSURE
17+
}
18+
}
19+
20+
}

src/main/resources/META-INF/plugin.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@
3636
implementationClass="org.tabooproject.development.inspection.DatabaseWorkspaceInspection"/>
3737

3838
<completion.contributor language="kotlin"
39-
implementationClass="org.tabooproject.development.completion.InfoFuncCompletion"/>
39+
implementationClass="org.tabooproject.development.completion.LogFuncCompletion"/>
40+
<completion.contributor language="kotlin"
41+
implementationClass="org.tabooproject.development.completion.InvokeMethodReflectCompletion"
42+
/>
43+
<completion.confidence language="kotlin"
44+
implementationClass="org.tabooproject.development.completion.TabooLiteralConfidence"
45+
order="before kotlinSkipAutopopupInStrings"/>
4046
</extensions>
4147

4248
<resource-bundle/>

0 commit comments

Comments
 (0)