添加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

@@ -29,14 +29,14 @@ sourceSets {
}
}
group = "me.zhouxi"
version = "1.0-SNAPSHOT"
version = "0.0.1"
repositories {
mavenCentral()
}
intellij {
version.set("IU-2023.2.5")
version.set("IC-2023.2.5")
sandboxDir.set("idea-sandbox")
plugins.set(listOf("java"))
}
@@ -45,7 +45,7 @@ dependencies {
annotationProcessor("org.projectlombok:lombok:1.18.32")
testCompileOnly("org.projectlombok:lombok:1.18.32")
testAnnotationProcessor("org.projectlombok:lombok:1.18.32")
implementation("org.jetbrains:grammar-kit:2022.3.2")
// implementation("org.jetbrains:grammar-kit:2022.3.2")
}
tasks {
buildPlugin {

View File

@@ -59,9 +59,8 @@
]
extends(".*Expression")=Expression
implements(".*Keyword")=[
"me.zhouxi.slint.lang.psi.SlintPsiKeywordIdentifier"
]
implements(".*Keyword")=["me.zhouxi.slint.lang.psi.keyword.SlintPsiKeywordIdentifier"]
mixin(".*Keyword")="me.zhouxi.slint.lang.psi.keyword.SlintPsiKeywordIdentifierImpl"
}
//
Document ::= DocumentElement*
@@ -72,28 +71,35 @@ private DocumentElement ::= Import | Struct | Enum | GlobalSingleton | Component
GlobalSingleton ::= ExportKeyword? GlobalKeyword ComponentName ComponentBody {
pin=2
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementImpl"
}
//import 定义
Import ::= ImportKeyword ImportElement? ModuleLocation';'{
Import ::= ImportKeyword (ImportElement|ImportResource)';'{
pin=1
elementTypeFactory="me.zhouxi.slint.lang.psi.stubs.types.SlintStubTypes.slintImport"
stubClass="me.zhouxi.slint.lang.psi.stubs.stub.SlintImportStub"
extends="me.zhouxi.slint.lang.psi.impl.SlintStubBasedPsiElementImpl<?>"
}
private ImportElement ::= '{' ImportedSpecifier (',' ImportedSpecifier)* ','? '}' FromKeyword {
ImportElement ::= '{' ImportSpecifier (',' ImportSpecifier)* ','? '}' FromKeyword ModuleLocation{
pin=1
}
ImportResource ::= ModuleLocation
// ABc as Def
ImportedSpecifier ::= ReferenceIdentifier ImportAlias?{
ImportSpecifier ::= ReferenceIdentifier ImportAlias?{
pin=1
recoverWhile=AliasNameRecover
elementTypeFactory="me.zhouxi.slint.lang.psi.stubs.types.SlintStubTypes.importSpecifier"
stubClass="me.zhouxi.slint.lang.psi.stubs.stub.SlintImportSpecifierStub"
extends="me.zhouxi.slint.lang.psi.impl.SlintStubBasedPsiElementImpl<?>"
}
private AliasNameRecover::=!(','|'}'|';')
ImportAlias ::= AsKeyword InternalName {
pin=1
recoverWhile=AliasNameRecover
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementImpl"
}
//Struct 定义
Struct ::= ExportKeyword? StructKeyword TypeName (':=')? StructBody {
@@ -106,14 +112,13 @@ private StructBody ::= '{' FieldDeclarations? '}'{
Enum ::= ExportKeyword? EnumKeyword EnumName '{' (EnumValue (','EnumValue)*','? )? '}'{
pin=2
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementImpl"
}
//--------------ExportsList -------------------------------------
//ExportsList
Export ::= ExportKeyword ExportElement {
Export ::= ExportKeyword (ExportType | ExportModule) {
pin=1
}
private ExportElement ::= ExportType | ExportModule
ExportType ::= '{' ExportSpecifier (','ExportSpecifier)* ','? '}'{
pin=1
@@ -121,7 +126,7 @@ ExportType ::= '{' ExportSpecifier (','ExportSpecifier)* ','? '}'{
ExportSpecifier::= ReferenceIdentifier ExportAlias?{
recoverWhile=AliasNameRecover
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementImpl"
}
ExportAlias ::= AsKeyword ExternalName{
pin=1
@@ -129,21 +134,15 @@ ExportAlias ::= AsKeyword ExternalName{
ExportModule ::= '*' FromKeyword ModuleLocation ';'{
pin=1
}
//---------- component ------------------------------------------------------------
//Component ::= NewComponent
//| LegacyComponent
//Old syntax
//private LegacyComponent ::=(GlobalKeyword ComponentName ':=' ComponentName? ComponentBody)| ('global'? SubComponent)
Component ::= ExportKeyword? ComponentKeyword ComponentName InheritDeclaration? ComponentBody {
pin=2
implements=[
"me.zhouxi.slint.lang.psi.SlintPsiNamedElement"
"com.intellij.psi.StubBasedPsiElement<me.zhouxi.slint.stubs.stub.SlintComponentStub>"
]
elementTypeClass="me.zhouxi.slint.stubs.types.SlintComponentStubType"
stubClass="me.zhouxi.slint.stubs.stub.SlintComponentStub"
mixin="me.zhouxi.slint.lang.psi.impl.SlintStubBasedPsiNamedElementImpl<me.zhouxi.slint.stubs.stub.SlintComponentStub>"
elementTypeFactory="me.zhouxi.slint.lang.psi.stubs.types.SlintStubTypes.component"
stubClass="me.zhouxi.slint.lang.psi.stubs.stub.SlintComponentStub"
extends="me.zhouxi.slint.lang.psi.impl.SlintStubBasedPsiNamedElementImpl<?>"
}
//组件定义
//private LegacyComponent ::= (ComponentName|NamedIdentifier ':=' ) ComponentBody
@@ -154,12 +153,12 @@ ComponentBody ::= '{' ComponentElement* '}'{
pin=1
}
//组件元素定义
private ComponentElement ::=ChildrenPlaceholder| PropertyDeclaration | CallbackDeclaration
private ComponentElement ::=ChildrenPlaceholder| Property | Callback
| Function | PropertyAnimation | CallbackConnection | Transitions
| PropertyChanged
| States | TwoWayBinding | PropertyBinding | ConditionalElement
| RepetitionElement | SubComponent {
recoverWhile=recoverWhileForComponentBody
recoverWhile(".*")=recoverWhileForComponentBody
}
private recoverWhileForComponentBody::= !(
'property'|'callback'|'changed'
@@ -172,12 +171,16 @@ ChildrenPlaceholder ::= '@' 'children'{
}
//--------------------------------PropertyDeclaration Start----------------------------------------------------
// 属性定义 in property <type> name: value / in property <type> name <=> value
PropertyDeclaration ::= PropertyModifier? PropertyKeyword ('<' Type '>')? PropertyName(PropertyValue|PropertyTwoWayBindingValue|';'){
Property ::= PropertyModifier? PropertyKeyword ('<' Type '>')? PropertyName(PropertyValue|PropertyTwoWayBindingValue|';'){
pin=2
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
implements=[
"me.zhouxi.slint.lang.psi.SlintPsiNamedElement"
]
elementTypeFactory="me.zhouxi.slint.lang.psi.stubs.types.SlintStubTypes.property"
stubClass="me.zhouxi.slint.lang.psi.stubs.stub.SlintPropertyStub"
extends="me.zhouxi.slint.lang.psi.impl.SlintStubBasedPsiNamedElementImpl<?>"
}
private PropertyModifier ::= InKeyword|OutKeyword|InOutKeyword|PrivateKeyword
PropertyModifier ::= InKeyword|OutKeyword|InOutKeyword|PrivateKeyword
private PropertyValue::= ':' BindingStatement {
pin=1
}
@@ -190,10 +193,10 @@ PropertyChanged ::= ChangedKeyword LocalVariable '=>' CodeBlock{
}
//--------------------------------CallbackDeclaration Start----------------------------------------------------
// 回调定义 pure callback abc()->int; callback abc; callback(..);callback()->type;
CallbackDeclaration ::= PureKeyword? CallbackKeyword FunctionName CallbackBinding? ';'{
Callback ::= PureKeyword? CallbackKeyword FunctionName CallbackBinding? ';'{
pin=2
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementImpl"
}
//回调参数定义
CallbackBinding::= CallbackArgument | ('<=>'QualifiedPropertyNameReference)
@@ -215,7 +218,7 @@ TwoWayBinding ::= ReferenceIdentifier '<=>' QualifiedPropertyNameReference ';' {
Function ::= FunctionModifiers? FunctionKeyword FunctionName FunctionArguments ReturnType? CodeBlock{
pin=2
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementImpl"
}
private FunctionModifiers ::= ((PublicKeyword | ProtectedKeyword) PureKeyword?) | (PureKeyword (PublicKeyword | ProtectedKeyword)?)
@@ -246,7 +249,7 @@ RepetitionIndex ::= '[' LocalVariable ']'{
//--------------------------------SubElementDeclaration Start---------------------------------------------------
//子组件结构元素定义
SubComponent ::= (PropertyName ':=')? ReferenceIdentifier ComponentBody{
pin=2
}
//--------------------------------TransitionsDeclaration Start---------------------------------------------------
@@ -268,7 +271,7 @@ States ::= StatesKeyword '[' State* ']'{
State ::= LocalVariable StateCondition? ':' '{' StateItem* '}' {
pin=3
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementImpl"
recoverWhile=recoverForRBracket
}
private recoverForRBracket::=!(']'|'}'|';'|GenericIdentifier)
@@ -514,7 +517,7 @@ Named ::= PropertyName | TypeName |ExternalName | InternalName|ComponentName|Fu
extends("PropertyName|TypeName|ComponentName|FunctionName|InternalName|ExternalName")=Named
}
LocalVariable ::= GenericIdentifier{
mixin="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintPsiNamedElementImpl"
implements=["me.zhouxi.slint.lang.psi.SlintPsiNamedElement"]
}
FunctionName ::= GenericIdentifier
@@ -534,13 +537,13 @@ EnumValue ::=GenericIdentifier
ExternalName ::=GenericIdentifier
ReferenceIdentifier::=GenericIdentifier{
mixin="me.zhouxi.slint.lang.psi.impl.SlintReferencedIdentifierMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintReferencedIdentifierImpl"
}
//----------UnnamedIdentifier------------------
PropertyNameReference ::= GenericIdentifier{
mixin="me.zhouxi.slint.lang.psi.impl.SlintReferencedIdentifierMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintReferencedIdentifierImpl"
}
FunctionReference ::=GenericIdentifier{
@@ -555,7 +558,7 @@ QualifiedTypeNameReference ::= TypeNameReference ('.' TypeNameReference)*{
}
ModuleLocation ::= RawStringLiteral{
mixin="me.zhouxi.slint.lang.psi.impl.SlintReferencedIdentifierMixinImpl"
extends="me.zhouxi.slint.lang.psi.impl.SlintReferencedIdentifierImpl"
}
//
//noinspection BnfSuspiciousToken

View File

@@ -10,14 +10,12 @@ import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.IStubFileElementType;
import com.intellij.psi.tree.TokenSet;
import me.zhouxi.slint.lang.lexer.SlintLexer;
import me.zhouxi.slint.lang.parser.SlintParser;
import me.zhouxi.slint.lang.psi.SlintFile;
import me.zhouxi.slint.lang.psi.SlintTypes;
import me.zhouxi.slint.stubs.types.SlintComponentStubType;
import me.zhouxi.slint.stubs.types.SlintFileElementType;
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType;
import org.jetbrains.annotations.NotNull;
import static me.zhouxi.slint.lang.psi.SlintTypes.*;
@@ -54,9 +52,6 @@ public class SlintParserDefinition implements ParserDefinition {
@Override
public @NotNull PsiElement createElement(ASTNode node) {
if (node.getElementType() instanceof SlintComponentStubType) {
return ((SlintComponentStubType) node.getElementType()).createPsi(node);
}
return SlintTypes.Factory.createElement(node);
}

View File

@@ -5,7 +5,7 @@ import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.PsiFileImpl;
import me.zhouxi.slint.stubs.types.SlintFileElementType;
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType;
import org.jetbrains.annotations.NotNull;
/**

View File

@@ -1,4 +0,0 @@
package me.zhouxi.slint.lang.psi;
public interface SlintPsiKeywordIdentifier extends SlintPsiElement{
}

View File

@@ -6,9 +6,9 @@ import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry
import me.zhouxi.slint.lang.psi.SlintPsiReferencedIdentifier;
import org.jetbrains.annotations.NotNull;
public abstract class SlintReferencedIdentifierMixinImpl extends SlintPsiElementImpl implements SlintPsiReferencedIdentifier {
public abstract class SlintReferencedIdentifierImpl extends SlintPsiElementImpl implements SlintPsiReferencedIdentifier {
public SlintReferencedIdentifierMixinImpl(@NotNull ASTNode node) {
public SlintReferencedIdentifierImpl(@NotNull ASTNode node) {
super(node);
}

View File

@@ -0,0 +1,18 @@
package me.zhouxi.slint.lang.psi.impl
import com.intellij.extapi.psi.StubBasedPsiElementBase
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.stubs.IStubElementType
import com.intellij.psi.stubs.StubElement
import me.zhouxi.slint.lang.psi.SlintPsiElement
abstract class SlintStubBasedPsiElementImpl<T : StubElement<out PsiElement>> :
StubBasedPsiElementBase<T>, SlintPsiElement {
constructor(node: ASTNode) : super(node)
constructor(stub: T, nodeType: IStubElementType<*, *>) : super(stub, nodeType)
}

View File

@@ -0,0 +1,6 @@
package me.zhouxi.slint.lang.psi.keyword;
import me.zhouxi.slint.lang.psi.SlintPsiElement;
public interface SlintPsiKeywordIdentifier extends SlintPsiElement {
}

View File

@@ -0,0 +1,17 @@
package me.zhouxi.slint.lang.psi.keyword;
import com.intellij.lang.ASTNode;
import me.zhouxi.slint.lang.psi.impl.SlintPsiElementImpl;
import org.jetbrains.annotations.NotNull;
public abstract class SlintPsiKeywordIdentifierImpl extends SlintPsiElementImpl implements SlintPsiKeywordIdentifier {
public SlintPsiKeywordIdentifierImpl(@NotNull ASTNode node) {
super(node);
}
@Override
public String toString() {
return "SlintKeyword:" + getText();
}
}

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
}

View File

@@ -47,9 +47,13 @@
<runLineMarkerContributor implementationClass="me.zhouxi.slint.preview.PreviewRunLineMarkerContributor"
language="Slint"/>
<stubElementTypeHolder class="me.zhouxi.slint.stubs.SlintStubTypes" externalIdPrefix="slint."/>
<stubElementTypeHolder class="me.zhouxi.slint.lang.psi.stubs.types.SlintStubTypes" externalIdPrefix="slint."/>
<stubIndex implementation="me.zhouxi.slint.stubs.index.ComponentNameIndex"/>
<stubIndex implementation="me.zhouxi.slint.lang.psi.stubs.index.ComponentNameIndex"/>
<stubIndex implementation="me.zhouxi.slint.lang.psi.stubs.index.PropertyNameIndex"/>
<stubIndex implementation="me.zhouxi.slint.lang.psi.stubs.index.ImportNameIndex"/>
</extensions>
<actions>