Skip to content

Commit

Permalink
Fix injection jump to parser file
Browse files Browse the repository at this point in the history
  • Loading branch information
oowekyala committed Jan 17, 2020
1 parent 7f489aa commit dcaf413
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import com.github.oowekyala.ijcc.lang.model.parserSimpleName
import com.github.oowekyala.ijcc.lang.psi.*
import com.github.oowekyala.ijcc.util.pop
import com.intellij.openapi.util.TextRange
import com.intellij.psi.ElementManipulators
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiLanguageInjectionHost
import com.intellij.psi.impl.source.tree.injected.changesHandler.contentRange
import java.util.*

/**
Expand All @@ -20,7 +22,7 @@ class InjectedTreeBuilderVisitor private constructor() : JccVisitor() {
// If visiting a node entails visiting other subtrees, these must be merged into a single node
// If the node may not contain injection hosts, EmptyLeaf must be pushed

private val nodeStackImpl: Deque<InjectionStructureTree> = LinkedList()
private val nodeStackImpl: Deque<InjectionStructureTree> = ArrayDeque()
val nodeStack: List<InjectionStructureTree>
get() = nodeStackImpl.toList()

Expand All @@ -32,7 +34,7 @@ class InjectedTreeBuilderVisitor private constructor() : JccVisitor() {
override fun visitGrammarFileRoot(o: JccGrammarFileRoot) {

// FIXME the compilation unit is not injected in the same injection file as the productions
// o.parserDeclaration.javaCompilationUnit?.accept(this)
// o.parserDeclaration.javaCompilationUnit?.accept(this)

o.containingFile.nonTerminalProductions.forEach { it.accept(this) }

Expand All @@ -56,7 +58,7 @@ class InjectedTreeBuilderVisitor private constructor() : JccVisitor() {
it.innerRange(1, 1) // remove the braces
}

override fun visitJavaCompilationUnit(o: JccJavaCompilationUnit) = visitInjectionHost(o)
// override fun visitJavaCompilationUnit(o: JccJavaCompilationUnit) = visitInjectionHost(o)

// catch all method, so that the number of leaves
// corresponds to the number of visited children
Expand Down Expand Up @@ -269,7 +271,7 @@ class InjectedTreeBuilderVisitor private constructor() : JccVisitor() {
""".trimIndent()
else ""

return jjtreeDecls + """
return jjtreeDecls + """
/** Get the next Token. */
final public Token getNextToken() {}
Expand Down Expand Up @@ -357,17 +359,35 @@ class InjectedTreeBuilderVisitor private constructor() : JccVisitor() {
val file = element.containingFile
val jcu = file.parserDeclaration?.javaCompilationUnit

// TODO stop ignoring contents of the ACU, in order to modify its structure!
// TODO add declarations inserted by JJTree (and implements clauses)

val leaf =

if (jcu != null)
SurroundNode(
MultiChildNode(
children = listOf(
HostLeaf(jcu) { ElementManipulators.getManipulator(it).getRangeInElement(it) },
node
)
) { "" },
prefix = "",
suffix = "}"
)
else {
SurroundNode(node, prefix = "class SomeParser {" + javaccInsertedDecls(file), suffix = "}")
}

val commonPrefix = jcu?.text?.trim()?.takeIf { it.endsWith("}") }?.removeSuffix("}") ?: "class MyParser {"

return SurroundNode(
node,
prefix = commonPrefix + javaccInsertedDecls(file),
suffix = "}"
leaf,
prefix = "",
suffix = javaccInsertedDecls(file) + "}"
)
}


// TODO stop ignoring contents of the ACU, in order to modify its structure!
// TODO add declarations inserted by JJTree (and implements clauses)

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ val JccGrammarFileRoot.linearInjectedStructure: LinearInjectedStructure
get() = getUserData(LinearStructureKey)
?: getLinearStructureFor(this)
.also {
putUserData(LinearStructureKey, it)
// putUserData(LinearStructureKey, it)
}

Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package com.github.oowekyala.ijcc.lang.psi

import com.github.oowekyala.ijcc.lang.injection.HostSpec
import com.github.oowekyala.ijcc.lang.injection.MultilineTextEscaper
import com.github.oowekyala.ijcc.lang.psi.impl.jccEltFactory
import com.github.oowekyala.ijcc.lang.psi.manipulators.JccJavaCompilationUnitManipulator
import com.intellij.psi.ElementManipulators
import com.intellij.psi.LiteralTextEscaper
import com.intellij.psi.PsiLanguageInjectionHost

interface JccJavaCompilationUnit : PsiLanguageInjectionHost, JccPsiElement {
@JvmDefault
override fun updateText(text: String): PsiLanguageInjectionHost =
this.replace(project.jccEltFactory.createJcu(text))
.let { it as PsiLanguageInjectionHost }
.also { HostSpec.replaceHost(this, it) }
this.also {
ElementManipulators.handleContentChange(this, text)
}
// this.replace(project.jccEltFactory.createJcu(text))
// .let { it as PsiLanguageInjectionHost }
// .also { HostSpec.replaceHost(this, it) }

@JvmDefault
override fun createLiteralTextEscaper(): LiteralTextEscaper<out PsiLanguageInjectionHost> =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.github.oowekyala.ijcc.lang.psi.manipulators

import com.github.oowekyala.ijcc.lang.JccTypes
import com.github.oowekyala.ijcc.lang.psi.JccJavaCompilationUnit
import com.github.oowekyala.ijcc.lang.psi.impl.jccEltFactory
import com.github.oowekyala.ijcc.lang.psi.isOfType
import com.github.oowekyala.ijcc.lang.psi.siblingSequence
import com.intellij.openapi.util.TextRange
import com.intellij.psi.AbstractElementManipulator


/**
* @author Clément Fournier
* @since 1.0
*/
class JccJavaCompilationUnitManipulator : AbstractElementManipulator<JccJavaCompilationUnit>() {


override fun getRangeInElement(element: JccJavaCompilationUnit): TextRange {
val braceOffset = element.lastChild.siblingSequence(false).first { it.isOfType(JccTypes.JCC_RBRACE) }
return TextRange.from(0, braceOffset.textRange.startOffset - element.textRange.startOffset)
}


override fun handleContentChange(element: JccJavaCompilationUnit,
range: TextRange,
newContent: String?): JccJavaCompilationUnit? {
val oldText = element.text
val newText = oldText.substring(0, range.startOffset) + newContent +
oldText.substring(range.endOffset)
return element.replace(element.project.jccEltFactory.createJcu(newText)) as JccJavaCompilationUnit
}
}
1 change: 1 addition & 0 deletions idea/changelog.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
<li>Add title to configuration options</li>
<li>Better resilience to mistyped Jjtree annotations</li>
<li>Fix private regexes defined in eg SPECIAL_TOKEN being reported as inaccessible</li>
<li>Fix jump to methods defined in parser (in injected fragments)</li>
</ul>
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,24 @@ object JavaccLanguageInjector : MultiHostInjector {
try {
when (context) {
// FIXME inject both into the same injection file
is JccJavaCompilationUnit -> registrar.injectIntoJCU(context)
// is JccJavaCompilationUnit -> registrar.injectIntoJCU(context)
is JccGrammarFileRoot -> registrar.injectIntoGrammar(context)
}
} catch (e: Exception) {
// TODO log?
}
}

private fun MultiHostRegistrar.injectIntoJCU(jcu: JccJavaCompilationUnit) {
startInjecting(JavaLanguage.INSTANCE)

val suffix = InjectedTreeBuilderVisitor.javaccInsertedDecls(
jcu.containingFile
) + "}"

addPlace(null, suffix, jcu, jcu.innerRange(endOffset = 1)) // remove last brace
doneInjecting()
}
//
// private fun MultiHostRegistrar.injectIntoJCU(jcu: JccJavaCompilationUnit) {
// startInjecting(JavaLanguage.INSTANCE)
//
// val suffix = InjectedTreeBuilderVisitor.javaccInsertedDecls(
// jcu.containingFile
// ) + "}"
//
// addPlace(null, suffix, jcu, jcu.innerRange(endOffset = 1)) // remove last brace
// doneInjecting()
// }

private fun MultiHostRegistrar.injectIntoGrammar(context: JccGrammarFileRoot) {
context.linearInjectedStructure.register(this)
Expand Down
2 changes: 2 additions & 0 deletions idea/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
implementationClass="com.github.oowekyala.ijcc.lang.psi.manipulators.JccLiteralRegexManipulator"/>
<lang.elementManipulator forClass="com.github.oowekyala.ijcc.lang.psi.JccIdentifier"
implementationClass="com.github.oowekyala.ijcc.lang.psi.manipulators.JccIdentifierManipulator"/>
<lang.elementManipulator forClass="com.github.oowekyala.ijcc.lang.psi.JccJavaCompilationUnit"
implementationClass="com.github.oowekyala.ijcc.lang.psi.manipulators.JccJavaCompilationUnitManipulator"/>
<lang.braceMatcher language="JavaCC" implementationClass="com.github.oowekyala.ijcc.JavaccPairedBraceMatcher"/>


Expand Down
21 changes: 2 additions & 19 deletions sandbox/Java.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -1667,7 +1667,6 @@ ASTCompilationUnit CompilationUnit() :
return jjtThis;
}
}

void PackageDeclaration() :
{}
{
Expand Down Expand Up @@ -1731,24 +1730,7 @@ void TypeDeclaration():
)
}

void ClassOrInterfaceDeclaration(int modifiers):
{
Token t = null;
jjtThis.setModifiers(modifiers);
boolean inInterfaceOld = inInterface;
inInterface = false;
}
{
( /* See note about this optional final modifier in BlockStatement */
["final"|"abstract"] "class" | "interface" { jjtThis.setInterface(); inInterface = true; } )
t=<IDENTIFIER> { checkForBadTypeIdentifierUsage(t.image); jjtThis.setImage(t.image); }
[ TypeParameters() ]
[ ExtendsList() ]
[ ImplementsList() ]
ClassOrInterfaceBody()
{ inInterface = inInterfaceOld; } // always restore the flag after leaving the node
}

void ClassOrInterfaceDeclaration
void ExtendsList():
{
boolean extendsMoreThanOne = false;
Expand All @@ -1771,6 +1753,7 @@ void EnumDeclaration(int modifiers):
Token t;
jjtThis.setModifiers(modifiers);
}

{
t = <IDENTIFIER> {
if (!"enum".equals(t.image)) {
Expand Down
19 changes: 0 additions & 19 deletions sandbox/JavaCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -1309,25 +1309,6 @@ void node_descriptor() :
}


JAVACODE
void node_descriptor_expression()
{
IElementType kind;
int nesting = 1;
while (true) {
kind = getType();
if (kind == JavaCCConstants._EOF)
builder.error("Unexpected <EOF>");
if (kind == JavaCCConstants.LPAREN) nesting++;
if (kind == JavaCCConstants.RPAREN) {
nesting--;
if (nesting == 0) break;
}
builder.advanceLexer();
}
}


/**********************************************
* THE JAVA GRAMMAR SPECIFICATION STARTS HERE *
**********************************************/
Expand Down

0 comments on commit dcaf413

Please sign in to comment.