fix: 语法问题
This commit is contained in:
@@ -38,7 +38,7 @@ repositories {
|
|||||||
intellij {
|
intellij {
|
||||||
version.set("IC-2023.2.5")
|
version.set("IC-2023.2.5")
|
||||||
sandboxDir.set("idea-sandbox")
|
sandboxDir.set("idea-sandbox")
|
||||||
plugins.set(listOf("java"))
|
plugins.set(listOf("java","Kotlin"))
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly("org.projectlombok:lombok:1.18.32")
|
compileOnly("org.projectlombok:lombok:1.18.32")
|
||||||
|
|||||||
@@ -148,7 +148,9 @@ Component ::= ExportKeyword? ComponentKeyword ComponentName InheritDeclaration?
|
|||||||
//private LegacyComponent ::= (ComponentName|NamedIdentifier ':=' ) ComponentBody
|
//private LegacyComponent ::= (ComponentName|NamedIdentifier ':=' ) ComponentBody
|
||||||
InheritDeclaration ::= InheritsKeyword ReferenceIdentifier {
|
InheritDeclaration ::= InheritsKeyword ReferenceIdentifier {
|
||||||
pin=1
|
pin=1
|
||||||
|
recoverWhile=recoverInherit
|
||||||
}
|
}
|
||||||
|
private recoverInherit::=!('{')
|
||||||
//组件元素定义
|
//组件元素定义
|
||||||
private ComponentElement ::=ChildrenPlaceholder| Property | Callback
|
private ComponentElement ::=ChildrenPlaceholder| Property | Callback
|
||||||
| Function | PropertyAnimation | CallbackConnection | Transitions
|
| Function | PropertyAnimation | CallbackConnection | Transitions
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package me.zhouxi.slint.completion
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.AutoPopupController
|
||||||
|
import com.intellij.codeInsight.completion.CompletionPhase.EmptyAutoPopup
|
||||||
|
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl
|
||||||
|
import com.intellij.codeInsight.editorActions.TypedHandlerDelegate
|
||||||
|
import com.intellij.codeInsight.lookup.LookupManager
|
||||||
|
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
||||||
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.editor.EditorModificationUtil
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/29
|
||||||
|
*/
|
||||||
|
class SlintCompletionAutoPopupHandler : TypedHandlerDelegate() {
|
||||||
|
override fun checkAutoPopup(charTyped: Char, project: Project, editor: Editor, file: PsiFile): Result {
|
||||||
|
val lookup = LookupManager.getActiveLookup(editor) as LookupImpl?
|
||||||
|
|
||||||
|
val phase = CompletionServiceImpl.getCompletionPhase()
|
||||||
|
if (LOG.isDebugEnabled) {
|
||||||
|
LOG.debug("checkAutoPopup: character=$charTyped;")
|
||||||
|
LOG.debug("phase=$phase")
|
||||||
|
LOG.debug("lookup=$lookup")
|
||||||
|
LOG.debug("currentCompletion=" + CompletionServiceImpl.getCompletionService().currentCompletion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lookup != null) {
|
||||||
|
if (editor.selectionModel.hasSelection()) {
|
||||||
|
lookup.performGuardedChange(Runnable { EditorModificationUtil.deleteSelectedText(editor) })
|
||||||
|
}
|
||||||
|
return Result.STOP
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Character.isLetterOrDigit(charTyped) || charTyped == '_' || charTyped == '@') {
|
||||||
|
if (phase is EmptyAutoPopup && phase.allowsSkippingNewAutoPopup(editor, charTyped)) {
|
||||||
|
return Result.CONTINUE
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoPopupController.getInstance(project).scheduleAutoPopup(editor)
|
||||||
|
return Result.STOP
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.CONTINUE
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOG = Logger.getInstance(
|
||||||
|
SlintCompletionAutoPopupHandler::class.java
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,47 +1,30 @@
|
|||||||
package me.zhouxi.slint.completion
|
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.CompletionProvider
|
||||||
import com.intellij.codeInsight.completion.CompletionType
|
import com.intellij.codeInsight.completion.CompletionType
|
||||||
import com.intellij.patterns.PlatformPatterns
|
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.*
|
||||||
import me.zhouxi.slint.lang.psi.SlintTypes
|
|
||||||
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
|
||||||
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
|
|
||||||
|
|
||||||
class SlintCompletionContributor : CompletionContributor() {
|
class SlintCompletionContributor : CompletionContributor() {
|
||||||
init {
|
init {
|
||||||
//文件级别
|
extend(TopKeywordProvider)
|
||||||
extend(
|
extend(BasicTypeProvider)
|
||||||
CompletionType.BASIC,
|
extend(AtChildrenCompletionProvider)
|
||||||
PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintFileElementType)),
|
extend(ElementKeywordProvider)
|
||||||
TopKeywordProvider
|
extend(ComponentProvider)
|
||||||
)
|
extend(PropertyBindingProvider)
|
||||||
|
extend(InheritsCompletionProvider)
|
||||||
|
}
|
||||||
|
|
||||||
//类型定义
|
private fun extend(
|
||||||
extend(
|
provider: AbstractSlintCompletionProvider<CompletionParameters>,
|
||||||
CompletionType.BASIC,
|
type: CompletionType = CompletionType.BASIC,
|
||||||
PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintTypes.Type)),
|
) {
|
||||||
BasicTypeProvider
|
extend(type, provider.pattern(), provider)
|
||||||
)
|
|
||||||
|
|
||||||
//componentBody
|
|
||||||
extend(
|
|
||||||
CompletionType.BASIC,
|
|
||||||
PlatformPatterns.psiElement().withAncestor(2, PlatformPatterns.psiElement(Component)),
|
|
||||||
ElementKeywordProvider
|
|
||||||
)
|
|
||||||
//componentBody
|
|
||||||
extend(
|
|
||||||
CompletionType.BASIC,
|
|
||||||
PlatformPatterns.psiElement().withAncestor(2,PlatformPatterns.psiElement(Component)),
|
|
||||||
ComponentProvider
|
|
||||||
)
|
|
||||||
//propertyBinding
|
|
||||||
extend(
|
|
||||||
CompletionType.BASIC,
|
|
||||||
PlatformPatterns.psiElement().withAncestor(2, PlatformPatterns.psiElement(Component)),
|
|
||||||
PropertyBindingProvider
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package me.zhouxi.slint.completion.provider
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
|
import com.intellij.codeInsight.completion.CompletionProvider
|
||||||
|
import com.intellij.patterns.ElementPattern
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/29
|
||||||
|
*/
|
||||||
|
abstract class AbstractSlintCompletionProvider<V : CompletionParameters?> : CompletionProvider<V>() {
|
||||||
|
|
||||||
|
abstract fun pattern(): ElementPattern<out PsiElement>
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package me.zhouxi.slint.completion.provider
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
|
import com.intellij.codeInsight.completion.CompletionResultSet
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
|
import com.intellij.icons.AllIcons
|
||||||
|
import com.intellij.patterns.ElementPattern
|
||||||
|
import com.intellij.patterns.PlatformPatterns.psiElement
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.util.ProcessingContext
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/29
|
||||||
|
*/
|
||||||
|
object AtChildrenCompletionProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
|
return psiElement()
|
||||||
|
.afterLeaf(psiElement().withText("@"))
|
||||||
|
.withParent(psiElement(Component))
|
||||||
|
}
|
||||||
|
|
||||||
|
val element = LookupElementBuilder.create("children").withIcon(AllIcons.Nodes.Annotationtype)
|
||||||
|
|
||||||
|
override fun addCompletions(
|
||||||
|
parameters: CompletionParameters,
|
||||||
|
context: ProcessingContext,
|
||||||
|
result: CompletionResultSet
|
||||||
|
) {
|
||||||
|
result.addElement(element)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
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.PlatformPatterns.psiElement
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
import me.zhouxi.slint.lang.psi.SlintPsiUtils.InternalTypes
|
import me.zhouxi.slint.lang.psi.SlintPsiUtils.InternalTypes
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.Type
|
||||||
|
|
||||||
object BasicTypeProvider : CompletionProvider<CompletionParameters>() {
|
object BasicTypeProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
override fun addCompletions(
|
override fun addCompletions(
|
||||||
parameters: CompletionParameters,
|
parameters: CompletionParameters,
|
||||||
context: ProcessingContext,
|
context: ProcessingContext,
|
||||||
@@ -17,4 +20,9 @@ object BasicTypeProvider : CompletionProvider<CompletionParameters>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val basicTypes = InternalTypes.map { LookupElementBuilder.create(it) }
|
private val basicTypes = InternalTypes.map { LookupElementBuilder.create(it) }
|
||||||
|
|
||||||
|
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
|
return psiElement().withAncestor(3, psiElement(Type))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,14 @@ 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
|
|
||||||
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.PlatformPatterns.psiElement
|
||||||
|
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.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
|
||||||
@@ -15,17 +18,20 @@ 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.parentOfTypes
|
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.SlintTypes.Component
|
||||||
|
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 ComponentProvider : CompletionProvider<CompletionParameters>() {
|
object ComponentProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
override fun addCompletions(
|
override fun addCompletions(
|
||||||
parameters: CompletionParameters,
|
parameters: CompletionParameters,
|
||||||
context: ProcessingContext,
|
context: ProcessingContext,
|
||||||
@@ -62,7 +68,18 @@ object ComponentProvider : CompletionProvider<CompletionParameters>() {
|
|||||||
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 '{}'
|
||||||
|
val caretOffset: Int = context.editor.caretModel.offset
|
||||||
|
val elementAt = context.file.findElementAt(caretOffset)
|
||||||
|
if (elementAt?.prevSibling !is SlintInheritDeclaration) {
|
||||||
|
context.document.insertString(caretOffset, "{}")
|
||||||
|
context.editor.caretModel.moveToOffset(caretOffset + 1)
|
||||||
|
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)) {
|
||||||
|
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)
|
||||||
@@ -98,4 +115,11 @@ object ComponentProvider : CompletionProvider<CompletionParameters>() {
|
|||||||
importElement.addAfter(specifier, element)
|
importElement.addAfter(specifier, element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
|
return or(
|
||||||
|
psiElement().withParent(psiElement(Component)).andNot(AtChildrenCompletionProvider.pattern()),
|
||||||
|
psiElement().withSuperParent(2, psiElement(InheritDeclaration))
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,13 @@ import com.intellij.codeInsight.completion.CompletionParameters
|
|||||||
import com.intellij.codeInsight.completion.CompletionProvider
|
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.PlatformPatterns.psiElement
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
||||||
|
|
||||||
object ElementKeywordProvider : CompletionProvider<CompletionParameters>() {
|
object ElementKeywordProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
override fun addCompletions(
|
override fun addCompletions(
|
||||||
parameters: CompletionParameters,
|
parameters: CompletionParameters,
|
||||||
context: ProcessingContext,
|
context: ProcessingContext,
|
||||||
@@ -18,6 +22,11 @@ object ElementKeywordProvider : CompletionProvider<CompletionParameters>() {
|
|||||||
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", "@children"
|
"states", "transitions", "function"
|
||||||
).map { LookupElementBuilder.create(it) }
|
).map { LookupElementBuilder.create(it) }
|
||||||
|
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
|
return psiElement().withParent(psiElement(Component))
|
||||||
|
.andNot(AtChildrenCompletionProvider.pattern())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package me.zhouxi.slint.completion.provider
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.completion.CompletionParameters
|
||||||
|
import com.intellij.codeInsight.completion.CompletionResultSet
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
|
import com.intellij.patterns.ElementPattern
|
||||||
|
import com.intellij.patterns.PlatformPatterns
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.util.ProcessingContext
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/29
|
||||||
|
*/
|
||||||
|
object InheritsCompletionProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
|
return PlatformPatterns.psiElement()
|
||||||
|
.afterLeaf(PlatformPatterns.psiElement().withParent(PlatformPatterns.psiElement(SlintTypes.ComponentName)))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun addCompletions(
|
||||||
|
parameters: CompletionParameters,
|
||||||
|
context: ProcessingContext,
|
||||||
|
result: CompletionResultSet
|
||||||
|
) {
|
||||||
|
result.addElement(LookupElementBuilder.create("inherits"))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,30 +5,36 @@ 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.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
|
import com.intellij.patterns.ElementPattern
|
||||||
|
import com.intellij.patterns.PlatformPatterns.psiElement
|
||||||
|
import com.intellij.patterns.StandardPatterns.or
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.util.parentOfType
|
import com.intellij.psi.util.parentOfType
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
import me.zhouxi.slint.lang.psi.SlintComponent
|
import me.zhouxi.slint.lang.psi.SlintComponent
|
||||||
import me.zhouxi.slint.lang.psi.SlintSubComponent
|
import me.zhouxi.slint.lang.psi.SlintSubComponent
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.Component
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.SubComponent
|
||||||
import me.zhouxi.slint.lang.psi.extension.inheritsProperties
|
import me.zhouxi.slint.lang.psi.extension.inheritsProperties
|
||||||
|
import me.zhouxi.slint.lang.psi.extension.resolve
|
||||||
|
import me.zhouxi.slint.lang.psi.extension.toLookupElement
|
||||||
|
|
||||||
object PropertyBindingProvider : CompletionProvider<CompletionParameters>() {
|
object PropertyBindingProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
override fun addCompletions(
|
override fun addCompletions(
|
||||||
parameters: CompletionParameters,
|
parameters: CompletionParameters,
|
||||||
context: ProcessingContext,
|
context: ProcessingContext,
|
||||||
result: CompletionResultSet
|
result: CompletionResultSet
|
||||||
) {
|
) {
|
||||||
val element = parameters.position
|
val element = parameters.position
|
||||||
val subComponent = element.parentOfType<SlintSubComponent>()
|
val component = element.parentOfType<SlintSubComponent>()?.resolve()
|
||||||
if (subComponent != null) {
|
?: element.parentOfType<SlintComponent>()
|
||||||
val component = subComponent.referenceIdentifier.reference?.resolve() as SlintComponent? ?: return
|
component?.let {
|
||||||
val builders = component.inheritsProperties()
|
result.addAllElements(it.inheritsProperties().map { it.toLookupElement() })
|
||||||
.map { LookupElementBuilder.create(it).withTypeText(component.name).withIcon(AllIcons.Nodes.Property) }
|
|
||||||
result.addAllElements(builders)
|
|
||||||
} else {
|
|
||||||
val component = element.parentOfType<SlintComponent>() ?: return
|
|
||||||
val builders = component.inheritsProperties()
|
|
||||||
.map { LookupElementBuilder.create(it).withTypeText(component.name).withIcon(AllIcons.Nodes.Property) }
|
|
||||||
result.addAllElements(builders)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
|
return psiElement().withParent(or(psiElement(Component), psiElement(SubComponent)))
|
||||||
|
.andNot(AtChildrenCompletionProvider.pattern())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
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.PlatformPatterns.psiElement
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
|
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
|
||||||
|
|
||||||
object TopKeywordProvider : CompletionProvider<CompletionParameters>() {
|
object TopKeywordProvider : AbstractSlintCompletionProvider<CompletionParameters>() {
|
||||||
override fun addCompletions(
|
override fun addCompletions(
|
||||||
parameters: CompletionParameters,
|
parameters: CompletionParameters,
|
||||||
context: ProcessingContext,
|
context: ProcessingContext,
|
||||||
@@ -17,4 +20,8 @@ object TopKeywordProvider : CompletionProvider<CompletionParameters>() {
|
|||||||
|
|
||||||
private val topKeywords =
|
private val topKeywords =
|
||||||
arrayOf("export", "component", "global", "enum", "struct").map { LookupElementBuilder.create(it) }
|
arrayOf("export", "component", "global", "enum", "struct").map { LookupElementBuilder.create(it) }
|
||||||
|
|
||||||
|
override fun pattern(): ElementPattern<out PsiElement> {
|
||||||
|
return psiElement().withSuperParent(1, psiElement(SlintFileElementType))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
79
src/main/kotlin/me/zhouxi/slint/formatter/FormattingBlock.kt
Normal file
79
src/main/kotlin/me/zhouxi/slint/formatter/FormattingBlock.kt
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package me.zhouxi.slint.formatter
|
||||||
|
|
||||||
|
import com.intellij.formatting.*
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.psi.TokenType
|
||||||
|
import com.intellij.psi.formatter.common.AbstractBlock
|
||||||
|
import com.intellij.psi.tree.TokenSet
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.*
|
||||||
|
import me.zhouxi.slint.lang.psi.utils.braces
|
||||||
|
import me.zhouxi.slint.lang.psi.utils.expressions
|
||||||
|
import me.zhouxi.slint.lang.psi.utils.keywords
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/28
|
||||||
|
*/
|
||||||
|
class FormattingBlock(
|
||||||
|
node: ASTNode,
|
||||||
|
wrap: Wrap?,
|
||||||
|
alignment: Alignment?,
|
||||||
|
private val indent: Indent?,
|
||||||
|
private val spacingBuilder: SpacingBuilder
|
||||||
|
) : AbstractBlock(node, wrap, alignment) {
|
||||||
|
override fun buildChildren(): List<Block> {
|
||||||
|
val childBlocks = arrayListOf<Block>()
|
||||||
|
val syntheticBlocks = arrayListOf<Block>()
|
||||||
|
var current = childBlocks
|
||||||
|
var myIndent: Indent? = indent
|
||||||
|
for (child in node.getChildren(null)) {
|
||||||
|
if (braces.contains(child.elementType) && (node.elementType == SubComponent || node.elementType == Component)) {
|
||||||
|
current = syntheticBlocks
|
||||||
|
myIndent = Indent.getNormalIndent()
|
||||||
|
}
|
||||||
|
if (child.elementType == TokenType.WHITE_SPACE || child.textLength == 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (child.firstChildNode == null || leafTokens.contains(child.elementType)) {
|
||||||
|
current.add(LeafBlock(child, wrap, alignment, Indent.getNoneIndent(), spacingBuilder))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (expressions.contains(child.elementType)) {
|
||||||
|
current.add(FormattingBlock(child, wrap, alignment, null, spacingBuilder))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
current.add(FormattingBlock(child, wrap, alignment, myIndent, spacingBuilder))
|
||||||
|
}
|
||||||
|
if (syntheticBlocks.isNotEmpty()) {
|
||||||
|
childBlocks.add(SyntheticBlock(syntheticBlocks, wrap, Indent.getNormalIndent(), alignment, spacingBuilder))
|
||||||
|
}
|
||||||
|
return childBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIndent() = indent
|
||||||
|
|
||||||
|
override fun getSpacing(child1: Block?, child2: Block): Spacing? {
|
||||||
|
if (child2 is SyntheticBlock) {
|
||||||
|
return Spacing.createSpacing(1, 1, 0, true, 2)
|
||||||
|
}
|
||||||
|
return spacingBuilder.getSpacing(this, child1, child2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isLeaf(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val leafTokens =
|
||||||
|
TokenSet.orSet(
|
||||||
|
TokenSet.create(
|
||||||
|
ReferenceIdentifier,
|
||||||
|
ComponentName,
|
||||||
|
InternalName,
|
||||||
|
LocalVariable,
|
||||||
|
PropertyName
|
||||||
|
),
|
||||||
|
keywords
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/main/kotlin/me/zhouxi/slint/formatter/LeafBlock.kt
Normal file
55
src/main/kotlin/me/zhouxi/slint/formatter/LeafBlock.kt
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package me.zhouxi.slint.formatter
|
||||||
|
|
||||||
|
import com.intellij.formatting.*
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.psi.formatter.common.ExtraRangesProvider
|
||||||
|
import com.intellij.psi.formatter.common.NodeIndentRangesCalculator
|
||||||
|
|
||||||
|
class LeafBlock(
|
||||||
|
private val treeNode: ASTNode,
|
||||||
|
private val wrap: Wrap?,
|
||||||
|
private val alignment: Alignment?,
|
||||||
|
private val indent: Indent?,
|
||||||
|
private val spacingBuilder: SpacingBuilder
|
||||||
|
) : ASTBlock, ExtraRangesProvider {
|
||||||
|
|
||||||
|
|
||||||
|
override fun getNode() = treeNode
|
||||||
|
|
||||||
|
override fun getTextRange(): TextRange = treeNode.textRange
|
||||||
|
|
||||||
|
override fun getSubBlocks() = EMPTY_SUB_BLOCKS
|
||||||
|
|
||||||
|
override fun getWrap() = wrap
|
||||||
|
|
||||||
|
override fun getIndent() = indent
|
||||||
|
|
||||||
|
override fun getAlignment() = alignment
|
||||||
|
|
||||||
|
override fun getSpacing(child1: Block?, child2: Block) = null
|
||||||
|
|
||||||
|
override fun getChildAttributes(newChildIndex: Int) = ChildAttributes(indent, null)
|
||||||
|
|
||||||
|
override fun isIncomplete() = false
|
||||||
|
|
||||||
|
override fun isLeaf() = true
|
||||||
|
|
||||||
|
override fun getExtraRangesToFormat(info: FormattingRangesInfo): List<TextRange>? {
|
||||||
|
val startOffset = textRange.startOffset
|
||||||
|
if (info.isOnInsertedLine(startOffset) && treeNode.textLength == 1 && treeNode.textContains('}')) {
|
||||||
|
val parent = treeNode.treeParent
|
||||||
|
return NodeIndentRangesCalculator(parent).calculateExtraRanges()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return javaClass.simpleName + " '" + StringUtil.escapeLineBreak(node.text) + "' " + textRange
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val EMPTY_SUB_BLOCKS = ArrayList<Block>()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package me.zhouxi.slint.formatter
|
||||||
|
|
||||||
|
import com.intellij.formatting.*
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.codeStyle.CodeStyleSettings
|
||||||
|
import com.intellij.psi.tree.TokenSet
|
||||||
|
import me.zhouxi.slint.lang.SlintLanguage
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.*
|
||||||
|
import me.zhouxi.slint.lang.psi.utils.keywords
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/7
|
||||||
|
*/
|
||||||
|
class SlintFormatterModelBuilder : FormattingModelBuilder {
|
||||||
|
override fun createModel(formattingContext: FormattingContext): FormattingModel {
|
||||||
|
val element = formattingContext.psiElement
|
||||||
|
val spacingBuilder = createSpaceBuilder(formattingContext.codeStyleSettings)
|
||||||
|
val slintBlock = FormattingBlock(
|
||||||
|
formattingContext.node,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
Indent.getNoneIndent(),
|
||||||
|
spacingBuilder
|
||||||
|
)
|
||||||
|
return FormattingModelProvider.createFormattingModelForPsiFile(
|
||||||
|
element.containingFile,
|
||||||
|
slintBlock,
|
||||||
|
formattingContext.codeStyleSettings
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRangeAffectingIndent(file: PsiFile, offset: Int, elementAtOffset: ASTNode): TextRange? {
|
||||||
|
return file.textRange
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private fun createSpaceBuilder(settings: CodeStyleSettings): SpacingBuilder {
|
||||||
|
return SpacingBuilder(settings, SlintLanguage.INSTANCE)
|
||||||
|
.after(Comma)
|
||||||
|
.spaces(1)
|
||||||
|
.before(Comma)
|
||||||
|
.spaces(0)
|
||||||
|
.before(Semicolon)
|
||||||
|
.spacing(0, 0, 0, false, 0)
|
||||||
|
.after(Semicolon)
|
||||||
|
.lineBreakInCode()
|
||||||
|
.after(Colon)
|
||||||
|
.spaces(1)
|
||||||
|
.around(TokenSet.create(DoubleArrow, Plus, Minus, Star, Div))
|
||||||
|
.spaces(1)
|
||||||
|
.before(CodeBlock)
|
||||||
|
.spacing(1, 1, 0, true, 2)
|
||||||
|
.around(keywords)
|
||||||
|
.spaces(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,19 +20,19 @@ class SlintLineIndentProvider : JavaLikeLangLineIndentProvider() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val SyntaxMap: Map<IElementType, SyntaxElement> = java.util.Map.ofEntries<IElementType, SyntaxElement>(
|
val SyntaxMap: Map<IElementType, SyntaxElement> = mapOf(
|
||||||
java.util.Map.entry(SlintTypes.LBracket, JavaLikeElement.BlockOpeningBrace),
|
SlintTypes.LBracket to JavaLikeElement.BlockOpeningBrace,
|
||||||
java.util.Map.entry(SlintTypes.RBracket, JavaLikeElement.BlockClosingBrace),
|
SlintTypes.RBracket to JavaLikeElement.BlockClosingBrace,
|
||||||
java.util.Map.entry(SlintTypes.LBrace, JavaLikeElement.BlockOpeningBrace),
|
SlintTypes.LBrace to JavaLikeElement.BlockOpeningBrace,
|
||||||
java.util.Map.entry(SlintTypes.RBrace, JavaLikeElement.BlockClosingBrace),
|
SlintTypes.RBrace to JavaLikeElement.BlockClosingBrace,
|
||||||
java.util.Map.entry(TokenType.WHITE_SPACE, JavaLikeElement.Whitespace),
|
TokenType.WHITE_SPACE to JavaLikeElement.Whitespace,
|
||||||
java.util.Map.entry(SlintTypes.Semicolon, JavaLikeElement.Semicolon),
|
SlintTypes.Semicolon to JavaLikeElement.Semicolon,
|
||||||
java.util.Map.entry(SlintTypes.LineComment, JavaLikeElement.LineComment),
|
SlintTypes.LineComment to JavaLikeElement.LineComment,
|
||||||
java.util.Map.entry(SlintTypes.BlockComment, JavaLikeElement.BlockComment),
|
SlintTypes.BlockComment to JavaLikeElement.BlockComment,
|
||||||
java.util.Map.entry(SlintTypes.Colon, JavaLikeElement.Colon),
|
SlintTypes.Colon to JavaLikeElement.Colon,
|
||||||
java.util.Map.entry(SlintTypes.Comma, JavaLikeElement.Comma),
|
SlintTypes.Comma to JavaLikeElement.Comma,
|
||||||
java.util.Map.entry(SlintTypes.LParent, JavaLikeElement.LeftParenthesis),
|
SlintTypes.LParent to JavaLikeElement.LeftParenthesis,
|
||||||
java.util.Map.entry(SlintTypes.RParent, JavaLikeElement.RightParenthesis)
|
SlintTypes.RParent to JavaLikeElement.RightParenthesis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
52
src/main/kotlin/me/zhouxi/slint/formatter/SyntheticBlock.kt
Normal file
52
src/main/kotlin/me/zhouxi/slint/formatter/SyntheticBlock.kt
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package me.zhouxi.slint.formatter
|
||||||
|
|
||||||
|
import com.intellij.formatting.*
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.formatter.common.ExtraRangesProvider
|
||||||
|
import com.intellij.psi.formatter.common.NodeIndentRangesCalculator
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.LBrace
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes.RBrace
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/28
|
||||||
|
*/
|
||||||
|
class SyntheticBlock(
|
||||||
|
private val subBlocks: List<Block>,
|
||||||
|
private val wrap: Wrap?,
|
||||||
|
private val indent: Indent,
|
||||||
|
private val alignment: Alignment?,
|
||||||
|
private val spacingBuilder: SpacingBuilder
|
||||||
|
) : Block {
|
||||||
|
override fun getTextRange(): TextRange {
|
||||||
|
return TextRange(subBlocks.first().textRange.startOffset, subBlocks.last().textRange.endOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSubBlocks(): List<Block> {
|
||||||
|
return subBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getWrap() = wrap
|
||||||
|
|
||||||
|
override fun getIndent() = indent
|
||||||
|
|
||||||
|
override fun getAlignment() = alignment
|
||||||
|
|
||||||
|
override fun getSpacing(child1: Block?, child2: Block): Spacing? {
|
||||||
|
if (child2 is ASTBlock && child2.node!!.elementType == SlintTypes.Semicolon) {
|
||||||
|
return Spacing.createSpacing(1, 1, 0, true, 2)
|
||||||
|
}
|
||||||
|
if (child1 is ASTBlock && child2 is ASTBlock
|
||||||
|
&& child1.node!!.elementType == LBrace && child2.node!!.elementType == RBrace
|
||||||
|
) {
|
||||||
|
return Spacing.createSpacing(1, 1, 0, false, 0)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getChildAttributes(newChildIndex: Int) = ChildAttributes(null, subBlocks[0].alignment)
|
||||||
|
|
||||||
|
override fun isIncomplete() = false
|
||||||
|
|
||||||
|
override fun isLeaf() = false
|
||||||
|
}
|
||||||
@@ -5,7 +5,9 @@ import com.intellij.openapi.editor.HighlighterColors
|
|||||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||||
|
|
||||||
object Definitions {
|
object Definitions {
|
||||||
@JvmField
|
val _Annotation =
|
||||||
|
TextAttributesKey.createTextAttributesKey("_Annotation", DefaultLanguageHighlighterColors.METADATA)
|
||||||
|
|
||||||
val _KeyWord: TextAttributesKey =
|
val _KeyWord: TextAttributesKey =
|
||||||
TextAttributesKey.createTextAttributesKey("_KeyWord", DefaultLanguageHighlighterColors.KEYWORD)
|
TextAttributesKey.createTextAttributesKey("_KeyWord", DefaultLanguageHighlighterColors.KEYWORD)
|
||||||
|
|
||||||
@@ -55,4 +57,6 @@ object Definitions {
|
|||||||
val SemiColon: Array<TextAttributesKey> = arrayOf(_SemiColon)
|
val SemiColon: Array<TextAttributesKey> = arrayOf(_SemiColon)
|
||||||
|
|
||||||
val Error: Array<TextAttributesKey> = arrayOf(_Error)
|
val Error: Array<TextAttributesKey> = arrayOf(_Error)
|
||||||
|
|
||||||
|
val Annotation: Array<TextAttributesKey> = arrayOf(_Annotation)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ import me.zhouxi.slint.lang.psi.keyword.SlintPsiKeywordIdentifier
|
|||||||
|
|
||||||
class KeywordHighlightAnnotator : Annotator {
|
class KeywordHighlightAnnotator : Annotator {
|
||||||
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
||||||
|
if (element is SlintChildrenPlaceholder) {
|
||||||
|
holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
|
||||||
|
.range(element)
|
||||||
|
.textAttributes(Definitions._Annotation)
|
||||||
|
.create()
|
||||||
|
return
|
||||||
|
}
|
||||||
if (element is SlintPsiKeywordIdentifier) {
|
if (element is SlintPsiKeywordIdentifier) {
|
||||||
holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
|
holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
|
||||||
.range(element)
|
.range(element)
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package me.zhouxi.slint.lang.psi.builder
|
||||||
|
|
||||||
|
import com.intellij.lang.PsiBuilder
|
||||||
|
import com.intellij.lang.impl.DelegateMarker
|
||||||
|
import com.intellij.lang.impl.PsiBuilderAdapter
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/29
|
||||||
|
*/
|
||||||
|
class SlintPsiBuilder(delegate: PsiBuilder) : PsiBuilderAdapter(delegate) {
|
||||||
|
override fun mark(): PsiBuilder.Marker {
|
||||||
|
return SlintMarker(super.mark())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author zhouxi 2024/5/29
|
||||||
|
*/
|
||||||
|
class SlintMarker(delegate: PsiBuilder.Marker) : DelegateMarker(delegate) {
|
||||||
|
override fun precede(): PsiBuilder.Marker {
|
||||||
|
return SlintMarker(super.precede())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun done(type: IElementType) {
|
||||||
|
println(type)
|
||||||
|
super.done(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package me.zhouxi.slint.lang.psi.extension
|
|
||||||
|
|
||||||
import me.zhouxi.slint.lang.psi.SlintComponent
|
|
||||||
import me.zhouxi.slint.lang.psi.SlintProperty
|
|
||||||
|
|
||||||
|
|
||||||
fun SlintComponent.inheritsProperties(): List<SlintProperty> {
|
|
||||||
val properties = this.propertyList
|
|
||||||
val inherit =
|
|
||||||
this.inheritDeclaration?.referenceIdentifier?.reference?.resolve() as SlintComponent? ?: return properties
|
|
||||||
return properties + inherit.inheritsProperties()
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package me.zhouxi.slint.lang.psi.extension
|
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import me.zhouxi.slint.lang.psi.SlintImport
|
|
||||||
import me.zhouxi.slint.lang.psi.SlintReferenceIdentifier
|
|
||||||
|
|
||||||
|
|
||||||
fun SlintImport.importNames(): List<SlintReferenceIdentifier> {
|
|
||||||
return this.importElement?.importSpecifierList?.map { it.referenceIdentifier } ?: emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导入的有效的名字,
|
|
||||||
* psiElement可能是identifier或者internalName
|
|
||||||
*/
|
|
||||||
fun SlintImport.availableNames(): List<PsiElement> {
|
|
||||||
return this.importElement?.importSpecifierList?.map {
|
|
||||||
it.importAlias?.internalName ?: it.referenceIdentifier
|
|
||||||
} ?: emptyList()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package me.zhouxi.slint.lang.psi.extension
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
|
import com.intellij.icons.AllIcons
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.parentOfType
|
||||||
|
import me.zhouxi.slint.lang.psi.*
|
||||||
|
|
||||||
|
|
||||||
|
fun SlintComponent.inheritsProperties(): List<SlintProperty> {
|
||||||
|
val properties = this.propertyList
|
||||||
|
val inherit =
|
||||||
|
this.inheritDeclaration?.referenceIdentifier?.reference?.resolve() as SlintComponent? ?: return properties
|
||||||
|
if (inherit == this) {
|
||||||
|
return properties
|
||||||
|
}
|
||||||
|
return properties + inherit.inheritsProperties()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun SlintImport.importNames(): List<SlintReferenceIdentifier> {
|
||||||
|
return this.importElement?.importSpecifierList?.map { it.referenceIdentifier } ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入的有效的名字,
|
||||||
|
* psiElement可能是identifier或者internalName
|
||||||
|
*/
|
||||||
|
fun SlintImport.availableNames(): List<PsiElement> {
|
||||||
|
return this.importElement?.importSpecifierList?.map {
|
||||||
|
it.importAlias?.internalName ?: it.referenceIdentifier
|
||||||
|
} ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun SlintSubComponent.resolve(): SlintComponent? {
|
||||||
|
return this.referenceIdentifier.reference?.resolve() as SlintComponent?
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun SlintProperty.toLookupElement(): LookupElementBuilder {
|
||||||
|
return LookupElementBuilder.create(this)
|
||||||
|
.withTypeText(this.parentOfType<SlintComponent>()?.componentName?.text)
|
||||||
|
.withIcon(AllIcons.Nodes.Property)
|
||||||
|
}
|
||||||
@@ -33,8 +33,10 @@ object SlintImportSpecifierElementType :
|
|||||||
val aliasNode = children.firstOrNull { it.tokenType == ImportAlias }
|
val aliasNode = children.firstOrNull { it.tokenType == ImportAlias }
|
||||||
aliasNode?.let {
|
aliasNode?.let {
|
||||||
val nameNode = tree.getChildren(aliasNode).firstOrNull { it.tokenType == InternalName }
|
val nameNode = tree.getChildren(aliasNode).firstOrNull { it.tokenType == InternalName }
|
||||||
val token = nameNode?.let { tree.getChildren(nameNode) }?.first() as LighterASTTokenNode
|
val token = nameNode?.let { tree.getChildren(nameNode) }?.firstOrNull() as LighterASTTokenNode?
|
||||||
tree.charTable.intern(token.text).toString()
|
token?.let {
|
||||||
|
tree.charTable.intern(it.text).toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SlintImportSpecifierStubImpl(parentStub, name, alias)
|
return SlintImportSpecifierStubImpl(parentStub, name, alias)
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
package me.zhouxi.slint.lang.psi.utils
|
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
|
||||||
import me.zhouxi.slint.lang.psi.*
|
|
||||||
import java.util.function.Function
|
|
||||||
import java.util.function.Predicate
|
|
||||||
|
|
||||||
|
|
||||||
fun resolveComponent(element: SlintReferenceIdentifier?): SlintComponent? {
|
|
||||||
if (element == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val maybeComponent = element.reference?.resolve()
|
|
||||||
if (maybeComponent is SlintComponent) {
|
|
||||||
return maybeComponent
|
|
||||||
}
|
|
||||||
return resolveReferencedComponent(maybeComponent ?: return null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resolveComponent(element: SlintInternalName): SlintComponent? {
|
|
||||||
//内部名字解析引用
|
|
||||||
val resolve = element.reference?.resolve()
|
|
||||||
if (resolve is SlintComponent) {
|
|
||||||
return resolve
|
|
||||||
}
|
|
||||||
//InternalName解析不到东西,换成External试一下
|
|
||||||
if (resolve == null) {
|
|
||||||
val externalName = PsiTreeUtil.getPrevSiblingOfType(element, SlintExternalName::class.java)
|
|
||||||
if (externalName == null) {
|
|
||||||
val externalName1 = PsiTreeUtil.getNextSiblingOfType(element, SlintExternalName::class.java) ?: return null
|
|
||||||
return resolveReferencedComponent(externalName1)
|
|
||||||
}
|
|
||||||
return resolveReferencedComponent(externalName)
|
|
||||||
}
|
|
||||||
return resolveReferencedComponent(resolve)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resolveComponent(element: SlintExternalName): SlintComponent? {
|
|
||||||
val resolve = element.reference?.resolve()
|
|
||||||
if (resolve is SlintComponent) {
|
|
||||||
return resolve
|
|
||||||
}
|
|
||||||
//InternalName解析不到东西,换成External试一下
|
|
||||||
if (resolve == null) {
|
|
||||||
val internalName = PsiTreeUtil.getPrevSiblingOfType(element, SlintInternalName::class.java)
|
|
||||||
if (internalName == null) {
|
|
||||||
val internalName1 = PsiTreeUtil.getNextSiblingOfType(element, SlintInternalName::class.java) ?: return null
|
|
||||||
return resolveReferencedComponent(internalName1)
|
|
||||||
}
|
|
||||||
return resolveReferencedComponent(internalName)
|
|
||||||
}
|
|
||||||
return resolveReferencedComponent(resolve)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun resolveReferencedComponent(element: PsiElement?): SlintComponent? {
|
|
||||||
if (element == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
when (element) {
|
|
||||||
is SlintComponentName -> return element.parent as SlintComponent?
|
|
||||||
is SlintComponent -> return element
|
|
||||||
is SlintReferenceIdentifier -> return resolveComponent(element)
|
|
||||||
is SlintInternalName -> return resolveComponent(element)
|
|
||||||
is SlintExternalName -> return resolveComponent(element)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchProperty(
|
|
||||||
component: PsiElement?,
|
|
||||||
predicate: Predicate<SlintProperty>
|
|
||||||
): SlintProperty? {
|
|
||||||
if (component is SlintSubComponent) {
|
|
||||||
return searchProperty(component, predicate)
|
|
||||||
}
|
|
||||||
if (component is SlintComponent) {
|
|
||||||
return searchElementInParents(component, predicate) { it.propertyList }
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchProperty(
|
|
||||||
subComponent: SlintSubComponent?,
|
|
||||||
predicate: Predicate<SlintProperty>
|
|
||||||
): SlintProperty? {
|
|
||||||
val component = resolveComponent(subComponent?.referenceIdentifier) ?: return null
|
|
||||||
return searchElementInParents(component, predicate) { it.propertyList }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchCallback(
|
|
||||||
subComponent: SlintSubComponent?,
|
|
||||||
predicate: Predicate<SlintCallback>
|
|
||||||
): SlintCallback? {
|
|
||||||
val component = subComponent?.referenceIdentifier?.reference?.resolve() ?: return null
|
|
||||||
return searchElementInParents(
|
|
||||||
component as SlintComponent,
|
|
||||||
predicate
|
|
||||||
) { it.callbackList }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> searchElementInParents(
|
|
||||||
component: SlintComponent?,
|
|
||||||
predicate: Predicate<T>,
|
|
||||||
function: Function<SlintComponent, List<T>?>
|
|
||||||
): T? {
|
|
||||||
if (component == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
val properties = function.apply(component) ?: arrayListOf<T>()
|
|
||||||
for (property in properties) {
|
|
||||||
if (predicate.test(property)) {
|
|
||||||
return property
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val inheritComponent = resolveReferencedComponent(component.inheritDeclaration?.referenceIdentifier)
|
|
||||||
return searchElementInParents(inheritComponent, predicate, function)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package me.zhouxi.slint.lang.psi.utils
|
||||||
|
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
import com.intellij.psi.tree.TokenSet
|
||||||
|
import me.zhouxi.slint.lang.psi.SlintTypes
|
||||||
|
|
||||||
|
|
||||||
|
val keywords = TokenSet.create(*SlintTypes::class.java.declaredFields
|
||||||
|
.filter { it.name.endsWith("Keyword") }
|
||||||
|
.map { it.get(null) as IElementType }.toTypedArray()
|
||||||
|
)
|
||||||
|
|
||||||
|
val braces = TokenSet.create(
|
||||||
|
SlintTypes.LBrace,
|
||||||
|
SlintTypes.LParent,
|
||||||
|
SlintTypes.LBracket
|
||||||
|
)
|
||||||
|
val expressions = TokenSet.create(*SlintTypes::class.java.declaredFields
|
||||||
|
.filter { it.name.endsWith("Expression") }
|
||||||
|
.map { it.get(null) as IElementType }.toTypedArray()
|
||||||
|
)
|
||||||
@@ -5,13 +5,10 @@ import com.intellij.psi.PsiReference
|
|||||||
import com.intellij.psi.PsiReferenceBase
|
import com.intellij.psi.PsiReferenceBase
|
||||||
import com.intellij.psi.PsiReferenceProvider
|
import com.intellij.psi.PsiReferenceProvider
|
||||||
import com.intellij.psi.util.parentOfType
|
import com.intellij.psi.util.parentOfType
|
||||||
import com.intellij.psi.util.parentOfTypes
|
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
import me.zhouxi.slint.lang.psi.SlintComponent
|
import me.zhouxi.slint.lang.psi.SlintComponent
|
||||||
import me.zhouxi.slint.lang.psi.SlintPropertyBinding
|
|
||||||
import me.zhouxi.slint.lang.psi.SlintSubComponent
|
import me.zhouxi.slint.lang.psi.SlintSubComponent
|
||||||
import me.zhouxi.slint.lang.psi.extension.inheritsProperties
|
import me.zhouxi.slint.lang.psi.extension.inheritsProperties
|
||||||
import me.zhouxi.slint.lang.psi.utils.searchProperty
|
|
||||||
|
|
||||||
object PropertyReferenceProvider : PsiReferenceProvider() {
|
object PropertyReferenceProvider : PsiReferenceProvider() {
|
||||||
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
|
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
<depends>com.intellij.modules.platform</depends>
|
<depends>com.intellij.modules.platform</depends>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<typedHandler implementation="me.zhouxi.slint.completion.SlintCompletionAutoPopupHandler" id="completionAutoPopup"
|
||||||
|
order="first"/>
|
||||||
<fileType name="Slint File"
|
<fileType name="Slint File"
|
||||||
implementationClass="me.zhouxi.slint.lang.psi.SlintFileType"
|
implementationClass="me.zhouxi.slint.lang.psi.SlintFileType"
|
||||||
fieldName="INSTANCE"
|
fieldName="INSTANCE"
|
||||||
@@ -55,6 +57,8 @@
|
|||||||
|
|
||||||
<stubIndex implementation="me.zhouxi.slint.lang.psi.stubs.index.ImportNameIndex"/>
|
<stubIndex implementation="me.zhouxi.slint.lang.psi.stubs.index.ImportNameIndex"/>
|
||||||
|
|
||||||
|
<lang.formatter language="Slint" implementationClass="me.zhouxi.slint.formatter.SlintFormatterModelBuilder"/>
|
||||||
|
|
||||||
</extensions>
|
</extensions>
|
||||||
<actions>
|
<actions>
|
||||||
<action id="slint.preview" class="me.zhouxi.slint.preview.PreviewAction"
|
<action id="slint.preview" class="me.zhouxi.slint.preview.PreviewAction"
|
||||||
|
|||||||
Reference in New Issue
Block a user