添加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" group = "me.zhouxi"
version = "1.0-SNAPSHOT" version = "0.0.1"
repositories { repositories {
mavenCentral() mavenCentral()
} }
intellij { intellij {
version.set("IU-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"))
} }
@@ -45,7 +45,7 @@ dependencies {
annotationProcessor("org.projectlombok:lombok:1.18.32") annotationProcessor("org.projectlombok:lombok:1.18.32")
testCompileOnly("org.projectlombok:lombok:1.18.32") testCompileOnly("org.projectlombok:lombok:1.18.32")
testAnnotationProcessor("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 { tasks {
buildPlugin { buildPlugin {

View File

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

View File

@@ -10,14 +10,12 @@ import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.IStubFileElementType;
import com.intellij.psi.tree.TokenSet; import com.intellij.psi.tree.TokenSet;
import me.zhouxi.slint.lang.lexer.SlintLexer; import me.zhouxi.slint.lang.lexer.SlintLexer;
import me.zhouxi.slint.lang.parser.SlintParser; import me.zhouxi.slint.lang.parser.SlintParser;
import me.zhouxi.slint.lang.psi.SlintFile; import me.zhouxi.slint.lang.psi.SlintFile;
import me.zhouxi.slint.lang.psi.SlintTypes; import me.zhouxi.slint.lang.psi.SlintTypes;
import me.zhouxi.slint.stubs.types.SlintComponentStubType; import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType;
import me.zhouxi.slint.stubs.types.SlintFileElementType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import static me.zhouxi.slint.lang.psi.SlintTypes.*; import static me.zhouxi.slint.lang.psi.SlintTypes.*;
@@ -54,9 +52,6 @@ public class SlintParserDefinition implements ParserDefinition {
@Override @Override
public @NotNull PsiElement createElement(ASTNode node) { public @NotNull PsiElement createElement(ASTNode node) {
if (node.getElementType() instanceof SlintComponentStubType) {
return ((SlintComponentStubType) node.getElementType()).createPsi(node);
}
return SlintTypes.Factory.createElement(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.PsiElementVisitor;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.PsiFileImpl; 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; 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 me.zhouxi.slint.lang.psi.SlintPsiReferencedIdentifier;
import org.jetbrains.annotations.NotNull; 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); 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 package me.zhouxi.slint.completion
import com.intellij.codeInsight.completion.* import com.intellij.codeInsight.completion.CompletionContributor
import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.codeInsight.completion.CompletionType
import com.intellij.icons.AllIcons
import com.intellij.patterns.PlatformPatterns import com.intellij.patterns.PlatformPatterns
import com.intellij.psi.PsiClass import me.zhouxi.slint.completion.provider.BasicTypeProvider
import com.intellij.psi.search.GlobalSearchScope import me.zhouxi.slint.completion.provider.ComponentProvider
import com.intellij.psi.stubs.StubIndex import me.zhouxi.slint.completion.provider.ElementKeywordProvider
import com.intellij.psi.util.childrenOfType import me.zhouxi.slint.completion.provider.TopKeywordProvider
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.lang.psi.SlintTypes import me.zhouxi.slint.lang.psi.SlintTypes
import me.zhouxi.slint.lang.psi.utils.exportedElements import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
import me.zhouxi.slint.lang.psi.utils.inheritDeclaredElements
import me.zhouxi.slint.stubs.StubKeys
import me.zhouxi.slint.stubs.types.SlintFileElementType
class SlintCompletionContributor : CompletionContributor() { class SlintCompletionContributor : CompletionContributor() {
init { init {
//文件级别 //文件级别
extend( extend(
CompletionType.BASIC, CompletionType.BASIC,
PlatformPatterns.psiElement().withAncestor(4, PlatformPatterns.psiElement(SlintFileElementType)), PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintFileElementType)),
object : CompletionProvider<CompletionParameters>() { TopKeywordProvider
override fun addCompletions( )
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
result.addAllElements(TopKeywords)
}
})
//类型定义 //类型定义
extend( extend(
CompletionType.BASIC, CompletionType.BASIC,
PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintTypes.Type)), PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintTypes.Type)),
object : CompletionProvider<CompletionParameters>() { BasicTypeProvider
override fun addCompletions( )
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
result.addAllElements(BasicTypes)
}
})
//componentBody //componentBody
extend( extend(
CompletionType.BASIC, CompletionType.BASIC,
PlatformPatterns.psiElement().withAncestor(3, PlatformPatterns.psiElement(SlintTypes.ComponentBody)), PlatformPatterns.psiElement().withAncestor(2, PlatformPatterns.psiElement(SlintTypes.ComponentBody)),
object : CompletionProvider<CompletionParameters>() { ElementKeywordProvider
override fun addCompletions( )
parameters: CompletionParameters, //componentBody
context: ProcessingContext, extend(
result: CompletionResultSet CompletionType.BASIC,
) { PlatformPatterns.psiElement().withAncestor(2, PlatformPatterns.psiElement(SlintTypes.ComponentBody)),
val project = parameters.position.project ComponentProvider
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)
}
})
} }
} }
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.openapi.editor.DefaultLanguageHighlighterColors
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import me.zhouxi.slint.lang.psi.* import me.zhouxi.slint.lang.psi.*
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) {

View File

@@ -11,7 +11,7 @@ import me.zhouxi.slint.lang.psi.SlintPsiNamedElement
/** /**
* @author zhouxi 2024/5/15 * @author zhouxi 2024/5/15
*/ */
abstract class SlintPsiNamedElementMixinImpl(node: ASTNode) : SlintPsiElementImpl(node), abstract class SlintPsiNamedElementImpl(node: ASTNode) : SlintPsiElementImpl(node),
SlintPsiNamedElement { SlintPsiNamedElement {
override fun getNameIdentifier(): PsiElement? { override fun getNameIdentifier(): PsiElement? {
return findChildByClass(SlintNamed::class.java) ?: this 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.StringStubIndexExtension
import com.intellij.psi.stubs.StubIndexKey
import me.zhouxi.slint.lang.psi.SlintComponent import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.stubs.StubKeys
class ComponentNameIndex : StringStubIndexExtension<SlintComponent>() { 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.lang.psi.SlintComponent
import me.zhouxi.slint.stubs.SlintPsiStub
/** /**
* @author zhouxi 2024/5/23 * @author zhouxi 2024/5/23
@@ -9,5 +8,5 @@ import me.zhouxi.slint.stubs.SlintPsiStub
interface SlintComponentStub : SlintPsiStub<SlintComponent> { interface SlintComponentStub : SlintPsiStub<SlintComponent> {
val exported: Boolean 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 com.intellij.psi.stubs.PsiFileStub
import me.zhouxi.slint.lang.psi.SlintComponent import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintFile import me.zhouxi.slint.lang.psi.SlintFile
import me.zhouxi.slint.lang.psi.SlintTypes 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> { 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.ASTNode
import com.intellij.lang.LighterAST import com.intellij.lang.LighterAST
import com.intellij.lang.LighterASTNode import com.intellij.lang.LighterASTNode
import com.intellij.lang.LighterASTTokenNode import com.intellij.lang.LighterASTTokenNode
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement 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.stubs.*
import com.intellij.psi.util.parentOfType
import me.zhouxi.slint.lang.SlintLanguage import me.zhouxi.slint.lang.SlintLanguage
import me.zhouxi.slint.lang.psi.SlintComponent 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.SlintTypes.*
import me.zhouxi.slint.lang.psi.impl.SlintComponentImpl import me.zhouxi.slint.lang.psi.impl.SlintComponentImpl
import me.zhouxi.slint.stubs.StubKeys import me.zhouxi.slint.lang.psi.stubs.stub.impl.SlintComponentStubImpl
import me.zhouxi.slint.stubs.impl.SlintComponentStubImpl import me.zhouxi.slint.lang.psi.stubs.index.StubIndexKeys
import me.zhouxi.slint.stubs.stub.SlintComponentStub import me.zhouxi.slint.lang.psi.stubs.stub.SlintComponentStub
import java.io.IOException import java.io.IOException
/** /**
* @author zhouxi 2024/5/23 * @author zhouxi 2024/5/23
*/ */
class SlintComponentStubType(debugName: String) : object SlintComponentElementType :
ILightStubElementType<SlintComponentStub, SlintComponent>(debugName, SlintLanguage.INSTANCE) { ILightStubElementType<SlintComponentStub, SlintComponent>("Component", SlintLanguage.INSTANCE) {
override fun createPsi(stub: SlintComponentStub): SlintComponent { override fun createPsi(stub: SlintComponentStub): SlintComponent {
return SlintComponentImpl(stub, this) return SlintComponentImpl(stub, this)
} }
@@ -36,7 +31,6 @@ class SlintComponentStubType(debugName: String) :
override fun createStub(psi: SlintComponent, parentStub: StubElement<out PsiElement?>): SlintComponentStub { override fun createStub(psi: SlintComponent, parentStub: StubElement<out PsiElement?>): SlintComponentStub {
return SlintComponentStubImpl( return SlintComponentStubImpl(
parentStub, parentStub,
this,
psi.exportKeyword != null, psi.exportKeyword != null,
psi.componentName!!.text psi.componentName!!.text
) )
@@ -49,14 +43,14 @@ class SlintComponentStubType(debugName: String) :
@Throws(IOException::class) @Throws(IOException::class)
override fun serialize(stub: SlintComponentStub, dataStream: StubOutputStream) { override fun serialize(stub: SlintComponentStub, dataStream: StubOutputStream) {
dataStream.writeBoolean(stub.exported) dataStream.writeBoolean(stub.exported)
dataStream.writeName(stub.identifier) dataStream.writeName(stub.componentName)
} }
@Throws(IOException::class) @Throws(IOException::class)
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): SlintComponentStub { override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>): SlintComponentStub {
val exported = dataStream.readBoolean() val exported = dataStream.readBoolean()
val identifier = dataStream.readNameString() 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 { 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 identifier = tree.getChildren(node).first { it.tokenType == ComponentName }
val token = tree.getChildren(identifier)[0] as LighterASTTokenNode 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) { 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.StubElement
import com.intellij.psi.stubs.StubInputStream import com.intellij.psi.stubs.StubInputStream
import com.intellij.psi.tree.ILightStubFileElementType import com.intellij.psi.tree.ILightStubFileElementType
import me.zhouxi.slint.lang.SlintLanguage import me.zhouxi.slint.lang.SlintLanguage
import me.zhouxi.slint.stubs.impl.SlintFileStubImpl import me.zhouxi.slint.lang.psi.stubs.stub.impl.SlintFileStubImpl
import me.zhouxi.slint.stubs.stub.SlintFileStub import me.zhouxi.slint.lang.psi.stubs.stub.SlintFileStub
object SlintFileElementType : ILightStubFileElementType<SlintFileStub>("SlintFile", SlintLanguage.INSTANCE) { object SlintFileElementType : ILightStubFileElementType<SlintFileStub>("SlintFile", SlintLanguage.INSTANCE) {
override fun getStubVersion(): Int { override fun getStubVersion() = 1
return 1
}
override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?): SlintFileStub { override fun deserialize(dataStream: StubInputStream, parentStub: StubElement<*>?) = SlintFileStubImpl(null)
return 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( fun searchProperty(
component: PsiElement?, component: PsiElement?,
predicate: Predicate<SlintPropertyDeclaration> predicate: Predicate<SlintProperty>
): SlintPropertyDeclaration? { ): SlintProperty? {
if (component is SlintSubComponent) { if (component is SlintSubComponent) {
return searchProperty(component, predicate) return searchProperty(component, predicate)
} }
if (component is SlintComponent) { if (component is SlintComponent) {
return searchElementInParents(component, predicate) { it.componentBody?.propertyDeclarationList } return searchElementInParents(component, predicate) { it.componentBody?.propertyList }
} }
return null return null
} }
fun searchProperty( fun searchProperty(
subComponent: SlintSubComponent?, subComponent: SlintSubComponent?,
predicate: Predicate<SlintPropertyDeclaration> predicate: Predicate<SlintProperty>
): SlintPropertyDeclaration? { ): SlintProperty? {
val component = resolveComponent(subComponent?.referenceIdentifier) ?: return null val component = resolveComponent(subComponent?.referenceIdentifier) ?: return null
return searchElementInParents(component, predicate) { it.componentBody?.propertyDeclarationList } return searchElementInParents(component, predicate) { it.componentBody?.propertyList }
} }
fun searchCallback( fun searchCallback(
subComponent: SlintSubComponent?, subComponent: SlintSubComponent?,
predicate: Predicate<SlintCallbackDeclaration> predicate: Predicate<SlintCallback>
): SlintCallbackDeclaration? { ): SlintCallback? {
val component = subComponent?.referenceIdentifier?.reference?.resolve() ?: return null val component = subComponent?.referenceIdentifier?.reference?.resolve() ?: return null
return searchElementInParents( return searchElementInParents(
component as SlintComponent, component as SlintComponent,
predicate predicate
) { it.componentBody?.callbackDeclarationList } ) { it.componentBody?.callbackList }
} }
fun <T> searchElementInParents( fun <T> searchElementInParents(
@@ -118,14 +118,14 @@ fun <T> searchElementInParents(
} }
fun SlintComponent.currentDeclaredElements(): List<SlintPsiNamedElement> { fun SlintComponent.currentDeclaredElements(): List<SlintPsiNamedElement> {
val properties = this.componentBody?.propertyDeclarationList ?: emptyList() val properties = this.componentBody?.propertyList ?: emptyList()
val callbacks = this.componentBody?.callbackDeclarationList ?: emptyList() val callbacks = this.componentBody?.callbackList ?: emptyList()
return properties + callbacks return properties + callbacks
} }
fun SlintComponent.inheritDeclaredElements(): List<SlintPsiNamedElement> { fun SlintComponent.inheritDeclaredElements(): List<SlintPsiNamedElement> {
val properties = this.componentBody?.propertyDeclarationList ?: emptyList() val properties = this.componentBody?.propertyList ?: emptyList()
val callbacks = this.componentBody?.callbackDeclarationList ?: emptyList() val callbacks = this.componentBody?.callbackList ?: emptyList()
val inheritedComponent = resolveReferencedComponent(this.inheritDeclaration?.referenceIdentifier) val inheritedComponent = resolveReferencedComponent(this.inheritDeclaration?.referenceIdentifier)
?: return properties + callbacks ?: return properties + callbacks
return properties + callbacks + inheritedComponent.inheritDeclaredElements() return properties + callbacks + inheritedComponent.inheritDeclaredElements()

View File

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

View File

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

View File

@@ -17,15 +17,20 @@ class ModuleLocationReferenceProvider : PsiReferenceProvider() {
class ModuleLocationReference(element: PsiElement) : PsiReferenceBase<PsiElement?>(element) { class ModuleLocationReference(element: PsiElement) : PsiReferenceBase<PsiElement?>(element) {
override fun resolve(): PsiElement? { override fun resolve(): PsiElement? {
val location = element as SlintModuleLocation val location = element as SlintModuleLocation
val filename = location.stringLiteral.text val filenameText = location.stringLiteral.text
if (filename.length < 3) return null if (filenameText.length < 3) return null
val directory = element.containingFile.originalFile.virtualFile?.parent ?: 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) return PsiManager.getInstance(element.project).findFile(file)
} }
override fun calculateDefaultRangeInElement(): TextRange { override fun calculateDefaultRangeInElement(): TextRange {
return TextRange(1, element.textLength - 1) 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" <runLineMarkerContributor implementationClass="me.zhouxi.slint.preview.PreviewRunLineMarkerContributor"
language="Slint"/> 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> </extensions>
<actions> <actions>