Skip to content
Snippets Groups Projects
Commit aa7d1500 authored by Johannes Mey's avatar Johannes Mey
Browse files

trivial language injection works

parent 49dab591
No related branches found
No related tags found
No related merge requests found
Showing
with 423 additions and 6 deletions
......@@ -48,12 +48,6 @@ repositories {
jcenter()
}
idea {
module {
generatedSourceDirs.add(file("src/gen"))
}
}
// Configure gradle-intellij-plugin plugin.
// Read more: https://github.com/JetBrains/gradle-intellij-plugin
intellij {
......@@ -73,6 +67,12 @@ sourceSets {
}
}
idea {
module {
generatedSourceDirs.add(file("src/gen/java"))
}
}
//import org.jetbrains.grammarkit.tasks.*
//
grammarKit {
......@@ -101,9 +101,28 @@ tasks {
purgeOldFiles = true
}
val generateJastAddAspectLexer = task<GenerateLexer>("generateJastAddAspectLexer") {
source = "src/main/grammar/JastAddAspect.flex"
targetDir = "src/gen/java/org/jastadd/tooling/aspect/lexer/"
targetClass = "JastAddAspectLexer"
purgeOldFiles = true
}
// not fully working because of https://github.com/JetBrains/gradle-grammar-kit-plugin/issues/3
val generateJastAddAspectParser = task<GenerateParser>("generateJastAddAspectParser") {
source = "src/main/grammar/JastAddAspect.bnf"
targetRoot = "src/gen/java"
pathToParser = "/org/jastadd/tooling/aspect/JastAddAspectParser.java"
pathToPsiRoot = "/org/jastadd/tooling/aspect/psi"
purgeOldFiles = true
}
compileJava {
dependsOn(generateRelAstGrammarLexer)
dependsOn(generateRelAstGrammarParser)
dependsOn(generateRelAstGrammarLexer)
dependsOn(generateRelAstGrammarParser)
}
withType<JavaCompile> {
......
{
parserClass="org.jastadd.tooling.aspect.parser.JastAddAspectParser"
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
psiClassPrefix="JastAddAspect"
psiImplClassSuffix="Impl"
psiPackage="org.jastadd.tooling.aspect.psi"
psiImplPackage="org.jastadd.tooling.aspect.psi.impl"
elementTypeHolderClass="org.jastadd.tooling.aspect.psi.JastAddAspectTypes"
elementTypeClass="org.jastadd.tooling.aspect.JastAddAspectElementType"
tokenTypeClass="org.jastadd.tooling.aspect.JastAddAspectTokenType"
}
jastaddAspectFile ::= (attribute_equation|comment)*
comment ::= (WHITESPACE | MULTILINECOMMENT | DOCCOMMENT | SINGLELINECOMMENT)
attribute_equation ::= EQ java_block
java_block ::= JAVABLOCK
{
implements="org.jastadd.tooling.aspect.psi.JastAddAspectJavaBlockExtension"
extends="org.jastadd.tooling.aspect.psi.impl.JastAddAspectJavaBlockImplExtension"
}
package org.jastadd.tooling.aspect.lexer;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import org.jastadd.tooling.aspect.psi.JastAddAspectTypes;
import com.intellij.psi.TokenType;
%%
%class JastAddAspectLexer
%implements FlexLexer
%unicode
%function advance
%type IElementType
%eof{ return;
%eof}
%{
private int counter = 0;
%}
WhiteSpace = [ ] | \t | \f | \n | \r | \r\n
//ID = [a-zA-Z$_][a-zA-Z0-9$_]*
//MultiLineComment = [/][*][^*]+[*]+([^*/][^*]*[*]+)*[/]
//DocComment = [/][*][*][^*]*[*]+([^*/][^*]*[*]+)*[/]
//SingleLineComment = [/][/] [^\n\r]* (\n | \r | \r\n)
NotParenthesis = [^{}]*
%state JAVA
%%
<YYINITIAL> {
{WhiteSpace}+ {}
"EQ" { yybegin(YYINITIAL); return JastAddAspectTypes.EQ; }
"{" { yybegin(JAVA); counter = 1; }
}
<JAVA> {
{NotParenthesis} {}
"{" { counter++; yybegin(JAVA); }
"}" { counter--; if (counter==0) { yybegin(YYINITIAL); return JastAddAspectTypes.JAVABLOCK; } }
}
package org.jastadd.tooling.aspect;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class JastAddAspectElementType extends IElementType {
public JastAddAspectElementType(@NotNull @NonNls String debugName) {
super(debugName, JastAddAspectLanguage.INSTANCE);
}
}
package org.jastadd.tooling.aspect;
import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider;
import org.jetbrains.annotations.NotNull;
public class JastAddAspectFile extends PsiFileBase {
public JastAddAspectFile(@NotNull FileViewProvider viewProvider) {
super(viewProvider, JastAddAspectLanguage.INSTANCE);
}
@NotNull
@Override
public FileType getFileType() {
return JastAddAttributeFileType.INSTANCE;
}
@Override
public String toString() {
return "JastAdd Attribute Aspect File";
}
}
package org.jastadd.tooling.aspect;
import com.intellij.openapi.fileTypes.LanguageFileType;
import org.jastadd.tooling.JastAddIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class JastAddAspectFileType extends LanguageFileType {
public static final JastAddAspectFileType INSTANCE = new JastAddAspectFileType();
private JastAddAspectFileType() {
super(JastAddAspectLanguage.INSTANCE);
}
@NotNull
@Override
public String getName() {
return "JastAdd Aspect";
}
@NotNull
@Override
public String getDescription() {
return "JastAdd file (for inter-type declarations)";
}
@NotNull
@Override
public String getDefaultExtension() {
return "jadd";
}
@Nullable
@Override
public Icon getIcon() {
return JastAddIcons.FILE;
}
}
package org.jastadd.tooling.aspect;
import com.intellij.lang.Language;
public class JastAddAspectLanguage extends Language {
public static final JastAddAspectLanguage INSTANCE = new JastAddAspectLanguage();
private JastAddAspectLanguage() {
super("JastAddAspect");
}
}
package org.jastadd.tooling.aspect;
import com.intellij.lang.ASTNode;
import com.intellij.lang.ParserDefinition;
import com.intellij.lang.PsiParser;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.project.Project;
import com.intellij.psi.FileViewProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.TokenSet;
import org.jastadd.tooling.aspect.lexer.JastAddAspectLexerAdapter;
import org.jastadd.tooling.aspect.parser.JastAddAspectParser;
import org.jastadd.tooling.aspect.psi.JastAddAspectTypes;
import org.jetbrains.annotations.NotNull;
public class JastAddAspectParserDefinition implements ParserDefinition {
public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE);
public static final TokenSet COMMENTS = TokenSet.create(JastAddAspectTypes.COMMENT);
public static final IFileElementType FILE = new IFileElementType(JastAddAspectLanguage.INSTANCE);
@NotNull
@Override
public Lexer createLexer(Project project) {
return new JastAddAspectLexerAdapter();
}
@NotNull
@Override
public TokenSet getWhitespaceTokens() {
return WHITE_SPACES;
}
@NotNull
@Override
public TokenSet getCommentTokens() {
return COMMENTS;
}
@NotNull
@Override
public TokenSet getStringLiteralElements() {
return TokenSet.EMPTY;
}
@NotNull
@Override
public PsiParser createParser(final Project project) {
return new JastAddAspectParser();
}
@Override
public IFileElementType getFileNodeType() {
return FILE;
}
@Override
public PsiFile createFile(FileViewProvider viewProvider) {
return new JastAddAspectFile(viewProvider);
}
@Override
public SpaceRequirements spaceExistenceTypeBetweenTokens(ASTNode left, ASTNode right) {
return SpaceRequirements.MAY;
}
@NotNull
@Override
public PsiElement createElement(ASTNode node) {
return JastAddAspectTypes.Factory.createElement(node);
}
}
package org.jastadd.tooling.aspect;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class JastAddAspectTokenType extends IElementType {
public JastAddAspectTokenType(@NotNull @NonNls String debugName) {
super(debugName, JastAddAspectLanguage.INSTANCE);
}
@Override
public String toString() {
return "JastAddAspectTokenType." + super.toString();
}
}
package org.jastadd.tooling.aspect;
import com.intellij.openapi.fileTypes.LanguageFileType;
import org.jastadd.tooling.JastAddIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class JastAddAttributeFileType extends LanguageFileType {
public static final JastAddAttributeFileType INSTANCE = new JastAddAttributeFileType();
private JastAddAttributeFileType() {
super(JastAddAspectLanguage.INSTANCE);
}
@NotNull
@Override
public String getName() {
return "JastAdd Attribute Aspect";
}
@NotNull
@Override
public String getDescription() {
return "JastAdd file (for attributes)";
}
@NotNull
@Override
public String getDefaultExtension() {
return "jrag";
}
@Nullable
@Override
public Icon getIcon() {
return JastAddIcons.FILE;
}
}
package org.jastadd.tooling.aspect;
import com.intellij.lang.Language;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.InjectedLanguagePlaces;
import com.intellij.psi.LanguageInjector;
import com.intellij.psi.PsiLanguageInjectionHost;
import org.jetbrains.annotations.NotNull;
public class JavaBlockLanguageInjector implements LanguageInjector {
/**
* @param host PSI element inside which your language will be injected.
* @param injectionPlacesRegistrar stores places where injection occurs. <br>
* Call its {@link InjectedLanguagePlaces#addPlace(Language, TextRange, String, String)}
* method to register particular injection place.
* For example, to inject your language in string literal inside quotes, you might want to <br>
* {@code injectionPlacesRegistrar.addPlace(myLanguage, new TextRange(1,host.getTextLength()-1))}
*/
@Override
public void getLanguagesToInject(@NotNull PsiLanguageInjectionHost host, @NotNull InjectedLanguagePlaces injectionPlacesRegistrar) {
injectionPlacesRegistrar.addPlace(JavaLanguage.INSTANCE, new TextRange(0, host.getTextLength()), "class X { public void m(){", "}");
}
}
package org.jastadd.tooling.aspect.lexer;
import com.intellij.lexer.FlexAdapter;
public class JastAddAspectLexerAdapter extends FlexAdapter {
public JastAddAspectLexerAdapter() {
super(new JastAddAspectLexer(null));
}
}
package org.jastadd.tooling.aspect.psi;
public interface JastAddAspectJavaBlockExtension extends com.intellij.psi.PsiLanguageInjectionHost {
}
package org.jastadd.tooling.aspect.psi.impl;
import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.LiteralTextEscaper;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLanguageInjectionHost;
import org.jastadd.tooling.aspect.psi.JastAddAspectJavaBlockExtension;
import org.jetbrains.annotations.NotNull;
public class JastAddAspectJavaBlockImplExtension extends ASTWrapperPsiElement implements JastAddAspectJavaBlockExtension {
public JastAddAspectJavaBlockImplExtension(@NotNull ASTNode node) {
super(node);
}
/**
* @return {@code true} if this instance can accept injections, {@code false} otherwise
*/
@Override
public boolean isValidHost() {
return true;
}
/**
* Update the host element using the provided text of the injected file. It may be required to escape characters from {@code text}
* in accordance with the host language syntax. The implementation may delegate to {@link ElementManipulators#handleContentChange(PsiElement, String)}
* if {@link ElementManipulator} implementation is registered for this element class.
*
* @param text text of the injected file
* @return the updated instance
*/
@Override
public PsiLanguageInjectionHost updateText(@NotNull String text) {
return this;
}
/**
* @return {@link LiteralTextEscaper} instance which will be used to convert the content of this host element to the content of injected file
*/
@Override
public @NotNull LiteralTextEscaper<? extends PsiLanguageInjectionHost> createLiteralTextEscaper() {
return LiteralTextEscaper.createSimple(this);
}
}
......@@ -57,6 +57,17 @@
implementation="org.jastadd.tooling.RelAstGrammarLanguageCodeStyleSettingsProvider"/>
<lang.commenter language="JastAddGrammar" implementationClass="org.jastadd.tooling.RelAstGrammarCommenter"/>
<!-- Attribute/Aspect Language -->
<fileType name="JastAdd Attribute Aspect" implementationClass="org.jastadd.tooling.aspect.JastAddAttributeFileType"
fieldName="INSTANCE" language="JastAddAspect" extensions="jrag"/>
<fileType name="JastAdd Aspect" implementationClass="org.jastadd.tooling.aspect.JastAddAspectFileType"
fieldName="INSTANCE" language="JastAddAspect" extensions="jadd"/>
<lang.parserDefinition language="JastAddAspect"
implementationClass="org.jastadd.tooling.aspect.JastAddAspectParserDefinition"/>
<languageInjector implementation="org.jastadd.tooling.aspect.JavaBlockLanguageInjector"/>
</extensions>
<actions>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment