添加stubIndex

This commit is contained in:
me
2024-05-26 13:48:10 +08:00
parent c25144f4b6
commit 9603c24461
51 changed files with 727 additions and 311 deletions

View File

@@ -1,87 +1,43 @@
package me.zhouxi.slint.completion
import com.intellij.codeInsight.completion.*
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.icons.AllIcons
import com.intellij.codeInsight.completion.CompletionContributor
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.PsiClass
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.psi.util.childrenOfType
import com.intellij.psi.util.parentOfType
import com.intellij.util.ProcessingContext
import me.zhouxi.slint.lang.SlintParserDefinition
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintFile
import me.zhouxi.slint.lang.psi.SlintImport
import me.zhouxi.slint.lang.psi.SlintPsiUtils.InternalTypes
import me.zhouxi.slint.completion.provider.BasicTypeProvider
import me.zhouxi.slint.completion.provider.ComponentProvider
import me.zhouxi.slint.completion.provider.ElementKeywordProvider
import me.zhouxi.slint.completion.provider.TopKeywordProvider
import me.zhouxi.slint.lang.psi.SlintTypes
import me.zhouxi.slint.lang.psi.utils.exportedElements
import me.zhouxi.slint.lang.psi.utils.inheritDeclaredElements
import me.zhouxi.slint.stubs.StubKeys
import me.zhouxi.slint.stubs.types.SlintFileElementType
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
class SlintCompletionContributor : CompletionContributor() {
init {
//文件级别
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement().withAncestor(4, PlatformPatterns.psiElement(SlintFileElementType)),
object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
result.addAllElements(TopKeywords)
}
})
PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintFileElementType)),
TopKeywordProvider
)
//类型定义
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintTypes.Type)),
object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
result.addAllElements(BasicTypes)
}
})
BasicTypeProvider
)
//componentBody
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintTypes.ComponentBody)),
object : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
val project = parameters.position.project
val components = StubIndex.getInstance().getAllKeys(StubKeys.Component, project).map {
LookupElementBuilder.create(it).withIcon(AllIcons.Nodes.Class)
}
result.addAllElements(components)
result.addAllElements(ElementKeywords)
val currentComponent = parameters.position.parentOfType<SlintComponent>() ?: return
val elements = currentComponent.inheritDeclaredElements().map {
LookupElementBuilder.create(it).withIcon(AllIcons.Nodes.Property)
}
result.addAllElements(elements)
}
})
PlatformPatterns.psiElement().withAncestor(2, PlatformPatterns.psiElement(SlintTypes.ComponentBody)),
ElementKeywordProvider
)
//componentBody
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement().withAncestor(2, PlatformPatterns.psiElement(SlintTypes.ComponentBody)),
ComponentProvider
)
}
}
val BasicTypes = InternalTypes.map { LookupElementBuilder.create(it) }
val TopKeywords = arrayOf("export", "component", "global", "enum", "struct").map { LookupElementBuilder.create(it) }
val ElementKeywords = arrayOf(
"in", "out", "in-out", "callback",
"property", "private", "changed",
"states", "transitions", "@children"
).map { LookupElementBuilder.create(it) }
}

View File

@@ -0,0 +1,20 @@
package me.zhouxi.slint.completion.provider
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionProvider
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.util.ProcessingContext
import me.zhouxi.slint.lang.psi.SlintPsiUtils.InternalTypes
object BasicTypeProvider : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
result.addAllElements(basicTypes)
}
private val basicTypes = InternalTypes.map { LookupElementBuilder.create(it) }
}

View File

@@ -0,0 +1,49 @@
package me.zhouxi.slint.completion.provider
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionProvider
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.codeInsight.lookup.LookupElementDecorator
import com.intellij.icons.AllIcons
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.psi.search.GlobalSearchScope.projectScope
import com.intellij.psi.stubs.StubIndex
import com.intellij.util.ProcessingContext
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.stubs.index.StubIndexKeys
object ComponentProvider : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
val project = parameters.position.project
val components = arrayListOf<SlintComponent>()
StubIndex.getInstance().processAllKeys(StubIndexKeys.Component, project) {
if (result.prefixMatcher.prefixMatches(it)) {
val elements = StubIndex.getElements(
StubIndexKeys.Component,
it,
project,
projectScope(project),
SlintComponent::class.java
)
components.addAll(elements)
}
true
}
val lookups = components.map {
val targetFile = it.containingFile.originalFile.virtualFile
val currentFile = parameters.position.containingFile.originalFile.virtualFile
val path = VfsUtil.findRelativePath(currentFile, targetFile, '/')
val builder =
LookupElementBuilder.create(it).withTypeText(path).withIcon(AllIcons.Nodes.Class)
LookupElementDecorator.withInsertHandler(builder) { _, item ->
println(item.psiElement)
}
}
result.addAllElements(lookups)
}
}

View File

@@ -0,0 +1,23 @@
package me.zhouxi.slint.completion.provider
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionProvider
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.util.ProcessingContext
object ElementKeywordProvider : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
result.addAllElements(elementKeywords)
}
private val elementKeywords = arrayOf(
"in", "out", "in-out", "callback",
"property", "private", "changed",
"states", "transitions", "@children"
).map { LookupElementBuilder.create(it) }
}

View File

@@ -0,0 +1,20 @@
package me.zhouxi.slint.completion.provider
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionProvider
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.util.ProcessingContext
object TopKeywordProvider : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
result.addAllElements(topKeywords)
}
private val topKeywords =
arrayOf("export", "component", "global", "enum", "struct").map { LookupElementBuilder.create(it) }
}

View File

@@ -6,6 +6,7 @@ import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
import com.intellij.psi.PsiElement
import me.zhouxi.slint.lang.psi.*
import me.zhouxi.slint.lang.psi.keyword.SlintPsiKeywordIdentifier
class KeywordHighlightAnnotator : Annotator {
override fun annotate(element: PsiElement, holder: AnnotationHolder) {

View File

@@ -11,7 +11,7 @@ import me.zhouxi.slint.lang.psi.SlintPsiNamedElement
/**
* @author zhouxi 2024/5/15
*/
abstract class SlintPsiNamedElementMixinImpl(node: ASTNode) : SlintPsiElementImpl(node),
abstract class SlintPsiNamedElementImpl(node: ASTNode) : SlintPsiElementImpl(node),
SlintPsiNamedElement {
override fun getNameIdentifier(): PsiElement? {
return findChildByClass(SlintNamed::class.java) ?: this

View File

@@ -1,10 +1,8 @@
package me.zhouxi.slint.stubs.index
package me.zhouxi.slint.lang.psi.stubs.index
import com.intellij.psi.stubs.StringStubIndexExtension
import com.intellij.psi.stubs.StubIndexKey
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.stubs.StubKeys
class ComponentNameIndex : StringStubIndexExtension<SlintComponent>() {
override fun getKey() = StubKeys.Component
override fun getKey() = StubIndexKeys.Component
}

View File

@@ -0,0 +1,4 @@
package me.zhouxi.slint.lang.psi.stubs.index;
public class ExportedNameIndex {
}

View File

@@ -0,0 +1,8 @@
package me.zhouxi.slint.lang.psi.stubs.index
import com.intellij.psi.stubs.StringStubIndexExtension
import me.zhouxi.slint.lang.psi.SlintImportSpecifier
class ImportNameIndex : StringStubIndexExtension<SlintImportSpecifier>() {
override fun getKey() = StubIndexKeys.Imported
}

View File

@@ -0,0 +1,10 @@
package me.zhouxi.slint.lang.psi.stubs.index
import com.intellij.psi.stubs.StringStubIndexExtension
import me.zhouxi.slint.lang.psi.SlintProperty
import me.zhouxi.slint.lang.psi.stubs.index.StubIndexKeys.Property
class PropertyNameIndex : StringStubIndexExtension<SlintProperty>() {
override fun getKey() = Property
}

View File

@@ -0,0 +1,24 @@
package me.zhouxi.slint.lang.psi.stubs.index
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.StubIndex
import me.zhouxi.slint.lang.psi.SlintComponent
fun searchComponent(key: String, project: Project, psiFile: PsiFile? = null): Collection<SlintComponent> {
val scope = psiFile?.let { GlobalSearchScope.fileScope(it) } ?: GlobalSearchScope.projectScope(project)
return StubIndex.getElements(
StubIndexKeys.Component,
key,
project, scope,
SlintComponent::class.java
)
}
fun searchProperty(key: String,project: Project,psiElement: PsiElement){
// GlobalSearchScope;
// StubIndex.getInstance().getAllKeys()
}

View File

@@ -0,0 +1,20 @@
package me.zhouxi.slint.lang.psi.stubs.index
import com.intellij.psi.stubs.StubIndexKey
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintImportSpecifier
import me.zhouxi.slint.lang.psi.SlintProperty
/**
* @author zhouxi 2024/5/23
*/
object StubIndexKeys {
val Component = StubIndexKey.createIndexKey<String, SlintComponent>("slint.component.index")
val Property = StubIndexKey.createIndexKey<String, SlintProperty>("slint.property.index")
val Imported = StubIndexKey.createIndexKey<String, SlintImportSpecifier>("slint.import.index")
val Exported = StubIndexKey.createIndexKey<String, SlintImportSpecifier>("slint.export.index")
}

View File

@@ -1,7 +1,6 @@
package me.zhouxi.slint.stubs.stub
package me.zhouxi.slint.lang.psi.stubs.stub
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.stubs.SlintPsiStub
/**
* @author zhouxi 2024/5/23
@@ -9,5 +8,5 @@ import me.zhouxi.slint.stubs.SlintPsiStub
interface SlintComponentStub : SlintPsiStub<SlintComponent> {
val exported: Boolean
val identifier: String
val componentName: String
}

View File

@@ -1,10 +1,10 @@
package me.zhouxi.slint.stubs.stub
package me.zhouxi.slint.lang.psi.stubs.stub
import com.intellij.psi.stubs.PsiFileStub
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintFile
import me.zhouxi.slint.lang.psi.SlintTypes
import me.zhouxi.slint.stubs.types.SlintFileElementType
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
interface SlintFileStub : PsiFileStub<SlintFile> {

View File

@@ -0,0 +1,11 @@
package me.zhouxi.slint.lang.psi.stubs.stub
import me.zhouxi.slint.lang.psi.SlintImportSpecifier
interface SlintImportSpecifierStub : SlintPsiStub<SlintImportSpecifier> {
val name: String
val alias: String?
}

View File

@@ -0,0 +1,5 @@
package me.zhouxi.slint.lang.psi.stubs.stub
import me.zhouxi.slint.lang.psi.SlintImport
interface SlintImportStub : SlintPsiStub<SlintImport>

View File

@@ -0,0 +1,15 @@
package me.zhouxi.slint.lang.psi.stubs.stub
import me.zhouxi.slint.lang.psi.SlintProperty
interface SlintPropertyStub : SlintPsiStub<SlintProperty> {
val isIn: Boolean
val isOut: Boolean
val isPrivate: Boolean
val propertyName: String
}

View File

@@ -0,0 +1,9 @@
package me.zhouxi.slint.lang.psi.stubs.stub
import com.intellij.psi.stubs.StubElement
import me.zhouxi.slint.lang.psi.SlintPsiElement
/**
* @author zhouxi 2024/5/23
*/
interface SlintPsiStub<T : SlintPsiElement> : StubElement<T>

View File

@@ -0,0 +1,19 @@
package me.zhouxi.slint.lang.psi.stubs.stub.impl
import com.intellij.psi.stubs.StubElement
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.stubs.stub.SlintComponentStub
import me.zhouxi.slint.lang.psi.stubs.types.SlintComponentElementType
/**
* @author zhouxi 2024/5/23
*/
class SlintComponentStubImpl(
parent: StubElement<*>?,
override val exported: Boolean,
override val componentName: String,
) :
SlintStubBase<SlintComponent>(parent, SlintComponentElementType), SlintComponentStub {
}

View File

@@ -0,0 +1,15 @@
package me.zhouxi.slint.lang.psi.stubs.stub.impl
import com.intellij.psi.stubs.PsiFileStubImpl
import me.zhouxi.slint.lang.psi.SlintFile
import me.zhouxi.slint.lang.psi.stubs.stub.SlintFileStub
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
/**
* @author zhouxi 2024/5/23
*/
class SlintFileStubImpl(file: SlintFile?) : PsiFileStubImpl<SlintFile>(file), SlintFileStub {
override fun getType() = SlintFileElementType
}

View File

@@ -0,0 +1,14 @@
package me.zhouxi.slint.lang.psi.stubs.stub.impl
import com.intellij.psi.stubs.StubElement
import me.zhouxi.slint.lang.psi.SlintImportSpecifier
import me.zhouxi.slint.lang.psi.stubs.stub.SlintImportSpecifierStub
import me.zhouxi.slint.lang.psi.stubs.types.SlintImportSpecifierElementType
class SlintImportSpecifierStubImpl(
parent: StubElement<*>?,
override val name: String,
override val alias: String? = null
) : SlintStubBase<SlintImportSpecifier>(parent, SlintImportSpecifierElementType), SlintImportSpecifierStub {
}

View File

@@ -0,0 +1,9 @@
package me.zhouxi.slint.lang.psi.stubs.stub.impl
import com.intellij.psi.stubs.StubElement
import me.zhouxi.slint.lang.psi.SlintImport
import me.zhouxi.slint.lang.psi.stubs.stub.SlintImportStub
import me.zhouxi.slint.lang.psi.stubs.types.SlintImportElementType
class SlintImportStubImpl(parent: StubElement<*>?) :
SlintStubBase<SlintImport>(parent, SlintImportElementType), SlintImportStub

View File

@@ -0,0 +1,38 @@
package me.zhouxi.slint.lang.psi.stubs.stub.impl
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.StubBase
import com.intellij.psi.stubs.StubElement
import com.intellij.util.BitUtil
import me.zhouxi.slint.lang.psi.SlintProperty
import me.zhouxi.slint.lang.psi.stubs.stub.SlintPropertyStub
import me.zhouxi.slint.lang.psi.stubs.types.SlintPropertyElementType
class SlintPropertyStubImpl(
parent: StubElement<*>?,
private val flag: Short,
override val propertyName: String
) : SlintStubBase<SlintProperty>(parent, SlintPropertyElementType), SlintPropertyStub {
override val isIn: Boolean
get() = BitUtil.isSet(flag.toInt(), IN)
override val isOut: Boolean
get() = BitUtil.isSet(flag.toInt(), OUT)
override val isPrivate: Boolean
get() = flag.toInt() == 0
companion object {
const val IN: Int = 0x01
const val OUT: Int = 0x02
fun pack(isIn: Boolean, isOut: Boolean): Short {
var flag = 0
if (isIn) {
flag = flag or IN
}
if (isOut) {
flag = flag or OUT
}
return flag.toShort()
}
}
}

View File

@@ -0,0 +1,16 @@
package me.zhouxi.slint.lang.psi.stubs.stub.impl
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.StubBase
import com.intellij.psi.stubs.StubElement
abstract class SlintStubBase<T : PsiElement> protected constructor(
parent: StubElement<*>?,
elementType: IStubElementType<*, *>?
) : StubBase<T>(parent, elementType) {
override fun toString(): String {
return StringUtil.trimEnd(javaClass.simpleName, "Impl")
}
}

View File

@@ -1,30 +1,25 @@
package me.zhouxi.slint.stubs.types
package me.zhouxi.slint.lang.psi.stubs.types
import com.intellij.lang.ASTNode
import com.intellij.lang.LighterAST
import com.intellij.lang.LighterASTNode
import com.intellij.lang.LighterASTTokenNode
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.impl.search.JavaSourceFilterScope
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.stubs.*
import com.intellij.psi.util.parentOfType
import me.zhouxi.slint.lang.SlintLanguage
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintExport
import me.zhouxi.slint.lang.psi.SlintTypes.*
import me.zhouxi.slint.lang.psi.impl.SlintComponentImpl
import me.zhouxi.slint.stubs.StubKeys
import me.zhouxi.slint.stubs.impl.SlintComponentStubImpl
import me.zhouxi.slint.stubs.stub.SlintComponentStub
import me.zhouxi.slint.lang.psi.stubs.stub.impl.SlintComponentStubImpl
import me.zhouxi.slint.lang.psi.stubs.index.StubIndexKeys
import me.zhouxi.slint.lang.psi.stubs.stub.SlintComponentStub
import java.io.IOException
/**
* @author zhouxi 2024/5/23
*/
class SlintComponentStubType(debugName: String) :
ILightStubElementType<SlintComponentStub, SlintComponent>(debugName, SlintLanguage.INSTANCE) {
object SlintComponentElementType :
ILightStubElementType<SlintComponentStub, SlintComponent>("Component", SlintLanguage.INSTANCE) {
override fun createPsi(stub: SlintComponentStub): SlintComponent {
return SlintComponentImpl(stub, this)
}
@@ -36,7 +31,6 @@ class SlintComponentStubType(debugName: String) :
override fun createStub(psi: SlintComponent, parentStub: StubElement<out PsiElement?>): SlintComponentStub {
return SlintComponentStubImpl(
parentStub,
this,
psi.exportKeyword != null,
psi.componentName!!.text
)
@@ -49,14 +43,14 @@ class SlintComponentStubType(debugName: String) :
@Throws(IOException::class)
override fun serialize(stub: SlintComponentStub, dataStream: StubOutputStream) {
dataStream.writeBoolean(stub.exported)
dataStream.writeName(stub.identifier)
dataStream.writeName(stub.componentName)
}
@Throws(IOException::class)
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): SlintComponentStub {
val exported = dataStream.readBoolean()
val identifier = dataStream.readNameString()
return SlintComponentStubImpl(parentStub, this, exported, identifier!!)
return SlintComponentStubImpl(parentStub, exported, identifier!!)
}
override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): SlintComponentStub {
@@ -64,10 +58,10 @@ class SlintComponentStubType(debugName: String) :
val identifier = tree.getChildren(node).first { it.tokenType == ComponentName }
val token = tree.getChildren(identifier)[0] as LighterASTTokenNode
return SlintComponentStubImpl(parentStub, this, exported, tree.charTable.intern(token.text).toString())
return SlintComponentStubImpl(parentStub, exported, tree.charTable.intern(token.text).toString())
}
override fun indexStub(stub: SlintComponentStub, sink: IndexSink) {
sink.occurrence(StubKeys.Component, stub.identifier)
sink.occurrence(StubIndexKeys.Component, stub.componentName)
}
}

View File

@@ -1,19 +1,15 @@
package me.zhouxi.slint.stubs.types
package me.zhouxi.slint.lang.psi.stubs.types
import com.intellij.psi.stubs.StubElement
import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.tree.ILightStubFileElementType
import me.zhouxi.slint.lang.SlintLanguage
import me.zhouxi.slint.stubs.impl.SlintFileStubImpl
import me.zhouxi.slint.stubs.stub.SlintFileStub
import me.zhouxi.slint.lang.psi.stubs.stub.impl.SlintFileStubImpl
import me.zhouxi.slint.lang.psi.stubs.stub.SlintFileStub
object SlintFileElementType : ILightStubFileElementType<SlintFileStub>("SlintFile", SlintLanguage.INSTANCE) {
override fun getStubVersion(): Int {
return 1
}
override fun getStubVersion() = 1
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?): SlintFileStub {
return SlintFileStubImpl(null)
}
}
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?) = SlintFileStubImpl(null)
}

View File

@@ -0,0 +1,42 @@
package me.zhouxi.slint.lang.psi.stubs.types
import com.intellij.lang.LighterAST
import com.intellij.lang.LighterASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.*
import me.zhouxi.slint.lang.SlintLanguage
import me.zhouxi.slint.lang.psi.SlintImport
import me.zhouxi.slint.lang.psi.impl.SlintImportImpl
import me.zhouxi.slint.lang.psi.stubs.stub.SlintImportStub
import me.zhouxi.slint.lang.psi.stubs.stub.impl.SlintImportStubImpl
object SlintImportElementType :
ILightStubElementType<SlintImportStub, SlintImport>("Import", SlintLanguage.INSTANCE) {
override fun getExternalId() = "slint.import"
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?): SlintImportStub {
return SlintImportStubImpl(parentStub)
}
override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): SlintImportStub {
return SlintImportStubImpl(parentStub)
}
override fun createStub(psi: SlintImport, parentStub: StubElement<out PsiElement>?): SlintImportStub {
return SlintImportStubImpl(parentStub)
}
override fun createPsi(stub: SlintImportStub): SlintImport {
return SlintImportImpl(stub, this)
}
override fun indexStub(stub: SlintImportStub, sink: IndexSink) {
}
override fun serialize(stub: SlintImportStub, dataStream: StubOutputStream) {
}
}

View File

@@ -0,0 +1,73 @@
package me.zhouxi.slint.lang.psi.stubs.types
import com.intellij.lang.LighterAST
import com.intellij.lang.LighterASTNode
import com.intellij.lang.LighterASTTokenNode
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.*
import me.zhouxi.slint.lang.SlintLanguage
import me.zhouxi.slint.lang.psi.SlintImportSpecifier
import me.zhouxi.slint.lang.psi.SlintTypes.*
import me.zhouxi.slint.lang.psi.impl.SlintImportSpecifierImpl
import me.zhouxi.slint.lang.psi.stubs.index.StubIndexKeys.Imported
import me.zhouxi.slint.lang.psi.stubs.stub.SlintImportSpecifierStub
import me.zhouxi.slint.lang.psi.stubs.stub.impl.SlintImportSpecifierStubImpl
object SlintImportSpecifierElementType :
ILightStubElementType<SlintImportSpecifierStub, SlintImportSpecifier>("ImportSpecifier", SlintLanguage.INSTANCE) {
override fun getExternalId() = "slint.import.specifier"
override fun createStub(
tree: LighterAST,
node: LighterASTNode,
parentStub: StubElement<*>
): SlintImportSpecifierStub {
val children = tree.getChildren(node);
val name = run {
val nameNode = children.first { it.tokenType == ReferenceIdentifier }
val token = tree.getChildren(nameNode)[0] as LighterASTTokenNode
tree.charTable.intern(token.text).toString()
}
val alias = run {
val aliasNode = children.firstOrNull { it.tokenType == ImportAlias }
aliasNode?.let {
val nameNode = tree.getChildren(aliasNode).firstOrNull { it.tokenType == InternalName }
val token = nameNode?.let { tree.getChildren(nameNode) }?.first() as LighterASTTokenNode
tree.charTable.intern(token.text).toString()
}
}
return SlintImportSpecifierStubImpl(parentStub, name, alias)
}
override fun createStub(
psi: SlintImportSpecifier,
parentStub: StubElement<out PsiElement>?
): SlintImportSpecifierStub {
return SlintImportSpecifierStubImpl(
parentStub,
psi.referenceIdentifier.text,
psi.importAlias?.internalName?.text
)
}
override fun createPsi(stub: SlintImportSpecifierStub): SlintImportSpecifier {
return SlintImportSpecifierImpl(stub, this)
}
override fun indexStub(stub: SlintImportSpecifierStub, sink: IndexSink) {
sink.occurrence(Imported, stub.alias ?: stub.name)
}
override fun serialize(stub: SlintImportSpecifierStub, dataStream: StubOutputStream) {
dataStream.writeName(stub.name)
dataStream.writeName(stub.alias)
}
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?): SlintImportSpecifierStub {
val name = dataStream.readNameString()
val alias = dataStream.readNameString()
return SlintImportSpecifierStubImpl(parentStub, name!!, alias)
}
}

View File

@@ -0,0 +1,79 @@
package me.zhouxi.slint.lang.psi.stubs.types
import com.intellij.lang.ASTNode
import com.intellij.lang.LighterAST
import com.intellij.lang.LighterASTNode
import com.intellij.lang.LighterASTTokenNode
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.*
import me.zhouxi.slint.lang.SlintLanguage
import me.zhouxi.slint.lang.psi.SlintProperty
import me.zhouxi.slint.lang.psi.SlintTypes.*
import me.zhouxi.slint.lang.psi.impl.SlintPropertyImpl
import me.zhouxi.slint.lang.psi.stubs.index.StubIndexKeys
import me.zhouxi.slint.lang.psi.stubs.stub.SlintPropertyStub
import me.zhouxi.slint.lang.psi.stubs.stub.impl.SlintPropertyStubImpl
import java.io.IOException
object SlintPropertyElementType :
ILightStubElementType<SlintPropertyStub, SlintProperty?>("SlintProperty", SlintLanguage.INSTANCE) {
override fun createStub(tree: LighterAST, node: LighterASTNode, parentStub: StubElement<*>): SlintPropertyStub {
val children = tree.getChildren(node)
val modifierNode = children.firstOrNull { it.tokenType == PropertyModifier }?.let {
when (tree.getChildren(it)[0].tokenType) {
InKeyword -> 1
OutKeyword -> 2
InOutKeyword -> 3
else -> 0
}
} ?: 0
val name = tree.getChildren(children.first { it.tokenType == PropertyName })[0] as LighterASTTokenNode
return SlintPropertyStubImpl(
parentStub,
modifierNode.toShort(),
tree.charTable.intern(name.text).toString()
)
}
fun createPsi(node: ASTNode): SlintProperty {
return SlintPropertyImpl(node)
}
override fun createPsi(stub: SlintPropertyStub): SlintProperty {
return SlintPropertyImpl(stub, this)
}
override fun createStub(
psi: SlintProperty,
parentStub: StubElement<out PsiElement?>
): SlintPropertyStub {
val modifier = psi.propertyModifier
val isIn = modifier?.inKeyword != null || modifier?.inOutKeyword != null
val isOut = modifier?.outKeyword != null || modifier?.inOutKeyword != null
val name = psi.propertyName!!.text
val flag = SlintPropertyStubImpl.pack(isIn, isOut)
return SlintPropertyStubImpl(parentStub, flag, name)
}
override fun getExternalId(): String {
return "slint.property"
}
@Throws(IOException::class)
override fun serialize(stub: SlintPropertyStub, dataStream: StubOutputStream) {
val flag = SlintPropertyStubImpl.pack(stub.isIn, stub.isOut)
dataStream.writeShort(flag.toInt())
dataStream.writeName(stub.propertyName)
}
@Throws(IOException::class)
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): SlintPropertyStub {
val flag = dataStream.readShort()
val name = dataStream.readNameString()
return SlintPropertyStubImpl(parentStub, flag, name!!)
}
override fun indexStub(stub: SlintPropertyStub, sink: IndexSink) {
sink.occurrence(StubIndexKeys.Property, stub.propertyName)
}
}

View File

@@ -0,0 +1,22 @@
package me.zhouxi.slint.lang.psi.stubs.types
import com.intellij.psi.tree.IElementType
@Suppress("UNUSED_PARAMETER")
interface SlintStubTypes {
companion object {
@JvmStatic
fun component(debugName: String) = SlintComponentElementType
@JvmStatic
fun property(debugName: String) = SlintPropertyElementType
@JvmStatic
fun importSpecifier(debugName: String) = SlintImportSpecifierElementType
@JvmStatic
fun slintImport(debugName: String) = SlintImportElementType
val File: IElementType = SlintFileElementType
}
}

View File

@@ -1,43 +0,0 @@
package me.zhouxi.slint.lang.psi.utils
import com.intellij.psi.PsiElement
import com.intellij.psi.util.childrenOfType
import me.zhouxi.slint.lang.psi.*
fun SlintExport.exportedElements(): List<SlintPsiNamedElement> {
val list = mutableListOf<SlintPsiNamedElement>()
// this.exportType?.exportIdentifierList?.forEach {
// if (it.externalName == null) {
// val component = it.referenceIdentifier.reference?.resolve() as SlintComponent?
// component?.let { list.add(component) }
// } else {
// list.add(it.externalName!!)
// }
// }
// this.component?.let { list.add(it) }
// this.globalSingleton?.let { list.add(it) }
// val file = this.exportModule?.moduleLocation?.reference?.resolve() as SlintFile? ?: return list
// val exports = file.childrenOfType<SlintExport>()
// //TODO recursion error
// exports.forEach { list.addAll(it.exportedElements()) }
return list
}
fun SlintImport.importedElements(): List<PsiElement> {
val list = mutableListOf<PsiElement>()
// this.importedIdentifierList.forEach { identifier ->
// list.add(identifier.referenceIdentifier)
// identifier.internalName?.let { list.add(it) }
// }
return list
}
fun SlintFile.importedElements(): List<PsiElement> {
return this.childrenOfType<SlintImport>().flatMap { it.importedElements() }
}
fun SlintFile.exportedElements(): List<SlintPsiNamedElement> {
return this.childrenOfType<SlintExport>().flatMap { it.exportedElements() }
}

View File

@@ -69,34 +69,34 @@ fun resolveReferencedComponent(element: PsiElement?): SlintComponent? {
fun searchProperty(
component: PsiElement?,
predicate: Predicate<SlintPropertyDeclaration>
): SlintPropertyDeclaration? {
predicate: Predicate<SlintProperty>
): SlintProperty? {
if (component is SlintSubComponent) {
return searchProperty(component, predicate)
}
if (component is SlintComponent) {
return searchElementInParents(component, predicate) { it.componentBody?.propertyDeclarationList }
return searchElementInParents(component, predicate) { it.componentBody?.propertyList }
}
return null
}
fun searchProperty(
subComponent: SlintSubComponent?,
predicate: Predicate<SlintPropertyDeclaration>
): SlintPropertyDeclaration? {
predicate: Predicate<SlintProperty>
): SlintProperty? {
val component = resolveComponent(subComponent?.referenceIdentifier) ?: return null
return searchElementInParents(component, predicate) { it.componentBody?.propertyDeclarationList }
return searchElementInParents(component, predicate) { it.componentBody?.propertyList }
}
fun searchCallback(
subComponent: SlintSubComponent?,
predicate: Predicate<SlintCallbackDeclaration>
): SlintCallbackDeclaration? {
predicate: Predicate<SlintCallback>
): SlintCallback? {
val component = subComponent?.referenceIdentifier?.reference?.resolve() ?: return null
return searchElementInParents(
component as SlintComponent,
predicate
) { it.componentBody?.callbackDeclarationList }
) { it.componentBody?.callbackList }
}
fun <T> searchElementInParents(
@@ -118,14 +118,14 @@ fun <T> searchElementInParents(
}
fun SlintComponent.currentDeclaredElements(): List<SlintPsiNamedElement> {
val properties = this.componentBody?.propertyDeclarationList ?: emptyList()
val callbacks = this.componentBody?.callbackDeclarationList ?: emptyList()
val properties = this.componentBody?.propertyList ?: emptyList()
val callbacks = this.componentBody?.callbackList ?: emptyList()
return properties + callbacks
}
fun SlintComponent.inheritDeclaredElements(): List<SlintPsiNamedElement> {
val properties = this.componentBody?.propertyDeclarationList ?: emptyList()
val callbacks = this.componentBody?.callbackDeclarationList ?: emptyList()
val properties = this.componentBody?.propertyList ?: emptyList()
val callbacks = this.componentBody?.callbackList ?: emptyList()
val inheritedComponent = resolveReferencedComponent(this.inheritDeclaration?.referenceIdentifier)
?: return properties + callbacks
return properties + callbacks + inheritedComponent.inheritDeclaredElements()

View File

@@ -22,11 +22,11 @@ class SlintReferenceContributor : PsiReferenceContributor() {
psiElement(SubComponent),
psiElement(Component),
psiElement(InheritDeclaration),
// psiElement(ImportedIdentifier),
psiElement(ImportSpecifier)
// psiElement(ExportIdentifier)
)
),
ComponentReferenceProvider()
ComponentReferenceProvider
)
//moduleLocation Reference
registrar.registerReferenceProvider(

View File

@@ -8,13 +8,12 @@ import com.intellij.psi.util.childrenOfType
import com.intellij.psi.util.parentOfType
import com.intellij.util.ProcessingContext
import me.zhouxi.slint.lang.psi.*
import me.zhouxi.slint.lang.psi.utils.exportedElements
import me.zhouxi.slint.lang.psi.utils.importedElements
import me.zhouxi.slint.lang.psi.stubs.index.searchComponent
/**
* @author zhouxi 2024/5/17
*/
class ComponentReferenceProvider : PsiReferenceProvider() {
object ComponentReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
return arrayOf(SlintComponentNameReference(element as SlintReferenceIdentifier))
}
@@ -22,21 +21,24 @@ class ComponentReferenceProvider : PsiReferenceProvider() {
class SlintComponentNameReference(element: SlintReferenceIdentifier) : PsiReferenceBase<PsiElement?>(element) {
override fun resolve(): PsiElement? {
val file = element.containingFile as SlintFile
//优先查找当前文件内的组件定义
val component = file.childrenOfType<SlintComponent>()
.firstOrNull { it.componentName?.textMatches(element) == true }
if (component != null) {
return component
file.childrenOfType<SlintComponent>()
.find { it.componentName?.textMatches(element) == true }
?.let { return it }
val specifier = if (element.parent is SlintImportSpecifier) {
element.parent as SlintImportSpecifier
} else {
file.childrenOfType<SlintImport>()
.flatMap { it.importElement?.importSpecifierList ?: arrayListOf() }
.find { (it.importAlias?.internalName ?: it.referenceIdentifier).textMatches(element) }
?: return null
}
//maybe internalName or referencedIdentifier;
val element = file.importedElements().firstOrNull { it.textMatches(element) } ?: return null
if (element is SlintPsiReferencedIdentifier) {
val location = element.parentOfType<SlintImport>()?.moduleLocation ?: return null
val targetFile = location.reference?.resolve() as SlintFile? ?: return null
return targetFile.exportedElements()
.firstOrNull { it.nameIdentifier?.textMatches(element) == true }
}
return element
val componentName = specifier.referenceIdentifier.text
val location = specifier.parentOfType<SlintImportElement>()?.moduleLocation ?: return null
val targetFile = location.reference?.resolve()?.containingFile ?: return null
val components = searchComponent(componentName, element.project, targetFile)
return components.firstOrNull()
}
}
}

View File

@@ -17,15 +17,20 @@ class ModuleLocationReferenceProvider : PsiReferenceProvider() {
class ModuleLocationReference(element: PsiElement) : PsiReferenceBase<PsiElement?>(element) {
override fun resolve(): PsiElement? {
val location = element as SlintModuleLocation
val filename = location.stringLiteral.text
if (filename.length < 3) return null
val filenameText = location.stringLiteral.text
if (filenameText.length < 3) return null
val directory = element.containingFile.originalFile.virtualFile?.parent ?: return null
val file = VfsUtil.findRelativeFile(directory, filename.substring(1, filename.length - 1)) ?: return null
val filename = filenameText.substring(1, filenameText.length - 1)
val file = VfsUtil.findRelativeFile(directory, *filename.split("/").toTypedArray())
?: return null
return PsiManager.getInstance(element.project).findFile(file)
}
override fun calculateDefaultRangeInElement(): TextRange {
return TextRange(1, element.textLength - 1)
}
override fun bindToElement(element: PsiElement): PsiElement {
return element
}
}
}

View File

@@ -1,9 +0,0 @@
package me.zhouxi.slint.stubs
import com.intellij.psi.stubs.StubElement
import me.zhouxi.slint.lang.psi.SlintPsiNamedElement
/**
* @author zhouxi 2024/5/23
*/
interface SlintPsiStub<T : SlintPsiNamedElement?> : StubElement<T>

View File

@@ -1,15 +0,0 @@
package me.zhouxi.slint.stubs
import com.intellij.psi.stubs.IStubElementType
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.stubs.stub.SlintComponentStub
import me.zhouxi.slint.stubs.types.SlintComponentStubType
/**
* @author zhouxi 2024/5/23
*/
interface SlintStubTypes {
companion object {
// val Component: IStubElementType<SlintComponentStub, SlintComponent> = SlintComponentStubType()
}
}

View File

@@ -1,12 +0,0 @@
package me.zhouxi.slint.stubs
import com.intellij.psi.stubs.StubIndexKey
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintComponentName
/**
* @author zhouxi 2024/5/23
*/
object StubKeys {
val Component: StubIndexKey<String, SlintComponent> = StubIndexKey.createIndexKey("slint.component")
}

View File

@@ -1,21 +0,0 @@
package me.zhouxi.slint.stubs.impl
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.StubBase
import com.intellij.psi.stubs.StubElement
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.stubs.stub.SlintComponentStub
/**
* @author zhouxi 2024/5/23
*/
class SlintComponentStubImpl(
parent: StubElement<*>?,
elementType: IStubElementType<out StubElement<*>, *>,
override val exported: Boolean,
override val identifier: String,
) :
StubBase<SlintComponent>(parent, elementType), SlintComponentStub {
}

View File

@@ -1,19 +0,0 @@
package me.zhouxi.slint.stubs.impl
import com.intellij.psi.stubs.PsiFileStubImpl
import com.intellij.psi.tree.IStubFileElementType
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintFile
import me.zhouxi.slint.lang.psi.SlintTypes
import me.zhouxi.slint.stubs.stub.SlintFileStub
import me.zhouxi.slint.stubs.types.SlintComponentStubType
import me.zhouxi.slint.stubs.types.SlintFileElementType
/**
* @author zhouxi 2024/5/23
*/
class SlintFileStubImpl(file: SlintFile?) : PsiFileStubImpl<SlintFile>(file), SlintFileStub {
override fun getType() = SlintFileElementType
}