diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6dcf081d1f4524c59f36726cbdf1aa5cf08f78cd..5f577a152c921d81814a44d3f9964c5fdd7ffca3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,6 +4,12 @@ stages: - jar - deploy +test: + image: openjdk:11 + stage: test + script: + - ./gradlew --continue --console=plain --info runPluginVerifier + jar: image: openjdk:11 stage: jar @@ -11,4 +17,4 @@ jar: - ./gradlew --continue --console=plain --info buildPlugin artifacts: paths: - - "/builds/jastadd/*/build/libs/JastAddGrammar-*.jar" + - "/builds/jastadd/*/build/libs/JastAddIntelliJPlugin-*.jar" diff --git a/CHANGELOG.md b/CHANGELOG.md index d4ce6b3735ade0fd6ea295c13df5dd3f02576c42..b03834d3988b4bb53aca8ff01d9e8f0cbccb696e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## [Unreleased] ### Added +- Reference support for type names within aspect files. + - usages are now highlighted +- Refactoring of type names now also works in aspects. + - Note that although it works in the Java embeddings within aspects, it does *not* work in "real" Java classes. + - Please use this feature with caution. As with most refactoring tools, it is quite fragile and won't give correct + results in all cases. ### Changed @@ -10,6 +16,7 @@ ### Removed ### Fixed +- A bug for type name refactoring in grammar files which prevented the actual definition from being renamed. ## [0.2.0] diff --git a/gradle.properties b/gradle.properties index b7faee122811ad55bd7686ba423947690f840e73..6ce3358a0efab352ed1cdd8d8c8eb8c2eb43989a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ pluginGroup = org.jastadd pluginName = JastAdd -pluginVersion = 0.2.0 +pluginVersion = 0.3.0 # See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html # for insight into build numbers and IntelliJ Platform versions. @@ -15,7 +15,7 @@ pluginUntilBuild = 212.* pluginVerifierIdeVersions = 2021.1.1, 2021.1.2, 2021.1.3, 2021.2.3 platformType = IC -platformVersion = 2021.1.1 +platformVersion = 2021.2.3 platformDownloadSources = true # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html diff --git a/settings.gradle.kts b/settings.gradle.kts index 2f0d5d41705f0afcd0af77de1b01f669f2825d8b..295fd94044af0021c291330ac5fdbde79d11623b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,2 +1,2 @@ -rootProject.name = "JastAddGrammar" +rootProject.name = "JastAddIntelliJPlugin" diff --git a/src/main/grammar/Aspect.bnf b/src/main/grammar/Aspect.bnf index 66baaec571ba7781a79e0955fbba30e9e9926a41..a11bb754aed3982b9eb69900f59c5b0f63c5df13 100644 --- a/src/main/grammar/Aspect.bnf +++ b/src/main/grammar/Aspect.bnf @@ -26,24 +26,6 @@ ] } - - - -//attribute_equation ::= EQ java_block -// -//java_block ::= JAVABLOCK -//{ -// implements="org.jastadd.tooling.aspect.psi.JastAddAspectJavaExtension" -// extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectJavaImplExtension" -//} - -// aspect_body_declarations_eof ::= aspect_body_declaration* EOF - - -//jastaddAspectFile ::= ( aspect_declaration | comment )* -// -//comment ::= (MULTI_LINE_COMMENT | DOC_COMMENT | SINGLE_LINE_COMMENT) - compilation_unit ::= import_declaration* type_declaration* import_declaration ::= IMPORT STATIC? name_name (DOT STAR)? SEMICOLON @@ -119,50 +101,50 @@ aspect_nested_interface_declaration ::= modifiers interface_declaration // TODO check if simplification is okay aspect_nested_class_declaration ::= modifiers class_declaration -aspect_method_declaration ::= modifiers type_parameters? aspect_result_type IDENTIFIER DOT method_declarator (THROWS name_list)? (block | SEMICOLON) +aspect_method_declaration ::= modifiers type_parameters? aspect_result_type ast_type_name DOT method_declarator (THROWS name_list)? (block | SEMICOLON) aspect_refine_method_declaration ::= REFINE [IDENTIFIER] modifiers type_parameters? aspect_result_type IDENTIFIER DOT method_declarator (THROWS name_list)? (block | SEMICOLON) -aspect_constructor_declaration ::= modifiers IDENTIFIER DOT IDENTIFIER formal_parameters (THROWS name_list)? LBRACE explicit_constructor_invocation? block_statement* RBRACE +aspect_constructor_declaration ::= modifiers ast_type_name DOT ast_type_name formal_parameters (THROWS name_list)? LBRACE explicit_constructor_invocation? block_statement* RBRACE -aspect_refine_constructor_declaration ::= REFINE IDENTIFIER (PUBLIC | PROTECTED | PRIVATE) IDENTIFIER DOT IDENTIFIER formal_parameters (THROWS name_list)? LBRACE block_statement* RBRACE +aspect_refine_constructor_declaration ::= REFINE IDENTIFIER (PUBLIC | PROTECTED | PRIVATE) ast_type_name DOT IDENTIFIER formal_parameters (THROWS name_list)? LBRACE block_statement* RBRACE -aspect_field_declaration ::= modifiers aspect_type IDENTIFIER DOT variable_declarator (COMMA variable_declarator)* SEMICOLON +aspect_field_declaration ::= modifiers aspect_type ast_type_name DOT variable_declarator (COMMA variable_declarator)* SEMICOLON -aspect_syn_attribute_declaration ::= annotation* SYN NTA? LAZY? FINAL? aspect_type IDENTIFIER DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)* )? RPAREN (CIRCULAR LBRACKET expression RBRACKET)? ( ASSIGN expression SEMICOLON | block | SEMICOLON ) +aspect_syn_attribute_declaration ::= annotation* SYN NTA? LAZY? FINAL? aspect_type ast_type_name DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)* )? RPAREN (CIRCULAR LBRACKET expression RBRACKET)? ( ASSIGN expression SEMICOLON | block | SEMICOLON ) { implements="org.jastadd.tooling.aspect.psi.JastAddAspectAttribute" extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectSynAttributeImpl" } -aspect_inh_attribute_declaration ::= annotation* INH NTA? LAZY? FINAL? aspect_type IDENTIFIER DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)* )? RPAREN (CIRCULAR LBRACKET expression RBRACKET)? SEMICOLON +aspect_inh_attribute_declaration ::= annotation* INH NTA? LAZY? FINAL? aspect_type ast_type_name DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)* )? RPAREN (CIRCULAR LBRACKET expression RBRACKET)? SEMICOLON { implements="org.jastadd.tooling.aspect.psi.JastAddAspectAttribute" extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectInhAttributeImpl" } // FIXME parentheses are not required around the WHEN expression? -aspect_rewrite ::= REWRITE IDENTIFIER (IDENTIFIER DOT IDENTIFIER LPAREN RPAREN)? LBRACE ((WHEN LPAREN expression RPAREN)? TO aspect_type ( expression SEMICOLON | block ))+ RBRACE +aspect_rewrite ::= REWRITE IDENTIFIER (ast_type_name DOT IDENTIFIER LPAREN RPAREN)? LBRACE ((WHEN LPAREN expression RPAREN)? TO aspect_type ( expression SEMICOLON | block ))+ RBRACE -aspect_syn_equation ::= annotation* EQUATION IDENTIFIER DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)*)? RPAREN ( ASSIGN expression SEMICOLON | block ) +aspect_syn_equation ::= annotation* EQUATION ast_type_name DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)*)? RPAREN ( ASSIGN expression SEMICOLON | block ) -aspect_refine_syn_equation ::= REFINE IDENTIFIER EQUATION IDENTIFIER DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)*)? RPAREN (ASSIGN expression SEMICOLON | block) +aspect_refine_syn_equation ::= REFINE IDENTIFIER EQUATION ast_type_name DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)*)? RPAREN (ASSIGN expression SEMICOLON | block) -aspect_inh_equation ::= annotation* EQUATION IDENTIFIER DOT IDENTIFIER LPAREN (INT IDENTIFIER)? RPAREN DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)*)? RPAREN (ASSIGN expression SEMICOLON | block) +aspect_inh_equation ::= annotation* EQUATION ast_type_name DOT IDENTIFIER LPAREN (INT IDENTIFIER)? RPAREN DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)*)? RPAREN (ASSIGN expression SEMICOLON | block) -aspect_refine_inh_equation ::= REFINE IDENTIFIER EQUATION IDENTIFIER DOT IDENTIFIER LPAREN (INT IDENTIFIER)? RPAREN DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)*)? RPAREN (ASSIGN expression SEMICOLON | block) +aspect_refine_inh_equation ::= REFINE IDENTIFIER EQUATION ast_type_name DOT IDENTIFIER LPAREN (INT IDENTIFIER)? RPAREN DOT attribute_name LPAREN (type IDENTIFIER (COMMA type IDENTIFIER)*)? RPAREN (ASSIGN expression SEMICOLON | block) -collection_attribute ::= annotation* COLL aspect_type IDENTIFIER DOT attribute_name LPAREN RPAREN CIRCULAR? (LBRACKET expression RBRACKET)? (WITH IDENTIFIER)? (ROOT IDENTIFIER)? SEMICOLON +collection_attribute ::= annotation* COLL aspect_type ast_type_name DOT attribute_name LPAREN RPAREN CIRCULAR? (LBRACKET expression RBRACKET)? (WITH IDENTIFIER)? (ROOT IDENTIFIER)? SEMICOLON { implements="org.jastadd.tooling.aspect.psi.JastAddAspectAttribute" extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectCollAttributeImpl" } -collection_contribution ::= annotation* IDENTIFIER CONTRIBUTES ( NTA expression TO IDENTIFIER DOT attribute_name LPAREN RPAREN | EACH? expression (WHEN expression)? TO IDENTIFIER DOT attribute_name LPAREN RPAREN (FOR EACH? expression)? | block TO IDENTIFIER DOT attribute_name LPAREN RPAREN ) SEMICOLON +collection_contribution ::= annotation* ast_type_name CONTRIBUTES ( NTA expression TO ast_type_name DOT attribute_name LPAREN RPAREN | EACH? expression (WHEN expression)? TO ast_type_name DOT attribute_name LPAREN RPAREN (FOR EACH? expression)? | block TO ast_type_name DOT attribute_name LPAREN RPAREN ) SEMICOLON -aspect_add_interface ::= IDENTIFIER IMPLEMENTS type_name_list SEMICOLON +aspect_add_interface ::= ast_type_name IMPLEMENTS type_name_list SEMICOLON -aspect_extend_interface ::= IDENTIFIER EXTENDS type_name_list SEMICOLON +aspect_extend_interface ::= ast_type_name EXTENDS type_name_list SEMICOLON class_declaration ::= CLASS IDENTIFIER type_parameters? (EXTENDS class_or_interface_type)? (implements type_name_list)? class_body @@ -179,11 +161,11 @@ enum_body ::= LBRACE enum_constant (COMMA enum_constant)* (SEMICOLON class_body_ enum_constant ::= java_identifier arguments? class_body? - type_parameters ::= LT type_parameter (COMMA type_parameter)* GT +type_parameters ::= LT type_parameter (COMMA type_parameter)* GT - type_parameter ::= java_identifier type_bound? +type_parameter ::= java_identifier type_bound? - type_bound ::= EXTENDS class_or_interface_type (AMPERSAND class_or_interface_type)* +type_bound ::= EXTENDS class_or_interface_type (AMPERSAND class_or_interface_type)* class_body ::= LBRACE class_body_declaration* RBRACE @@ -226,13 +208,17 @@ aspect_result_type ::= VOID | aspect_type aspect_reference_type ::= aspect_class_or_interface_type (LBRACKET RBRACKET)* -aspect_class_or_interface_type ::= IDENTIFIER type_arguments? (DOT java_identifier type_arguments? )* +aspect_class_or_interface_type ::= ast_type_name type_arguments? (DOT java_identifier type_arguments? )* type ::= reference_type | primitive_type reference_type ::= ( primitive_type (LBRACKET RBRACKET)+ ) | ( class_or_interface_type (LBRACKET RBRACKET)* ) class_or_interface_type ::= java_identifier type_arguments? (DOT java_identifier type_arguments? )* +{ + extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectClassOrInterfaceTypeImplExtension" + implements="org.jastadd.tooling.grammar.psi.GrammarNamedElement" +} type_arguments ::= LT (type_argument (COMMA type_argument)* )? GT @@ -404,17 +390,11 @@ java_identifier ::= IDENTIFIER | INH | SYN | LAZY | REWRITE | TO | WHEN | ASPECT attribute_name ::= IDENTIFIER -// EOF - -// unused keywords +ast_type_name ::= IDENTIFIER +{ + extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectAstTypeNameImplExtension" + implements="org.jastadd.tooling.grammar.psi.GrammarNamedElement" +} +// unused keywords must still appear somewhere unused_keywords ::= GOTO | CONST ELLIPSIS | PACKAGE - -// island things - -//// should be parsed after circular and in collection attributes -//expression_in_brackets ::= LBRACKET_ANYTHING_RBRACKET // LBRACKET expression RBRACKET -//{ -// implements="org.jastadd.tooling.aspect.psi.JastAddAspectJavaExtension" -// extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectJavaImplExtension" -//} diff --git a/src/main/grammar/Aspect.flex b/src/main/grammar/Aspect.flex index dce79a03c8df1a1c25ed0e2aedb9eb022e03348f..671249c9a3a6c97ba3d764f5297f2604aa92dc1d 100644 --- a/src/main/grammar/Aspect.flex +++ b/src/main/grammar/Aspect.flex @@ -12,7 +12,7 @@ import com.intellij.psi.TokenType; %unicode %function advance %type IElementType -%eof{ return; +%eof{ %eof} %{ @@ -37,10 +37,6 @@ SingleLineComment = "//" [^\n\r]* (\n | \r | \r\n) FormalComment = "/**" [^*]* [*]+([^*/][^*]*[*]+)*[/] MultiLineComment = "/*" [^*]+ [*]+([^*/][^*]*[*]+)*[/] - -NotBrace = ( [^{}/]+ | [/][^{}/*] )+ -NotBracket = ( [^\[\]/]+ | [/][^\[\]/*] )+ - // from jjt DecimalLiteral = [1-9] [0-9]* HexLiteral = 0 [xX] [0-9a-fA-F]+ diff --git a/src/main/grammar/Grammar.bnf b/src/main/grammar/Grammar.bnf index 5de306140c7aea29b0cc1fa45f6eb812fe8a9680..df4ab340fe111e7d0c0c3d3b8f11ffa0d52f0a20 100644 --- a/src/main/grammar/Grammar.bnf +++ b/src/main/grammar/Grammar.bnf @@ -19,15 +19,15 @@ GrammarFile ::= comment* ((type_decl | relation) comment*)* comment ::= (WHITESPACE | MULTILINECOMMENT | DOCCOMMENT | SINGLELINECOMMENT) -type_decl ::= ABSTRACT? declared_name (COL type_reference)? (ASSIGN (component | nta_component)*)? SCOL +type_decl ::= ABSTRACT? type_name (COL type_name)? (ASSIGN (component | nta_component)*)? SCOL { extends="org.jastadd.tooling.grammar.psi.impl.GrammarTypeDeclImplExtension" - implements="org.jastadd.tooling.grammar.psi.GrammarTypeDeclExtension" + implements="org.jastadd.tooling.grammar.psi.GrammarNamedElement" } nta_component ::= SLASH component SLASH -component ::= (declared_name COL type_reference STAR?) | (type_reference STAR?) | (LBRACKET declared_name COL type_reference RBRACKET) | (LBRACKET type_reference RBRACKET) | (LT declared_name (COL (java_type_use))? GT) +component ::= (component_name COL type_name STAR?) | (type_name STAR?) | (LBRACKET component_name COL type_name RBRACKET) | (LBRACKET type_name RBRACKET) | (LT component_name (COL (java_type_use))? GT) java_type_use ::= parameterized_java_type_use | simple_java_type_use @@ -37,16 +37,24 @@ simple_java_type_use ::= java_name (DOT java_name)* relation ::= REL ((unnamed_role LEFT navigable_role) | (navigable_role RIGHT unnamed_role) | (navigable_role BIDIRECTIONAL navigable_role)) SCOL -unnamed_role ::= type_reference | navigable_role +unnamed_role ::= type_name | navigable_role -navigable_role ::= type_reference DOT declared_name (STAR | QUESTION_MARK)? +navigable_role ::= type_name DOT component_name (STAR | QUESTION_MARK)? -// for auto-completion, it is helpful if we can distinguish the different IDs -declared_name ::= ID -type_reference ::= ID +//// for auto-completion, it is helpful if we can distinguish the different IDs +//type_name ::= ID + +type_name ::= ID { - extends="org.jastadd.tooling.grammar.psi.impl.GrammarTypeReferenceImplExtension" - implements="org.jastadd.tooling.grammar.psi.GrammarTypeReferenceExtension" + extends="org.jastadd.tooling.grammar.psi.impl.GrammarTypeNameImplExtension" + implements="org.jastadd.tooling.grammar.psi.GrammarNamedElement" } +component_name ::= ID +{ + extends="org.jastadd.tooling.grammar.psi.impl.GrammarComponentNameImplExtension" + implements="org.jastadd.tooling.grammar.psi.GrammarNamedElement" +} + + java_name ::= ID diff --git a/src/main/grammar/Grammar.flex b/src/main/grammar/Grammar.flex index 3f8006a0e296c7f371112ed2bac6cdf849b294db..43ff67a073b74d98a95e1c5b589851d320f1e483 100644 --- a/src/main/grammar/Grammar.flex +++ b/src/main/grammar/Grammar.flex @@ -13,7 +13,7 @@ import com.intellij.psi.TokenType; %unicode %function advance %type IElementType -%eof{ return; +%eof{ %eof} diff --git a/src/main/java/org/jastadd/tooling/aspect/AspectFileType.java b/src/main/java/org/jastadd/tooling/aspect/AspectFileType.java index cdfd30057acece4fdb07ee4aa50a6860451a5d75..1c09a318af6f72f8958891264e22c78410d2907d 100644 --- a/src/main/java/org/jastadd/tooling/aspect/AspectFileType.java +++ b/src/main/java/org/jastadd/tooling/aspect/AspectFileType.java @@ -2,6 +2,7 @@ package org.jastadd.tooling.aspect; import com.intellij.openapi.fileTypes.LanguageFileType; import org.jastadd.tooling.util.JastAddIcons; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -21,6 +22,11 @@ public class AspectFileType extends LanguageFileType { return "JastAdd Aspect"; } + @Override + public @Nls @NotNull String getDisplayName() { + return getName(); + } + @NotNull @Override public String getDescription() { diff --git a/src/main/java/org/jastadd/tooling/aspect/AspectReferenceContributor.java b/src/main/java/org/jastadd/tooling/aspect/AspectReferenceContributor.java new file mode 100644 index 0000000000000000000000000000000000000000..6a86c3afbc287f5c9adb6b884c44ca521680b306 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/AspectReferenceContributor.java @@ -0,0 +1,50 @@ +package org.jastadd.tooling.aspect; + +import com.intellij.openapi.util.TextRange; +import com.intellij.patterns.PlatformPatterns; +import com.intellij.psi.*; +import com.intellij.util.ProcessingContext; +import org.jastadd.tooling.aspect.psi.JastAddAspectAstTypeName; +import org.jastadd.tooling.aspect.psi.JastAddAspectClassOrInterfaceType; +import org.jastadd.tooling.grammar.GrammarReference; +import org.jetbrains.annotations.NotNull; + +public class AspectReferenceContributor extends PsiReferenceContributor { + + @Override + public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { + registrar.registerReferenceProvider(PlatformPatterns.psiElement(JastAddAspectAstTypeName.class), + new PsiReferenceProvider() { + @NotNull + @Override + public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, + @NotNull ProcessingContext context) { + JastAddAspectAstTypeName astTypeName = (JastAddAspectAstTypeName) element; + String value = astTypeName.getText(); + if (value != null) { + TextRange range = new TextRange(0, value.length()); + return new PsiReference[]{new GrammarReference(element, range)}; + } + return PsiReference.EMPTY_ARRAY; + } + }); + registrar.registerReferenceProvider(PlatformPatterns.psiElement(JastAddAspectClassOrInterfaceType.class), + new PsiReferenceProvider() { + @NotNull + @Override + public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, + @NotNull ProcessingContext context) { + JastAddAspectClassOrInterfaceType classOrInterfaceType = (JastAddAspectClassOrInterfaceType) element; + if (classOrInterfaceType.getTypeArgumentsList().isEmpty() && classOrInterfaceType.getJavaIdentifierList().size() == 1) { + String value = classOrInterfaceType.getJavaIdentifierList().get(0).getText(); + if (value != null) { + TextRange range = new TextRange(0, value.length()); + return new PsiReference[]{new GrammarReference(element, range)}; + } + } + return PsiReference.EMPTY_ARRAY; + } + }); + } + +} diff --git a/src/main/java/org/jastadd/tooling/aspect/AspectSyntaxHighlighter.java b/src/main/java/org/jastadd/tooling/aspect/AspectSyntaxHighlighter.java index 4f44cb07d6504401460d79fa8038bfeaaea729ee..1c91d8e82aa7345cbd9be27b016d4abe2323e331 100644 --- a/src/main/java/org/jastadd/tooling/aspect/AspectSyntaxHighlighter.java +++ b/src/main/java/org/jastadd/tooling/aspect/AspectSyntaxHighlighter.java @@ -103,22 +103,8 @@ public class AspectSyntaxHighlighter extends SyntaxHighlighterBase { // unclear // TODO unclear IO // TODO missing AT_NAME - // TODO unused NOTPARENTHESIS // TODO combined DOT_CLASS - // islands - // public static final TextAttributesKey CLASS_BODY_UNSUPPORTED = createTextAttributesKey("ASPECT_CLASS_BODY_UNSUPPORTED", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey CLASS_ANYTHING_LBRACE_ANYTHING_RBRACE = createTextAttributesKey("ASPECT_CLASS_ANYTHING_LBRACE_ANYTHING_RBRACE", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey INTERFACE_ANYTHING_LBRACE_ANYTHING_RBRACE = createTextAttributesKey("ASPECT_INTERFACE_ANYTHING_LBRACE_ANYTHING_RBRACE", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey AT_NAME_LPAREN_ANYTHING_RPAREN = createTextAttributesKey("ASPECT_AT_NAME_LPAREN_ANYTHING_RPAREN", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey AT_INTERFACE_ANYTHING_LBRACE_ANYTHING_RBRACE = createTextAttributesKey("ASPECT_AT_INTERFACE_ANYTHING_LBRACE_ANYTHING_RBRACE", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey ENUM_ANYTHING_LBRACE_ANYTHING_RBRACE = createTextAttributesKey("ASPECT_ENUM_ANYTHING_LBRACE_ANYTHING_RBRACE", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey STATEMENT = createTextAttributesKey("ASPECT_STATEMENT", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey LBRACE_ANYTHING_RBRACE = createTextAttributesKey("ASPECT_LBRACE_ANYTHING_RBRACE", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey LBRACKET_ANYTHING_RBRACKET = createTextAttributesKey("ASPECT_LBRACKET_ANYTHING_RBRACKET", DefaultLanguageHighlighterColors.); - // public static final TextAttributesKey JAVA_EXPLICIT_CONSTRUCTUR_BLOCK = createTextAttributesKey("ASPECT_JAVA_EXPLICIT_CONSTRUCTUR_BLOCK", DefaultLanguageHighlighterColors.); - - public static final TextAttributesKey BAD_CHARACTER = createTextAttributesKey("JASTADD_BAD_CHARACTER", HighlighterColors.BAD_CHARACTER); diff --git a/src/main/java/org/jastadd/tooling/aspect/AttributeFileType.java b/src/main/java/org/jastadd/tooling/aspect/AttributeFileType.java index a1f0720468f90b304f8b2c2e102442b4ca31b0cc..9db0f85d7be5e57870b66119ae61bc944c16f8b1 100644 --- a/src/main/java/org/jastadd/tooling/aspect/AttributeFileType.java +++ b/src/main/java/org/jastadd/tooling/aspect/AttributeFileType.java @@ -2,6 +2,7 @@ package org.jastadd.tooling.aspect; import com.intellij.openapi.fileTypes.LanguageFileType; import org.jastadd.tooling.util.JastAddIcons; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -21,6 +22,11 @@ public class AttributeFileType extends LanguageFileType { return "JastAdd Attribute Aspect"; } + @Override + public @Nls @NotNull String getDisplayName() { + return getName(); + } + @NotNull @Override public String getDescription() { diff --git a/src/main/java/org/jastadd/tooling/aspect/JavaLanguageInjector.java b/src/main/java/org/jastadd/tooling/aspect/JavaLanguageInjector.java index 58036e3cced547b1c0af6a0a12d4836bbddcbe71..8039be6810d627efe799c4fc2c2af62183aca2cc 100644 --- a/src/main/java/org/jastadd/tooling/aspect/JavaLanguageInjector.java +++ b/src/main/java/org/jastadd/tooling/aspect/JavaLanguageInjector.java @@ -6,7 +6,9 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.InjectedLanguagePlaces; import com.intellij.psi.LanguageInjector; import com.intellij.psi.PsiLanguageInjectionHost; -import org.jastadd.tooling.aspect.psi.*; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectClassDeclaration; +import org.jastadd.tooling.aspect.psi.JastAddAspectBlock; +import org.jastadd.tooling.aspect.psi.JastAddAspectExpression; import org.jetbrains.annotations.NotNull; public class JavaLanguageInjector implements LanguageInjector { diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/AspectElementFactory.java b/src/main/java/org/jastadd/tooling/aspect/psi/AspectElementFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..575b08a8d95c3e09a06a0849ec22306d4825291b --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/psi/AspectElementFactory.java @@ -0,0 +1,37 @@ +package org.jastadd.tooling.aspect.psi; + +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFileFactory; +import org.jastadd.tooling.aspect.AspectFileType; + +public class AspectElementFactory { + + private AspectElementFactory() { + throw new IllegalStateException("Utility class"); + } + + public static JastAddAspectAstTypeName createAstTypeName(Project project, String name) { + final AspectFile file = createFile(project, "aspect A{syn int " + name + ".attributeName();}"); + PsiElement result = file.getFirstChild().findElementAt(17); + if (result != null) { + return (JastAddAspectAstTypeName) result.getParent(); + } + return null; + } + + public static JastAddAspectClassOrInterfaceType createClassOrInterfaceType(Project project, String name) { + final AspectFile file = createFile(project, "aspect Navigation{X<" + name + "> X.z=0;}"); + PsiElement result = file.getFirstChild().findElementAt(20); + if (result != null) { + return (JastAddAspectClassOrInterfaceType) result.getParent().getParent(); + } + return null; + } + + public static AspectFile createFile(Project project, String text) { + String name = "dummy.jrag"; + return (AspectFile) PsiFileFactory.getInstance(project). + createFileFromText(name, AspectFileType.INSTANCE, text); + } +} diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectAstTypeNameManipulator.java b/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectAstTypeNameManipulator.java new file mode 100644 index 0000000000000000000000000000000000000000..894ddf86ad0abd17601fb882e258510de93e09ff --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectAstTypeNameManipulator.java @@ -0,0 +1,29 @@ +package org.jastadd.tooling.aspect.psi; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.AbstractElementManipulator; +import com.intellij.psi.ElementManipulator; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class JastAddAspectAstTypeNameManipulator extends AbstractElementManipulator<JastAddAspectAstTypeName> implements ElementManipulator<JastAddAspectAstTypeName> { + /** + * Changes the element's text to the given new text. + * + * @param element element to be changed + * @param range range within the element + * @param newContent new element text + * @return changed element + * @throws IncorrectOperationException if something goes wrong + */ + @Nullable + @Override + public JastAddAspectAstTypeName handleContentChange(@NotNull JastAddAspectAstTypeName element, @NotNull TextRange range, String newContent) { + try { + return (JastAddAspectAstTypeName) element.setName(range.replace(element.getText(), newContent)); + } catch (Exception e) { // e.g., in case the range is wrong + throw new IncorrectOperationException(e); + } + } +} diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectClassOrInterfaceTypeManipulator.java b/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectClassOrInterfaceTypeManipulator.java new file mode 100644 index 0000000000000000000000000000000000000000..88e3f360e2130909052ce4aad975a7ab6da95eb9 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectClassOrInterfaceTypeManipulator.java @@ -0,0 +1,32 @@ +package org.jastadd.tooling.aspect.psi; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.AbstractElementManipulator; +import com.intellij.psi.ElementManipulator; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class JastAddAspectClassOrInterfaceTypeManipulator extends AbstractElementManipulator<JastAddAspectClassOrInterfaceType> implements ElementManipulator<JastAddAspectClassOrInterfaceType> { + /** + * Changes the element's text to the given new text. + * + * @param element element to be changed + * @param range range within the element + * @param newContent new element text + * @return changed element + * @throws IncorrectOperationException if something goes wrong + */ + @Nullable + @Override + public JastAddAspectClassOrInterfaceType handleContentChange(@NotNull JastAddAspectClassOrInterfaceType element, @NotNull TextRange range, String newContent) { + try { + if (element.getJavaIdentifierList().size() != 1 || !element.getTypeArgumentsList().isEmpty()) { + throw new IncorrectOperationException("Operation only valid for \"primitive\" instances of JastAddAspectClassOrInterfaceType"); + } + return (JastAddAspectClassOrInterfaceType) element.setName(range.replace(element.getText(), newContent)); + } catch (Exception e) { // e.g., in case the range is wrong + throw new IncorrectOperationException(e); + } + } +} diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAstTypeNameImplExtension.java b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAstTypeNameImplExtension.java new file mode 100644 index 0000000000000000000000000000000000000000..c83758eea7659596e84856ed3d74ea7440cb1bde --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAstTypeNameImplExtension.java @@ -0,0 +1,38 @@ +package org.jastadd.tooling.aspect.psi.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import org.jastadd.tooling.aspect.psi.AspectElementFactory; +import org.jastadd.tooling.aspect.psi.JastAddAspectAstTypeName; +import org.jastadd.tooling.grammar.psi.GrammarNamedElement; +import org.jastadd.tooling.grammar.psi.impl.GrammarNamedElementImpl; +import org.jetbrains.annotations.NotNull; + +public class JastAddAspectAstTypeNameImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement { + + public JastAddAspectAstTypeNameImplExtension(@NotNull ASTNode node) { + super(node); + } + + public String getName() { + // this finds the *first* ID, which is what we want + return getNode().getText(); + } + + public PsiElement setName(@NotNull String newName) { + // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably) + ASTNode keyNode = getNode().getFirstChildNode(); + if (keyNode != null) { + JastAddAspectAstTypeName name = AspectElementFactory.createAstTypeName(getProject(), newName); + assert name != null; // we know the name is not null because we always create the same one + ASTNode newKeyNode = name.getNode().getFirstChildNode(); + getNode().replaceChild(keyNode, newKeyNode); + } + return this; + } + + public PsiElement getNameIdentifier() { + return getNode().getPsi(); + } + +} diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectClassOrInterfaceTypeImplExtension.java b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectClassOrInterfaceTypeImplExtension.java new file mode 100644 index 0000000000000000000000000000000000000000..ca1542e8db7756b3ad81660546a929b38fb3278d --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectClassOrInterfaceTypeImplExtension.java @@ -0,0 +1,38 @@ +package org.jastadd.tooling.aspect.psi.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import org.jastadd.tooling.aspect.psi.AspectElementFactory; +import org.jastadd.tooling.aspect.psi.JastAddAspectClassOrInterfaceType; +import org.jastadd.tooling.grammar.psi.GrammarNamedElement; +import org.jastadd.tooling.grammar.psi.impl.GrammarNamedElementImpl; +import org.jetbrains.annotations.NotNull; + +public class JastAddAspectClassOrInterfaceTypeImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement { + + public JastAddAspectClassOrInterfaceTypeImplExtension(@NotNull ASTNode node) { + super(node); + } + + public String getName() { + // this finds the *first* ID, which is what we want + return getNode().getText(); + } + + public PsiElement setName(@NotNull String newName) { + // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably) + ASTNode keyNode = getNode().getFirstChildNode(); + if (keyNode != null) { + JastAddAspectClassOrInterfaceType name = AspectElementFactory.createClassOrInterfaceType(getProject(), newName); + assert name != null; // we know the name is not null because we always create the same one + ASTNode newKeyNode = name.getNode().getFirstChildNode(); + getNode().replaceChild(keyNode, newKeyNode); + } + return this; + } + + public PsiElement getNameIdentifier() { + return getNode().getPsi(); + } + +} diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarAnnotator.java b/src/main/java/org/jastadd/tooling/grammar/GrammarAnnotator.java index 67973459c048ce172a6698f080e7c46ecb1678f5..ee0e88a0704b3b396255c3ff30f81192eefbbac7 100644 --- a/src/main/java/org/jastadd/tooling/grammar/GrammarAnnotator.java +++ b/src/main/java/org/jastadd/tooling/grammar/GrammarAnnotator.java @@ -8,7 +8,7 @@ import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; import com.intellij.psi.PsiElement; import org.jastadd.tooling.grammar.psi.GrammarComponent; -import org.jastadd.tooling.grammar.psi.GrammarTypeReference; +import org.jastadd.tooling.grammar.psi.GrammarTypeName; import org.jetbrains.annotations.NotNull; public class GrammarAnnotator implements Annotator { @@ -18,11 +18,11 @@ public class GrammarAnnotator implements Annotator { if (element instanceof GrammarComponent) { GrammarComponent component = (GrammarComponent) element; - if (component.getTypeReference() != null && component.getDeclaredName() != null) { - String name = component.getDeclaredName().getText(); - if (name != null && !name.equals("") && name.equals(component.getTypeReference().getName())) { + if (component.getTypeName() != null && component.getComponentName() != null) { + String name = component.getComponentName().getText(); + if (name != null && !name.equals("") && name.equals(component.getTypeName().getName())) { holder.newAnnotation(HighlightSeverity.WEAK_WARNING, "Redundant name") - .range(component.getDeclaredName().getTextRange()) + .range(component.getComponentName().getTextRange()) .highlightType(ProblemHighlightType.WEAK_WARNING) .textAttributes(DefaultLanguageHighlighterColors.HIGHLIGHTED_REFERENCE) .tooltip("When the name of a component is the same as its type, it can be omitted.") @@ -30,8 +30,8 @@ public class GrammarAnnotator implements Annotator { .create(); } } - } else if (element instanceof GrammarTypeReference) { - GrammarTypeReference reference = (GrammarTypeReference) element; + } else if (element instanceof GrammarTypeName) { + GrammarTypeName reference = (GrammarTypeName) element; if (GrammarUtil.findTypeDecl(element.getProject(), reference.getName()).isEmpty()) { holder.newAnnotation(HighlightSeverity.ERROR, "Undefined reference") .range(element.getTextRange()) diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarChooseByNameContributor.java b/src/main/java/org/jastadd/tooling/grammar/GrammarChooseByNameContributor.java index f1d88f5bdd920cd0494edf557d463572f4c8f215..615f51e2e80274d44e432b3752e79c422f929325 100644 --- a/src/main/java/org/jastadd/tooling/grammar/GrammarChooseByNameContributor.java +++ b/src/main/java/org/jastadd/tooling/grammar/GrammarChooseByNameContributor.java @@ -18,7 +18,7 @@ public class GrammarChooseByNameContributor implements ChooseByNameContributor { List<GrammarTypeDecl> typeDecls = GrammarUtil.findTypeDecl(project); List<String> names = new ArrayList<>(typeDecls.size()); for (GrammarTypeDecl typeDecl : typeDecls) { - if (typeDecl.getName() != null && typeDecl.getName().length() > 0) { + if (typeDecl.getName() != null && !typeDecl.getName().isEmpty()) { names.add(typeDecl.getName()); } } diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarCompletionContributor.java b/src/main/java/org/jastadd/tooling/grammar/GrammarCompletionContributor.java index ee356908fe4ccce7cab89dec9c3fe41251744209..a3939dc90ca034aef2cafe0657bc7898bc10dddb 100644 --- a/src/main/java/org/jastadd/tooling/grammar/GrammarCompletionContributor.java +++ b/src/main/java/org/jastadd/tooling/grammar/GrammarCompletionContributor.java @@ -7,7 +7,7 @@ import com.intellij.util.ProcessingContext; import org.jastadd.tooling.grammar.parser.GrammarTypes; import org.jastadd.tooling.grammar.psi.GrammarElementFactory; import org.jastadd.tooling.grammar.psi.GrammarTypeDecl; -import org.jastadd.tooling.grammar.psi.GrammarTypeReference; +import org.jastadd.tooling.grammar.psi.GrammarTypeName; import org.jastadd.tooling.util.JastAddIcons; import org.jetbrains.annotations.NotNull; @@ -24,7 +24,7 @@ public class GrammarCompletionContributor extends CompletionContributor { @NotNull ProcessingContext context, @NotNull CompletionResultSet resultSet) { for (GrammarTypeDecl decl : GrammarUtil.findTypeDecl(parameters.getPosition().getProject())) { - GrammarTypeReference ref = GrammarElementFactory.createTypeReference(parameters.getPosition().getProject(), decl.getName()); + GrammarTypeName ref = GrammarElementFactory.createTypeName(parameters.getPosition().getProject(), decl.getName()); resultSet.addElement(LookupElementBuilder.create(ref).withIcon(JastAddIcons.FILE).withTypeText(decl.getContainingFile().getName())); } } diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarRefactoringSupportProvider.java b/src/main/java/org/jastadd/tooling/grammar/GrammarRefactoringSupportProvider.java index 1e70ce549ffe5b03a1befa41a162fb785ad77224..07be384087a7e006e7321d61f0fd7503076309dc 100644 --- a/src/main/java/org/jastadd/tooling/grammar/GrammarRefactoringSupportProvider.java +++ b/src/main/java/org/jastadd/tooling/grammar/GrammarRefactoringSupportProvider.java @@ -3,8 +3,7 @@ package org.jastadd.tooling.grammar; import com.intellij.lang.refactoring.RefactoringSupportProvider; import com.intellij.psi.PsiElement; -import org.jastadd.tooling.grammar.psi.GrammarDeclaredName; -import org.jastadd.tooling.grammar.psi.GrammarTypeReference; +import org.jastadd.tooling.grammar.psi.GrammarTypeName; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -14,7 +13,7 @@ public class GrammarRefactoringSupportProvider extends RefactoringSupportProvide public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement elementToRename, @Nullable PsiElement context) { // in-place rename is still not available since not all requirements are met // see https://intellij-support.jetbrains.com/hc/en-us/community/posts/360006918740-How-do-I-enable-in-place-rename-Renaming-via-dialog-works-fine- - return (elementToRename instanceof GrammarDeclaredName) || (elementToRename instanceof GrammarTypeReference); + return elementToRename instanceof GrammarTypeName; } } diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarReference.java b/src/main/java/org/jastadd/tooling/grammar/GrammarReference.java index 3c6fc4b3afa6eb1eebe986362d90a88234f2f571..2825e6631cca7531cf229a040f95820a1d79a3c4 100644 --- a/src/main/java/org/jastadd/tooling/grammar/GrammarReference.java +++ b/src/main/java/org/jastadd/tooling/grammar/GrammarReference.java @@ -48,7 +48,7 @@ public class GrammarReference extends PsiReferenceBase<PsiElement> implements Ps List<GrammarTypeDecl> typeDecls = GrammarUtil.findTypeDecl(project); List<LookupElement> variants = new ArrayList<>(); for (final GrammarTypeDecl typeDecl : typeDecls) { - if (typeDecl.getName() != null && typeDecl.getName().length() > 0) { + if (typeDecl.getName() != null && !typeDecl.getName().isEmpty()) { variants.add(LookupElementBuilder .create(typeDecl).withIcon(JastAddIcons.FILE) .withPresentableText(typeDecl.getName()) diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarReferenceContributor.java b/src/main/java/org/jastadd/tooling/grammar/GrammarReferenceContributor.java index 728058c2095b0c858788183b68779f0c64235d59..2724d9107c243d2067c8abc7485be942a718e005 100644 --- a/src/main/java/org/jastadd/tooling/grammar/GrammarReferenceContributor.java +++ b/src/main/java/org/jastadd/tooling/grammar/GrammarReferenceContributor.java @@ -4,21 +4,21 @@ import com.intellij.openapi.util.TextRange; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.*; import com.intellij.util.ProcessingContext; -import org.jastadd.tooling.grammar.psi.GrammarTypeReference; +import org.jastadd.tooling.grammar.psi.GrammarTypeName; import org.jetbrains.annotations.NotNull; public class GrammarReferenceContributor extends PsiReferenceContributor { @Override public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { - registrar.registerReferenceProvider(PlatformPatterns.psiElement(GrammarTypeReference.class), + registrar.registerReferenceProvider(PlatformPatterns.psiElement(GrammarTypeName.class), new PsiReferenceProvider() { @NotNull @Override public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { - GrammarTypeReference typeReference = (GrammarTypeReference) element; + GrammarTypeName typeReference = (GrammarTypeName) element; String value = typeReference.getText(); if (value != null) { TextRange range = new TextRange(0, value.length()); diff --git a/src/main/java/org/jastadd/tooling/grammar/GrammarRemoveRedundantComponentNameFix.java b/src/main/java/org/jastadd/tooling/grammar/GrammarRemoveRedundantComponentNameFix.java index b906a768ff0caa222424459a692b38577c53e7e5..a95cb2a727795e8cbf9942dcc7ba6e216ea0e426 100644 --- a/src/main/java/org/jastadd/tooling/grammar/GrammarRemoveRedundantComponentNameFix.java +++ b/src/main/java/org/jastadd/tooling/grammar/GrammarRemoveRedundantComponentNameFix.java @@ -38,8 +38,8 @@ public class GrammarRemoveRedundantComponentNameFix extends BaseIntentionAction @Override public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException { - PsiElement first = component.getDeclaredName(); - PsiElement last = component.getDeclaredName(); + PsiElement first = component.getComponentName(); + PsiElement last = component.getComponentName(); while (last != null && last.getNode().getElementType() != GrammarTypes.COL) { last = last.getNextSibling(); } diff --git a/src/main/java/org/jastadd/tooling/grammar/RelAstFileType.java b/src/main/java/org/jastadd/tooling/grammar/RelAstFileType.java index 0eaedb0525a2718c2e8adca6434a43bd398a7121..5f70cebf6bb171459c9adfeaf414f2171ac82a6f 100644 --- a/src/main/java/org/jastadd/tooling/grammar/RelAstFileType.java +++ b/src/main/java/org/jastadd/tooling/grammar/RelAstFileType.java @@ -2,6 +2,7 @@ package org.jastadd.tooling.grammar; import com.intellij.openapi.fileTypes.LanguageFileType; import org.jastadd.tooling.util.JastAddIcons; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -21,6 +22,11 @@ public class RelAstFileType extends LanguageFileType { return "RelAst Grammar"; } + @Override + public @Nls @NotNull String getDisplayName() { + return getName(); + } + @NotNull @Override public String getDescription() { diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarElementFactory.java b/src/main/java/org/jastadd/tooling/grammar/psi/GrammarElementFactory.java index 05a33fa932d60b0c1651b986c91e9c163a95430a..0a0aa0308f30baed6dad4a163c9a44093e07264f 100644 --- a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarElementFactory.java +++ b/src/main/java/org/jastadd/tooling/grammar/psi/GrammarElementFactory.java @@ -13,14 +13,14 @@ public class GrammarElementFactory { throw new IllegalStateException("Utility class"); } - public static GrammarDeclaredName createDeclaredName(Project project, String name) { + public static GrammarTypeName createTypeName(Project project, String name) { final GrammarFile file = createFile(project, name + ";"); - return (GrammarDeclaredName) file.getFirstChild().getFirstChild(); + return (GrammarTypeName) (Objects.requireNonNull(file.getFirstChild().getNode().findChildByType(GrammarTypes.TYPE_NAME)).getPsi()); } - public static GrammarTypeReference createTypeReference(Project project, String name) { - final GrammarFile file = createFile(project, "X : " + name + ";"); - return (GrammarTypeReference) (Objects.requireNonNull(file.getFirstChild().getNode().findChildByType(GrammarTypes.TYPE_REFERENCE)).getPsi()); + public static GrammarComponentName createComponentName(Project project, String name) { + final GrammarFile file = createFile(project, "X ::= " + name + ":X ;"); + return (GrammarComponentName) file.getFirstChild().getFirstChild(); } public static GrammarFile createFile(Project project, String text) { diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeDeclExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeDeclExtension.java deleted file mode 100644 index 3459b1aca8435d9392d54556a96365d08491e3f1..0000000000000000000000000000000000000000 --- a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeDeclExtension.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.jastadd.tooling.grammar.psi; - -public interface GrammarTypeDeclExtension extends GrammarNamedElement { -} diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeReferenceManipulator.java b/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeNameManipulator.java similarity index 66% rename from src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeReferenceManipulator.java rename to src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeNameManipulator.java index 7ab2f70c6e8376f986224f54c36c08994fe70e80..ea2a34466ebe44825504e12bb9bad25577e2dd66 100644 --- a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeReferenceManipulator.java +++ b/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeNameManipulator.java @@ -7,7 +7,7 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class GrammarTypeReferenceManipulator extends AbstractElementManipulator<GrammarTypeReference> implements ElementManipulator<GrammarTypeReference> { +public class GrammarTypeNameManipulator extends AbstractElementManipulator<GrammarTypeName> implements ElementManipulator<GrammarTypeName> { /** * Changes the element's text to the given new text. * @@ -19,9 +19,9 @@ public class GrammarTypeReferenceManipulator extends AbstractElementManipulator< */ @Nullable @Override - public GrammarTypeReference handleContentChange(@NotNull GrammarTypeReference element, @NotNull TextRange range, String newContent) { + public GrammarTypeName handleContentChange(@NotNull GrammarTypeName element, @NotNull TextRange range, String newContent) { try { - return (GrammarTypeReference) element.setName(range.replace(element.getText(), newContent)); + return (GrammarTypeName) element.setName(range.replace(element.getText(), newContent)); } catch (Exception e) { // e.g., in case the range is wrong throw new IncorrectOperationException(e); } diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeReferenceExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeReferenceExtension.java deleted file mode 100644 index c9cbb3c9089193483e7a999be66b1b9400a03a0f..0000000000000000000000000000000000000000 --- a/src/main/java/org/jastadd/tooling/grammar/psi/GrammarTypeReferenceExtension.java +++ /dev/null @@ -1,4 +0,0 @@ -package org.jastadd.tooling.grammar.psi; - -public interface GrammarTypeReferenceExtension extends GrammarNamedElement { -} diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeReferenceImplExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarComponentNameImplExtension.java similarity index 67% rename from src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeReferenceImplExtension.java rename to src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarComponentNameImplExtension.java index 495e20e17f1a30459b97257765e10ea10126de23..8f4fc2504ff8fba1970c99bf9c7dd81ba568abda 100644 --- a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeReferenceImplExtension.java +++ b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarComponentNameImplExtension.java @@ -2,14 +2,14 @@ package org.jastadd.tooling.grammar.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; +import org.jastadd.tooling.grammar.psi.GrammarComponentName; import org.jastadd.tooling.grammar.psi.GrammarElementFactory; -import org.jastadd.tooling.grammar.psi.GrammarTypeReference; -import org.jastadd.tooling.grammar.psi.GrammarTypeReferenceExtension; +import org.jastadd.tooling.grammar.psi.GrammarNamedElement; import org.jetbrains.annotations.NotNull; -public class GrammarTypeReferenceImplExtension extends GrammarNamedElementImpl implements GrammarTypeReferenceExtension { +public class GrammarComponentNameImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement { - public GrammarTypeReferenceImplExtension(@NotNull ASTNode node) { + public GrammarComponentNameImplExtension(@NotNull ASTNode node) { super(node); } @@ -22,7 +22,7 @@ public class GrammarTypeReferenceImplExtension extends GrammarNamedElementImpl i // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably) ASTNode keyNode = getNode().getFirstChildNode(); if (keyNode != null) { - GrammarTypeReference name = GrammarElementFactory.createTypeReference(getProject(), newName); + GrammarComponentName name = GrammarElementFactory.createComponentName(getProject(), newName); ASTNode newKeyNode = name.getNode().getFirstChildNode(); getNode().replaceChild(keyNode, newKeyNode); } diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java index 8df00b485a450166dae96f9b694d23c09b97ed54..39bd24dbfd95d0f4f9989ec860c9de58a9e2b38a 100644 --- a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java +++ b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java @@ -3,12 +3,12 @@ package org.jastadd.tooling.grammar.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jastadd.tooling.grammar.parser.GrammarTypes; -import org.jastadd.tooling.grammar.psi.GrammarDeclaredName; import org.jastadd.tooling.grammar.psi.GrammarElementFactory; -import org.jastadd.tooling.grammar.psi.GrammarTypeDeclExtension; +import org.jastadd.tooling.grammar.psi.GrammarNamedElement; +import org.jastadd.tooling.grammar.psi.GrammarTypeName; import org.jetbrains.annotations.NotNull; -public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implements GrammarTypeDeclExtension { +public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement { public GrammarTypeDeclImplExtension(@NotNull ASTNode node) { super(node); @@ -16,7 +16,7 @@ public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implem public String getName() { // this finds the *first* ID, which is what we want - ASTNode keyNode = getNode().findChildByType(GrammarTypes.DECLARED_NAME); + ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); if (keyNode != null) { return keyNode.getText(); } else { @@ -25,9 +25,9 @@ public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implem } public PsiElement setName(@NotNull String newName) { - ASTNode keyNode = getNode().findChildByType(GrammarTypes.DECLARED_NAME); + ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); if (keyNode != null) { - GrammarDeclaredName name = GrammarElementFactory.createDeclaredName(getProject(), newName); + GrammarTypeName name = GrammarElementFactory.createTypeName(getProject(), newName); ASTNode newKeyNode = name.getNode(); getNode().replaceChild(keyNode, newKeyNode); } @@ -35,7 +35,7 @@ public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implem } public PsiElement getNameIdentifier() { - ASTNode keyNode = getNode().findChildByType(GrammarTypes.DECLARED_NAME); + ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); if (keyNode != null) { return keyNode.getPsi(); } else { diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeNameImplExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeNameImplExtension.java new file mode 100644 index 0000000000000000000000000000000000000000..753e63cc14ca327f4e521221916b9e293e854641 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeNameImplExtension.java @@ -0,0 +1,36 @@ +package org.jastadd.tooling.grammar.psi.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import org.jastadd.tooling.grammar.psi.GrammarElementFactory; +import org.jastadd.tooling.grammar.psi.GrammarNamedElement; +import org.jastadd.tooling.grammar.psi.GrammarTypeName; +import org.jetbrains.annotations.NotNull; + +public class GrammarTypeNameImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement { + + public GrammarTypeNameImplExtension(@NotNull ASTNode node) { + super(node); + } + + public String getName() { + // this finds the *first* ID, which is what we want + return getNode().getText(); + } + + public PsiElement setName(@NotNull String newName) { + // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably) + ASTNode keyNode = getNode().getFirstChildNode(); + if (keyNode != null) { + GrammarTypeName name = GrammarElementFactory.createTypeName(getProject(), newName); + ASTNode newKeyNode = name.getNode().getFirstChildNode(); + getNode().replaceChild(keyNode, newKeyNode); + } + return this; + } + + public PsiElement getNameIdentifier() { + return getNode().getPsi(); + } + +} diff --git a/src/main/java/org/jastadd/tooling/java/JavaColorSettingsPage.java b/src/main/java/org/jastadd/tooling/java/JavaColorSettingsPage.java index ea402dfe1be2cefbfcaaf140d01ef9afe8e9f744..8f945215297dd78ca51ae6bc5b59b75e59b1a036 100644 --- a/src/main/java/org/jastadd/tooling/java/JavaColorSettingsPage.java +++ b/src/main/java/org/jastadd/tooling/java/JavaColorSettingsPage.java @@ -17,12 +17,12 @@ import java.util.Map; public class JavaColorSettingsPage implements ColorSettingsPage { private static final AttributesDescriptor[] DESCRIPTORS = new AttributesDescriptor[]{ - new AttributesDescriptor("Nonterminal Use", JavaSyntaxHighlighter.NT_USE), - new AttributesDescriptor("High-Level API Use", JavaSyntaxHighlighter.HIGHLEVEL_API_USE), - new AttributesDescriptor("Low-Level API Use", JavaSyntaxHighlighter.LOWLEVEL_API_USE), - new AttributesDescriptor("Internal API Use", JavaSyntaxHighlighter.INTERNAL_API_USE), - new AttributesDescriptor("Attribute Call", JavaSyntaxHighlighter.ATTRIBUTE_CALL), - new AttributesDescriptor("Inter-Type Declaration Use", JavaSyntaxHighlighter.INTERTYPE_DECL_USE) + new AttributesDescriptor("Nonterminal use", JavaSyntaxHighlighter.NT_USE), + new AttributesDescriptor("High-Level API use", JavaSyntaxHighlighter.HIGHLEVEL_API_USE), + new AttributesDescriptor("Low-Level API use", JavaSyntaxHighlighter.LOWLEVEL_API_USE), + new AttributesDescriptor("Internal API use", JavaSyntaxHighlighter.INTERNAL_API_USE), + new AttributesDescriptor("Attribute call", JavaSyntaxHighlighter.ATTRIBUTE_CALL), + new AttributesDescriptor("Inter-Type declaration use", JavaSyntaxHighlighter.INTERTYPE_DECL_USE) }; @Nullable @@ -63,13 +63,13 @@ public class JavaColorSettingsPage implements ColorSettingsPage { @NotNull @Override - public AttributesDescriptor[] getAttributeDescriptors() { + public AttributesDescriptor @NotNull [] getAttributeDescriptors() { return DESCRIPTORS; } @NotNull @Override - public ColorDescriptor[] getColorDescriptors() { + public ColorDescriptor @NotNull [] getColorDescriptors() { return ColorDescriptor.EMPTY_ARRAY; } diff --git a/src/main/java/org/jastadd/tooling/java/NonterminalUseAnnotator.java b/src/main/java/org/jastadd/tooling/java/NonterminalUseAnnotator.java index e232500fa4cdb5b3bd56983db37c8f2a053b4612..fa6888dcdb5228b64546cc7b5488e73caab6b05c 100644 --- a/src/main/java/org/jastadd/tooling/java/NonterminalUseAnnotator.java +++ b/src/main/java/org/jastadd/tooling/java/NonterminalUseAnnotator.java @@ -40,7 +40,7 @@ public class NonterminalUseAnnotator implements Annotator { return; } String production = Arrays.stream(productionTag.getDataElements()).map(PsiElement::getText).collect(Collectors.joining()); - String reference = getNavigationUrlFromFileLocation(declaredAt); + String reference = getNavigationUrlFromFileLocation(declaredAt); holder.newAnnotation(HighlightSeverity.INFORMATION, "JastAdd Nonterminal: " + production) .range(element.getTextRange()) diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 2cb82c0e622ba51f68afd3203e7e4cb0c75381fa..a9b7feec56cba1ca3ce62fdb1bbb238ad4fef635 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -38,8 +38,8 @@ <lang.refactoringSupport language="JastAddGrammar" implementationClass="org.jastadd.tooling.grammar.GrammarRefactoringSupportProvider"/> - <lang.elementManipulator forClass="org.jastadd.tooling.grammar.psi.GrammarTypeReference" - implementationClass="org.jastadd.tooling.grammar.psi.GrammarTypeReferenceManipulator"/> + <lang.elementManipulator forClass="org.jastadd.tooling.grammar.psi.GrammarTypeName" + implementationClass="org.jastadd.tooling.grammar.psi.GrammarTypeNameManipulator"/> <lang.findUsagesProvider language="JastAddGrammar" @@ -80,6 +80,14 @@ <colorSettingsPage implementation="org.jastadd.tooling.java.JavaColorSettingsPage"/> + <psi.referenceContributor implementation="org.jastadd.tooling.aspect.AspectReferenceContributor"/> + + <lang.elementManipulator forClass="org.jastadd.tooling.aspect.psi.JastAddAspectAstTypeName" + implementationClass="org.jastadd.tooling.aspect.psi.JastAddAspectAstTypeNameManipulator"/> + + <lang.elementManipulator forClass="org.jastadd.tooling.aspect.psi.JastAddAspectClassOrInterfaceType" + implementationClass="org.jastadd.tooling.aspect.psi.JastAddAspectClassOrInterfaceTypeManipulator"/> + <lang.formatter language="JastAddAspect" implementationClass="org.jastadd.tooling.aspect.AspectFormattingModelBuilder"/> </extensions>