fix: 语法问题
This commit is contained in:
@@ -2,11 +2,7 @@ package me.zhouxi.slint.completion
|
|||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionContributor
|
import com.intellij.codeInsight.completion.CompletionContributor
|
||||||
import com.intellij.codeInsight.completion.CompletionParameters
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
import com.intellij.codeInsight.completion.CompletionProvider
|
|
||||||
import com.intellij.codeInsight.completion.CompletionType
|
import com.intellij.codeInsight.completion.CompletionType
|
||||||
import com.intellij.openapi.util.Pair
|
|
||||||
import com.intellij.patterns.ElementPattern
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import me.zhouxi.slint.completion.provider.*
|
import me.zhouxi.slint.completion.provider.*
|
||||||
|
|
||||||
class SlintCompletionContributor : CompletionContributor() {
|
class SlintCompletionContributor : CompletionContributor() {
|
||||||
@@ -14,8 +10,8 @@ class SlintCompletionContributor : CompletionContributor() {
|
|||||||
extend(TopKeywordProvider)
|
extend(TopKeywordProvider)
|
||||||
extend(BasicTypeProvider)
|
extend(BasicTypeProvider)
|
||||||
extend(AtChildrenCompletionProvider)
|
extend(AtChildrenCompletionProvider)
|
||||||
extend(ElementKeywordProvider)
|
extend(ComponentElementKeywordProvider)
|
||||||
extend(ComponentProvider)
|
extend(ComponentNameProvider)
|
||||||
extend(PropertyBindingProvider)
|
extend(PropertyBindingProvider)
|
||||||
extend(InheritsCompletionProvider)
|
extend(InheritsCompletionProvider)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,31 @@
|
|||||||
package me.zhouxi.slint.completion.provider
|
package me.zhouxi.slint.completion.provider
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionParameters
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
import com.intellij.codeInsight.completion.CompletionProvider
|
import com.intellij.codeInsight.completion.CompletionResultSet
|
||||||
import com.intellij.codeInsight.completion.CompletionResultSet
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.patterns.ElementPattern
|
||||||
import com.intellij.patterns.ElementPattern
|
import com.intellij.patterns.PlatformPatterns.psiElement
|
||||||
import com.intellij.patterns.PlatformPatterns.psiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.util.ProcessingContext
|
||||||
import com.intellij.util.ProcessingContext
|
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
||||||
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
|
||||||
|
object ComponentElementKeywordProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
object ElementKeywordProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
override fun addCompletions(
|
||||||
override fun addCompletions(
|
parameters: CompletionParameters,
|
||||||
parameters: CompletionParameters,
|
context: ProcessingContext,
|
||||||
context: ProcessingContext,
|
result: CompletionResultSet
|
||||||
result: CompletionResultSet
|
) {
|
||||||
) {
|
result.addAllElements(elementKeywords)
|
||||||
result.addAllElements(elementKeywords)
|
}
|
||||||
}
|
|
||||||
|
private val elementKeywords = arrayOf(
|
||||||
private val elementKeywords = arrayOf(
|
"in", "out", "in-out", "callback",
|
||||||
"in", "out", "in-out", "callback",
|
"property", "private", "changed",
|
||||||
"property", "private", "changed",
|
"states", "transitions", "function"
|
||||||
"states", "transitions", "function"
|
).map { LookupElementBuilder.create(it) }
|
||||||
).map { LookupElementBuilder.create(it) }
|
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
override fun pattern(): ElementPattern<out PsiElement> {
|
return psiElement().withParent(psiElement(Component))
|
||||||
return psiElement().withParent(psiElement(Component))
|
.andNot(AtChildrenCompletionProvider.pattern())
|
||||||
.andNot(AtChildrenCompletionProvider.pattern())
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,125 +1,124 @@
|
|||||||
package me.zhouxi.slint.completion.provider
|
package me.zhouxi.slint.completion.provider
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.*
|
import com.intellij.codeInsight.completion.*
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
import com.intellij.codeInsight.lookup.LookupElementDecorator.withInsertHandler
|
import com.intellij.codeInsight.lookup.LookupElementDecorator.withInsertHandler
|
||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.openapi.vfs.VfsUtil
|
import com.intellij.openapi.vfs.VfsUtil
|
||||||
import com.intellij.patterns.ElementPattern
|
import com.intellij.patterns.ElementPattern
|
||||||
import com.intellij.patterns.PlatformPatterns.psiElement
|
import com.intellij.patterns.PlatformPatterns.psiElement
|
||||||
import com.intellij.patterns.StandardPatterns.or
|
import com.intellij.patterns.StandardPatterns.or
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import com.intellij.psi.search.GlobalSearchScope.projectScope
|
import com.intellij.psi.search.GlobalSearchScope.projectScope
|
||||||
import com.intellij.psi.stubs.StubIndex
|
import com.intellij.psi.stubs.StubIndex
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
import com.intellij.psi.util.childrenOfType
|
import com.intellij.psi.util.childrenOfType
|
||||||
import com.intellij.psi.util.parentOfType
|
import com.intellij.util.ProcessingContext
|
||||||
import com.intellij.util.ProcessingContext
|
import me.zhouxi.slint.lang.createComma
|
||||||
import me.zhouxi.slint.lang.createComma
|
import me.zhouxi.slint.lang.createImport
|
||||||
import me.zhouxi.slint.lang.createImport
|
import me.zhouxi.slint.lang.createImportSpecifier
|
||||||
import me.zhouxi.slint.lang.createImportSpecifier
|
import me.zhouxi.slint.lang.psi.SlintComponent
|
||||||
import me.zhouxi.slint.lang.psi.SlintComponent
|
import me.zhouxi.slint.lang.psi.SlintImport
|
||||||
import me.zhouxi.slint.lang.psi.SlintImport
|
import me.zhouxi.slint.lang.psi.SlintInheritDeclaration
|
||||||
import me.zhouxi.slint.lang.psi.SlintInheritDeclaration
|
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
||||||
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
import me.zhouxi.slint.lang.psi.SlintTypes.InheritDeclaration
|
||||||
import me.zhouxi.slint.lang.psi.SlintTypes.InheritDeclaration
|
import me.zhouxi.slint.lang.psi.extension.importNames
|
||||||
import me.zhouxi.slint.lang.psi.extension.importNames
|
import me.zhouxi.slint.lang.psi.stubs.index.StubIndexKeys
|
||||||
import me.zhouxi.slint.lang.psi.stubs.index.StubIndexKeys
|
|
||||||
|
object ComponentNameProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
object ComponentProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
override fun addCompletions(
|
||||||
override fun addCompletions(
|
parameters: CompletionParameters,
|
||||||
parameters: CompletionParameters,
|
context: ProcessingContext,
|
||||||
context: ProcessingContext,
|
result: CompletionResultSet
|
||||||
result: CompletionResultSet
|
) {
|
||||||
) {
|
val project = parameters.position.project
|
||||||
val project = parameters.position.project
|
val components = arrayListOf<SlintComponent>()
|
||||||
val components = arrayListOf<SlintComponent>()
|
StubIndex.getInstance().processAllKeys(StubIndexKeys.Component, project) {
|
||||||
StubIndex.getInstance().processAllKeys(StubIndexKeys.Component, project) {
|
if (result.prefixMatcher.prefixMatches(it)) {
|
||||||
if (result.prefixMatcher.prefixMatches(it)) {
|
val elements = StubIndex.getElements(
|
||||||
val elements = StubIndex.getElements(
|
StubIndexKeys.Component,
|
||||||
StubIndexKeys.Component,
|
it,
|
||||||
it,
|
project,
|
||||||
project,
|
projectScope(project),
|
||||||
projectScope(project),
|
SlintComponent::class.java
|
||||||
SlintComponent::class.java
|
)
|
||||||
)
|
components.addAll(elements)
|
||||||
components.addAll(elements)
|
}
|
||||||
}
|
true
|
||||||
true
|
}
|
||||||
}
|
val lookups = components.map {
|
||||||
val lookups = components.map {
|
val targetFile = it.containingFile.originalFile
|
||||||
val targetFile = it.containingFile.originalFile
|
val currentFile = parameters.position.containingFile.originalFile.virtualFile
|
||||||
val currentFile = parameters.position.containingFile.originalFile.virtualFile
|
val path = VfsUtil.findRelativePath(currentFile, targetFile.virtualFile, '/')
|
||||||
val path = VfsUtil.findRelativePath(currentFile, targetFile.virtualFile, '/')
|
val builder = LookupElementBuilder.create(it).withTypeText(path).withIcon(AllIcons.Nodes.Class)
|
||||||
val builder = LookupElementBuilder.create(it).withTypeText(path).withIcon(AllIcons.Nodes.Class)
|
withInsertHandler(builder, ComponentInsertHandler(targetFile, path))
|
||||||
withInsertHandler(builder, ComponentInsertHandler(targetFile, path))
|
}
|
||||||
}
|
result.addAllElements(lookups)
|
||||||
result.addAllElements(lookups)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
class ComponentInsertHandler(
|
||||||
class ComponentInsertHandler(
|
private val targetFile: PsiFile,
|
||||||
private val targetFile: PsiFile,
|
private val path: String?
|
||||||
private val path: String?
|
) : InsertHandler<LookupElement> {
|
||||||
) : InsertHandler<LookupElement> {
|
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||||
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
//insert '{}'
|
||||||
//insert '{}'
|
val caretOffset: Int = context.editor.caretModel.offset
|
||||||
val caretOffset: Int = context.editor.caretModel.offset
|
val elementAt = context.file.findElementAt(caretOffset)
|
||||||
val elementAt = context.file.findElementAt(caretOffset)
|
if (elementAt?.prevSibling !is SlintInheritDeclaration) {
|
||||||
if (elementAt?.prevSibling !is SlintInheritDeclaration) {
|
context.document.insertString(caretOffset, " { }")
|
||||||
context.document.insertString(caretOffset, "{}")
|
context.editor.caretModel.moveToOffset(caretOffset + 3)
|
||||||
context.editor.caretModel.moveToOffset(caretOffset + 1)
|
PsiDocumentManager.getInstance(context.project).commitDocument(context.document)
|
||||||
PsiDocumentManager.getInstance(context.project).commitDocument(context.document)
|
}
|
||||||
}
|
val component = item.psiElement as SlintComponent
|
||||||
val component = item.psiElement as SlintComponent
|
if (component.containingFile.isEquivalentTo(context.file)) {
|
||||||
if (component.containingFile.isEquivalentTo(context.file)) {
|
return
|
||||||
return
|
}
|
||||||
}
|
val targetImport = context.file.childrenOfType<SlintImport>().find { import ->
|
||||||
val targetImport = context.file.childrenOfType<SlintImport>().find { import ->
|
val target = import.importElement?.moduleLocation?.reference?.resolve()
|
||||||
val target = import.importElement?.moduleLocation?.reference?.resolve()
|
PsiManager.getInstance(context.project).areElementsEquivalent(target, targetFile)
|
||||||
PsiManager.getInstance(context.project).areElementsEquivalent(target, targetFile)
|
}
|
||||||
}
|
if (targetImport == null) {
|
||||||
if (targetImport == null) {
|
//不存在对指定文件的Import,插入
|
||||||
//不存在对指定文件的Import,插入
|
val import = createImport(context.project, component.componentName!!.text, path!!)
|
||||||
val import = createImport(context.project, component.componentName!!.text, path!!)
|
context.file.addBefore(import, context.file.firstChild)
|
||||||
context.file.addBefore(import, context.file.firstChild)
|
return
|
||||||
return
|
}
|
||||||
}
|
//如果导入的Name里面包含了这个ComponentName
|
||||||
//如果导入的Name里面包含了这个ComponentName
|
if (targetImport.importNames().any { it.textMatches(component.componentName!!) }) {
|
||||||
if (targetImport.importNames().any { it.textMatches(component.componentName!!) }) {
|
return
|
||||||
return
|
}
|
||||||
}
|
//引入的文件存在,但是没有导入对应组件
|
||||||
//引入的文件存在,但是没有导入对应组件
|
val importElement = targetImport.importElement!!
|
||||||
val importElement = targetImport.importElement!!
|
val specifier = createImportSpecifier(context.project, component.componentName!!.text)
|
||||||
val specifier = createImportSpecifier(context.project, component.componentName!!.text)
|
val last = importElement.importSpecifierList.lastOrNull()
|
||||||
val last = importElement.importSpecifierList.lastOrNull()
|
//不存在前置节点
|
||||||
//不存在前置节点
|
if (last == null) {
|
||||||
if (last == null) {
|
importElement.addAfter(specifier, importElement.childrenOfType<LeafPsiElement>()[0])
|
||||||
importElement.addAfter(specifier, importElement.childrenOfType<LeafPsiElement>()[0])
|
PsiDocumentManager.getInstance(context.project).commitDocument(context.document)
|
||||||
PsiDocumentManager.getInstance(context.project).commitDocument(context.document)
|
return
|
||||||
return
|
}
|
||||||
}
|
val element = PsiTreeUtil.nextVisibleLeaf(last)
|
||||||
val element = PsiTreeUtil.nextVisibleLeaf(last)
|
if (!element!!.textMatches(",")) {
|
||||||
if (!element!!.textMatches(",")) {
|
val comma = importElement.addAfter(createComma(context.project), last)
|
||||||
val comma = importElement.addAfter(createComma(context.project), last)
|
importElement.addAfter(specifier, comma)
|
||||||
importElement.addAfter(specifier, comma)
|
PsiDocumentManager.getInstance(context.project).commitDocument(context.document)
|
||||||
PsiDocumentManager.getInstance(context.project).commitDocument(context.document)
|
return
|
||||||
return
|
}
|
||||||
}
|
PsiDocumentManager.getInstance(context.project).commitDocument(context.document)
|
||||||
PsiDocumentManager.getInstance(context.project).commitDocument(context.document)
|
importElement.addAfter(specifier, element)
|
||||||
importElement.addAfter(specifier, element)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
override fun pattern(): ElementPattern<out PsiElement> {
|
return or(
|
||||||
return or(
|
psiElement().withParent(psiElement(Component)).andNot(AtChildrenCompletionProvider.pattern()),
|
||||||
psiElement().withParent(psiElement(Component)).andNot(AtChildrenCompletionProvider.pattern()),
|
psiElement().withSuperParent(2, psiElement(InheritDeclaration))
|
||||||
psiElement().withSuperParent(2, psiElement(InheritDeclaration))
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -2,11 +2,20 @@ package me.zhouxi.slint.completion.provider
|
|||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionParameters
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
import com.intellij.codeInsight.completion.CompletionResultSet
|
import com.intellij.codeInsight.completion.CompletionResultSet
|
||||||
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
import com.intellij.codeInsight.completion.InsertHandler
|
||||||
|
import com.intellij.codeInsight.completion.InsertionContext
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder.*
|
||||||
|
import com.intellij.codeInsight.template.Template
|
||||||
|
import com.intellij.codeInsight.template.TemplateEditingAdapter
|
||||||
|
import com.intellij.codeInsight.template.TemplateManager
|
||||||
|
import com.intellij.codeInsight.template.impl.ConstantNode
|
||||||
|
import com.intellij.icons.AllIcons
|
||||||
import com.intellij.patterns.ElementPattern
|
import com.intellij.patterns.ElementPattern
|
||||||
import com.intellij.patterns.PlatformPatterns.psiElement
|
import com.intellij.patterns.PlatformPatterns.psiElement
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
||||||
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
|
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
|
||||||
|
|
||||||
object TopKeywordProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
object TopKeywordProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
@@ -15,13 +24,42 @@ object TopKeywordProvider : AbstractSlintCompletionProvider<CompletionParameters
|
|||||||
context: ProcessingContext,
|
context: ProcessingContext,
|
||||||
result: CompletionResultSet
|
result: CompletionResultSet
|
||||||
) {
|
) {
|
||||||
result.addAllElements(topKeywords)
|
result.addAllElements(completion)
|
||||||
|
result.addElement(create("component"))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val topKeywords =
|
val completion = arrayListOf(create("component "), create("struct "), create("enum "))
|
||||||
arrayOf("export", "component", "global", "enum", "struct").map { LookupElementBuilder.create(it) }
|
.flatMap {
|
||||||
|
arrayListOf(
|
||||||
|
it,
|
||||||
|
it.withPresentableText(it.lookupString)
|
||||||
|
.withTailText("\$Name$ {...}")
|
||||||
|
.withInsertHandler(MyInsertHandler()),
|
||||||
|
create("export ${it.lookupString}"),
|
||||||
|
create("export ${it.lookupString}")
|
||||||
|
.withTailText("\$Name$ {...}")
|
||||||
|
.withInsertHandler(MyInsertHandler()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun pattern(): ElementPattern<out PsiElement> {
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
return psiElement().withSuperParent(1, psiElement(SlintFileElementType))
|
return psiElement().withSuperParent(2, psiElement(SlintFileElementType))
|
||||||
|
.andNot(psiElement().withParent(psiElement(Component)))
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyInsertHandler : InsertHandler<LookupElement> {
|
||||||
|
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||||
|
val manager = TemplateManager.getInstance(context.project)
|
||||||
|
val template = manager.createTemplate("", "", " \$Name$ { \n }")
|
||||||
|
template.isToReformat = true
|
||||||
|
template.addVariable("Name", ConstantNode(""), true)
|
||||||
|
manager.startTemplate(context.editor, template, object : TemplateEditingAdapter() {
|
||||||
|
override fun templateFinished(template: Template, brokenOff: Boolean) {
|
||||||
|
context.editor.caretModel.moveToOffset(context.tailOffset - 2);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,10 +50,13 @@ object SlintComponentElementType :
|
|||||||
|
|
||||||
override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): SlintComponentStub {
|
override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): SlintComponentStub {
|
||||||
val exported = tree.getChildren(node).any { it.tokenType == ExportKeyword }
|
val exported = tree.getChildren(node).any { it.tokenType == ExportKeyword }
|
||||||
val identifier = tree.getChildren(node).first { it.tokenType == ComponentName }
|
val token = tree.getChildren(node).find { it.tokenType == ComponentName }
|
||||||
val token = tree.getChildren(identifier)[0] as LighterASTTokenNode
|
?.let {
|
||||||
|
val text = tree.getChildren(it)[0] as LighterASTTokenNode
|
||||||
|
tree.charTable.intern(text.text)
|
||||||
|
}
|
||||||
|
|
||||||
return SlintComponentStubImpl(parentStub, exported, tree.charTable.intern(token.text).toString())
|
return SlintComponentStubImpl(parentStub, exported, token.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun indexStub(stub: SlintComponentStub, sink: IndexSink) {
|
override fun indexStub(stub: SlintComponentStub, sink: IndexSink) {
|
||||||
|
|||||||
Reference in New Issue
Block a user