Refactoring transpiler.
This commit is contained in:
parent
dd92d99afd
commit
d116b2c555
@ -135,7 +135,12 @@ public class DefaultAstBuilderVisitor extends WebViewComponentsParserBaseVisitor
|
|||||||
children.add((QuestionTagChild) childResult);
|
children.add((QuestionTagChild) childResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.nodeFactory.questionTagNode(this.getTokenRange(ctx), children);
|
return this.nodeFactory.questionTagNode(
|
||||||
|
this.getTokenRange(ctx),
|
||||||
|
ctx.QuestionTagOpen().getSymbol(),
|
||||||
|
ctx.QuestionTagClose().getSymbol(),
|
||||||
|
children
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -147,7 +152,12 @@ public class DefaultAstBuilderVisitor extends WebViewComponentsParserBaseVisitor
|
|||||||
children.add((HtmlCommentChild) childResult);
|
children.add((HtmlCommentChild) childResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.nodeFactory.htmlCommentNode(this.getTokenRange(ctx), children);
|
return this.nodeFactory.htmlCommentNode(
|
||||||
|
this.getTokenRange(ctx),
|
||||||
|
ctx.HtmlCommentOpen().getSymbol(),
|
||||||
|
ctx.HtmlCommentClose().getSymbol(),
|
||||||
|
children
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -340,7 +350,7 @@ public class DefaultAstBuilderVisitor extends WebViewComponentsParserBaseVisitor
|
|||||||
if (groovyCode != null) {
|
if (groovyCode != null) {
|
||||||
return this.nodeFactory.equalsScriptletNode(
|
return this.nodeFactory.equalsScriptletNode(
|
||||||
this.getTokenRange(ctx),
|
this.getTokenRange(ctx),
|
||||||
ctx.GroovyCode().getSymbol().getTokenIndex()
|
ctx.GroovyCode().getSymbol().getText()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@ -363,7 +373,7 @@ public class DefaultAstBuilderVisitor extends WebViewComponentsParserBaseVisitor
|
|||||||
if (groovyCode != null) {
|
if (groovyCode != null) {
|
||||||
return this.nodeFactory.dollarScriptletNode(
|
return this.nodeFactory.dollarScriptletNode(
|
||||||
this.getTokenRange(ctx),
|
this.getTokenRange(ctx),
|
||||||
groovyCode.getSymbol().getTokenIndex()
|
groovyCode.getSymbol().getText()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -7,6 +7,7 @@ import groowt.view.component.web.antlr.TokenList;
|
|||||||
import groowt.view.component.web.ast.extension.*;
|
import groowt.view.component.web.ast.extension.*;
|
||||||
import groowt.view.component.web.ast.node.*;
|
import groowt.view.component.web.ast.node.*;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -109,13 +110,23 @@ public class DefaultNodeFactory implements NodeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public QuestionNode questionTagNode(TokenRange tokenRange, List<? extends QuestionTagChild> children) {
|
public QuestionNode questionTagNode(
|
||||||
return this.objectFactory.get(QuestionNode.class, tokenRange, children);
|
TokenRange tokenRange,
|
||||||
|
Token openToken,
|
||||||
|
Token closeToken,
|
||||||
|
List<? extends QuestionTagChild> children
|
||||||
|
) {
|
||||||
|
return this.objectFactory.get(QuestionNode.class, tokenRange, openToken, closeToken, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HtmlCommentNode htmlCommentNode(TokenRange tokenRange, List<? extends HtmlCommentChild> children) {
|
public HtmlCommentNode htmlCommentNode(
|
||||||
return this.objectFactory.get(HtmlCommentNode.class, tokenRange, children);
|
TokenRange tokenRange,
|
||||||
|
Token openToken,
|
||||||
|
Token closeToken,
|
||||||
|
List<? extends HtmlCommentChild> children
|
||||||
|
) {
|
||||||
|
return this.objectFactory.get(HtmlCommentNode.class, tokenRange, openToken, closeToken, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -209,8 +220,8 @@ public class DefaultNodeFactory implements NodeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EqualsScriptletNode equalsScriptletNode(TokenRange tokenRange, int groovyIndex) {
|
public EqualsScriptletNode equalsScriptletNode(TokenRange tokenRange, String groovyCode) {
|
||||||
return this.objectFactory.get(EqualsScriptletNode.class, tokenRange, groovyIndex);
|
return this.objectFactory.get(EqualsScriptletNode.class, tokenRange, groovyCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -219,8 +230,8 @@ public class DefaultNodeFactory implements NodeFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DollarScriptletNode dollarScriptletNode(TokenRange tokenRange, int groovyIndex) {
|
public DollarScriptletNode dollarScriptletNode(TokenRange tokenRange, String groovyCode) {
|
||||||
return this.objectFactory.get(DollarScriptletNode.class, tokenRange, groovyIndex);
|
return this.objectFactory.get(DollarScriptletNode.class, tokenRange, groovyCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,6 +2,7 @@ package groowt.view.component.web.ast;
|
|||||||
|
|
||||||
import groowt.view.component.web.ast.node.*;
|
import groowt.view.component.web.ast.node.*;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -20,9 +21,19 @@ public interface NodeFactory {
|
|||||||
|
|
||||||
BodyTextNode bodyTextNode(TokenRange tokenRange, List<? extends BodyTextChild> children);
|
BodyTextNode bodyTextNode(TokenRange tokenRange, List<? extends BodyTextChild> children);
|
||||||
|
|
||||||
QuestionNode questionTagNode(TokenRange tokenRange, List<? extends QuestionTagChild> children);
|
QuestionNode questionTagNode(
|
||||||
|
TokenRange tokenRange,
|
||||||
|
Token openToken,
|
||||||
|
Token closeToken,
|
||||||
|
List<? extends QuestionTagChild> children
|
||||||
|
);
|
||||||
|
|
||||||
HtmlCommentNode htmlCommentNode(TokenRange tokenRange, List<? extends HtmlCommentChild> children);
|
HtmlCommentNode htmlCommentNode(
|
||||||
|
TokenRange tokenRange,
|
||||||
|
Token openToken,
|
||||||
|
Token closeToken,
|
||||||
|
List<? extends HtmlCommentChild> children
|
||||||
|
);
|
||||||
|
|
||||||
TextNode textNode(TokenRange tokenRange, String content);
|
TextNode textNode(TokenRange tokenRange, String content);
|
||||||
|
|
||||||
@ -63,11 +74,11 @@ public interface NodeFactory {
|
|||||||
|
|
||||||
ComponentValueNode componentValueNode(TokenRange tokenRange, ComponentNode componentNode);
|
ComponentValueNode componentValueNode(TokenRange tokenRange, ComponentNode componentNode);
|
||||||
|
|
||||||
EqualsScriptletNode equalsScriptletNode(TokenRange tokenRange, int groovyIndex);
|
EqualsScriptletNode equalsScriptletNode(TokenRange tokenRange, String groovyCode);
|
||||||
|
|
||||||
PlainScriptletNode plainScriptletNode(TokenRange tokenRange, int groovyIndex);
|
PlainScriptletNode plainScriptletNode(TokenRange tokenRange, int groovyIndex);
|
||||||
|
|
||||||
DollarScriptletNode dollarScriptletNode(TokenRange tokenRange, int groovyIndex);
|
DollarScriptletNode dollarScriptletNode(TokenRange tokenRange, String groovyCode);
|
||||||
|
|
||||||
DollarReferenceNode dollarReferenceNode(TokenRange tokenRange, int groovyIndex);
|
DollarReferenceNode dollarReferenceNode(TokenRange tokenRange, int groovyIndex);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import org.antlr.v4.runtime.Token;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public abstract sealed class GStringNodeExtension implements NodeExtension
|
public abstract sealed class GStringNodeExtension implements NodeExtension
|
||||||
permits GStringPathExtension, GStringScriptletExtension {
|
permits GStringPathExtension, GStringScriptletExtension {
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import groowt.view.component.web.ast.node.Node;
|
|||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public non-sealed class GStringPathExtension extends GStringNodeExtension {
|
public non-sealed class GStringPathExtension extends GStringNodeExtension {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -6,6 +6,7 @@ import groowt.view.component.web.ast.node.Node;
|
|||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public non-sealed class GStringScriptletExtension extends GStringNodeExtension {
|
public non-sealed class GStringScriptletExtension extends GStringNodeExtension {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -29,4 +29,8 @@ public class BodyTextNode extends AbstractTreeNode implements BodyChildNode {
|
|||||||
super(tokenRange, extensionContainer, childrenAsNodes(checkChildren(children)));
|
super(tokenRange, extensionContainer, childrenAsNodes(checkChildren(children)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<BodyTextChild> getChildrenAsBodyTextChildren() {
|
||||||
|
return this.getChildren().stream().map(BodyTextChild.class::cast).toList();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,28 @@
|
|||||||
package groowt.view.component.web.ast.node;
|
package groowt.view.component.web.ast.node;
|
||||||
|
|
||||||
import groowt.util.di.annotation.Given;
|
import groowt.util.di.annotation.Given;
|
||||||
import groowt.view.component.web.antlr.TokenList;
|
|
||||||
import groowt.view.component.web.ast.extension.GStringPathExtension;
|
|
||||||
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class DollarReferenceNode extends AbstractLeafNode implements GroovyBodyNode {
|
public class DollarReferenceNode extends AbstractLeafNode implements GroovyBodyNode {
|
||||||
|
|
||||||
private final int groovyTokenIndex;
|
private final List<String> parts;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DollarReferenceNode(
|
public DollarReferenceNode(
|
||||||
TokenList tokenList,
|
|
||||||
NodeExtensionContainer extensionContainer,
|
NodeExtensionContainer extensionContainer,
|
||||||
@Given TokenRange tokenRange,
|
@Given TokenRange tokenRange,
|
||||||
@Given int groovyTokenIndex
|
List<String> parts
|
||||||
) {
|
) {
|
||||||
super(tokenRange, extensionContainer);
|
super(tokenRange, extensionContainer);
|
||||||
this.groovyTokenIndex = groovyTokenIndex;
|
this.parts = parts;
|
||||||
this.createGStringPath(tokenList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createGStringPath(TokenList tokenList) {
|
public List<String> getParts() {
|
||||||
this.createExtension(GStringPathExtension.class, TokenRange.fromIndex(tokenList, this.groovyTokenIndex));
|
return this.parts;
|
||||||
}
|
|
||||||
|
|
||||||
public GStringPathExtension getGStringPath() {
|
|
||||||
return this.getExtension(GStringPathExtension.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,33 +1,26 @@
|
|||||||
package groowt.view.component.web.ast.node;
|
package groowt.view.component.web.ast.node;
|
||||||
|
|
||||||
import groowt.util.di.annotation.Given;
|
import groowt.util.di.annotation.Given;
|
||||||
import groowt.view.component.web.antlr.TokenList;
|
|
||||||
import groowt.view.component.web.ast.extension.GStringScriptletExtension;
|
|
||||||
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
public class DollarScriptletNode extends AbstractLeafNode implements GroovyBodyNode {
|
public class DollarScriptletNode extends AbstractLeafNode implements GroovyBodyNode {
|
||||||
|
|
||||||
private final GStringScriptletExtension gStringScriptlet;
|
private final String groovyCode;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DollarScriptletNode(
|
public DollarScriptletNode(
|
||||||
TokenList tokenList,
|
|
||||||
NodeExtensionContainer extensionContainer,
|
NodeExtensionContainer extensionContainer,
|
||||||
@Given TokenRange tokenRange,
|
@Given TokenRange tokenRange,
|
||||||
@Given int groovyTokenIndex
|
@Given String groovyCode
|
||||||
) {
|
) {
|
||||||
super(tokenRange, extensionContainer);
|
super(tokenRange, extensionContainer);
|
||||||
this.gStringScriptlet = this.createGStringScriptlet(tokenList, groovyTokenIndex);
|
this.groovyCode = groovyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected GStringScriptletExtension createGStringScriptlet(TokenList tokenList, int groovyTokenIndex) {
|
public String getGroovyCode() {
|
||||||
return this.createExtension(GStringScriptletExtension.class, TokenRange.fromIndex(tokenList, groovyTokenIndex));
|
return this.groovyCode;
|
||||||
}
|
|
||||||
|
|
||||||
public GStringScriptletExtension getGStringScriptlet() {
|
|
||||||
return this.gStringScriptlet;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,23 @@
|
|||||||
package groowt.view.component.web.ast.node;
|
package groowt.view.component.web.ast.node;
|
||||||
|
|
||||||
import groowt.util.di.annotation.Given;
|
import groowt.util.di.annotation.Given;
|
||||||
import groowt.view.component.web.antlr.TokenList;
|
|
||||||
import groowt.view.component.web.ast.extension.GroovyCodeNodeExtension;
|
|
||||||
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
import org.antlr.v4.runtime.Token;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class EqualsScriptletNode extends AbstractLeafNode implements GroovyBodyNode {
|
public class EqualsScriptletNode extends AbstractLeafNode implements GroovyBodyNode {
|
||||||
|
|
||||||
private final int groovyIndex;
|
private final String groovyCode;
|
||||||
private final GroovyCodeNodeExtension groovyCode;
|
|
||||||
|
|
||||||
public EqualsScriptletNode(
|
public EqualsScriptletNode(
|
||||||
TokenList tokenList,
|
|
||||||
NodeExtensionContainer extensionContainer,
|
NodeExtensionContainer extensionContainer,
|
||||||
@Given TokenRange tokenRange,
|
@Given TokenRange tokenRange,
|
||||||
@Given int groovyIndex
|
@Given String groovyCode
|
||||||
) {
|
) {
|
||||||
super(tokenRange, extensionContainer);
|
super(tokenRange, extensionContainer);
|
||||||
this.groovyIndex = groovyIndex;
|
this.groovyCode = groovyCode;
|
||||||
this.groovyCode = this.createGroovyCode(tokenList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected GroovyCodeNodeExtension createGroovyCode(TokenList tokenList) {
|
public String getGroovyCode() {
|
||||||
return this.createExtension(
|
|
||||||
GroovyCodeNodeExtension.class,
|
|
||||||
TokenRange.fromIndex(tokenList, this.groovyIndex),
|
|
||||||
(Function<? super List<Token>, String>) this::toValidGroovyCode
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String toValidGroovyCode(List<Token> groovyTokens) {
|
|
||||||
return "{ -> " + groovyTokens.stream().map(Token::getText).collect(Collectors.joining()) + " }";
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getGroovyIndex() {
|
|
||||||
return this.groovyIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroovyCodeNodeExtension getGroovyCode() {
|
|
||||||
return this.groovyCode;
|
return this.groovyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,18 +4,38 @@ import groowt.util.di.annotation.Given;
|
|||||||
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class HtmlCommentNode extends AbstractTreeNode implements BodyTextChild {
|
public class HtmlCommentNode extends AbstractTreeNode implements BodyTextChild {
|
||||||
|
|
||||||
|
private final Token openToken;
|
||||||
|
private final Token closeToken;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public HtmlCommentNode(
|
public HtmlCommentNode(
|
||||||
NodeExtensionContainer extensionContainer,
|
NodeExtensionContainer extensionContainer,
|
||||||
@Given TokenRange tokenRange,
|
@Given TokenRange tokenRange,
|
||||||
|
@Given Token openToken,
|
||||||
|
@Given Token closeToken,
|
||||||
@Given List<? extends HtmlCommentChild> children
|
@Given List<? extends HtmlCommentChild> children
|
||||||
) {
|
) {
|
||||||
super(tokenRange, extensionContainer, children.stream().map(HtmlCommentChild::asNode).toList());
|
super(tokenRange, extensionContainer, children.stream().map(HtmlCommentChild::asNode).toList());
|
||||||
|
this.openToken = openToken;
|
||||||
|
this.closeToken = closeToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<HtmlCommentChild> getChildrenAsHtmlCommentChildren() {
|
||||||
|
return this.getChildren().stream().map(HtmlCommentChild.class::cast).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token getOpenToken() {
|
||||||
|
return this.openToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token getCloseToken() {
|
||||||
|
return this.closeToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,50 +2,26 @@ package groowt.view.component.web.ast.node;
|
|||||||
|
|
||||||
import groowt.util.di.annotation.Given;
|
import groowt.util.di.annotation.Given;
|
||||||
import groowt.view.component.web.antlr.TokenList;
|
import groowt.view.component.web.antlr.TokenList;
|
||||||
import groowt.view.component.web.ast.extension.GroovyCodeNodeExtension;
|
|
||||||
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import org.antlr.v4.runtime.Token;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class PlainScriptletNode extends AbstractLeafNode implements GroovyBodyNode {
|
public class PlainScriptletNode extends AbstractLeafNode implements GroovyBodyNode {
|
||||||
|
|
||||||
private final int groovyIndex;
|
private final String groovyCode;
|
||||||
private final GroovyCodeNodeExtension groovyCode;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public PlainScriptletNode(
|
public PlainScriptletNode(
|
||||||
TokenList tokenList,
|
TokenList tokenList,
|
||||||
NodeExtensionContainer extensionContainer,
|
NodeExtensionContainer extensionContainer,
|
||||||
@Given TokenRange tokenRange,
|
@Given TokenRange tokenRange,
|
||||||
@Given int groovyIndex
|
@Given String groovyCode
|
||||||
) {
|
) {
|
||||||
super(tokenRange, extensionContainer);
|
super(tokenRange, extensionContainer);
|
||||||
this.groovyIndex = groovyIndex;
|
this.groovyCode = groovyCode;
|
||||||
this.groovyCode = this.createGroovyCode(tokenList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected GroovyCodeNodeExtension createGroovyCode(TokenList tokenList) {
|
public String getGroovyCode() {
|
||||||
return this.createExtension(
|
|
||||||
GroovyCodeNodeExtension.class,
|
|
||||||
TokenRange.fromIndex(tokenList, this.groovyIndex),
|
|
||||||
(Function<? super List<Token>, String>) this::toValidGroovyCode
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String toValidGroovyCode(List<Token> groovyTokens) {
|
|
||||||
return "{ Writer out -> " + groovyTokens.stream().map(Token::getText).collect(Collectors.joining()) + " }";
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getGroovyIndex() {
|
|
||||||
return this.groovyIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GroovyCodeNodeExtension getGroovyCode() {
|
|
||||||
return this.groovyCode;
|
return this.groovyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,18 +4,38 @@ import groowt.util.di.annotation.Given;
|
|||||||
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
import groowt.view.component.web.ast.extension.NodeExtensionContainer;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class QuestionNode extends AbstractTreeNode implements BodyTextChild {
|
public class QuestionNode extends AbstractTreeNode implements BodyTextChild {
|
||||||
|
|
||||||
|
private final Token openToken;
|
||||||
|
private final Token closeToken;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public QuestionNode(
|
public QuestionNode(
|
||||||
NodeExtensionContainer extensionContainer,
|
NodeExtensionContainer extensionContainer,
|
||||||
@Given TokenRange tokenRange,
|
@Given TokenRange tokenRange,
|
||||||
|
@Given Token openToken,
|
||||||
|
@Given Token closeToken,
|
||||||
@Given List<? extends QuestionTagChild> children
|
@Given List<? extends QuestionTagChild> children
|
||||||
) {
|
) {
|
||||||
super(tokenRange, extensionContainer, children.stream().map(QuestionTagChild::asNode).toList());
|
super(tokenRange, extensionContainer, children.stream().map(QuestionTagChild::asNode).toList());
|
||||||
|
this.openToken = openToken;
|
||||||
|
this.closeToken = closeToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<QuestionTagChild> getChildrenAsQuestionTagChildren() {
|
||||||
|
return this.getChildren().stream().map(QuestionTagChild.class::cast).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token getOpenToken() {
|
||||||
|
return this.openToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Token getCloseToken() {
|
||||||
|
return this.closeToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import org.codehaus.groovy.ast.stmt.Statement;
|
|||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public interface AppendOrAddStatementFactory {
|
public interface AppendOrAddStatementFactory {
|
||||||
|
|
||||||
enum Action {
|
enum Action {
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
|
import groowt.view.component.web.ast.node.BodyTextNode;
|
||||||
|
import org.codehaus.groovy.ast.stmt.Statement;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface BodyTextTranspiler {
|
||||||
|
List<Statement> createBodyTextStatements(BodyTextNode bodyTextNode, TranspilerState state);
|
||||||
|
}
|
@ -6,8 +6,5 @@ import org.codehaus.groovy.ast.stmt.Statement;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface ComponentTranspiler {
|
public interface ComponentTranspiler {
|
||||||
List<Statement> createComponentStatements(
|
List<Statement> createComponentStatements(ComponentNode componentNode, TranspilerState state);
|
||||||
ComponentNode componentNode,
|
|
||||||
TranspilerState state
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
|
import groowt.util.di.annotation.Given;
|
||||||
|
import groowt.view.component.web.WebViewComponentBugError;
|
||||||
|
import groowt.view.component.web.ast.node.*;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
|
import org.codehaus.groovy.ast.expr.ConstantExpression;
|
||||||
|
import org.codehaus.groovy.ast.stmt.Statement;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static groowt.view.component.web.transpile.TranspilerUtil.getStringLiteral;
|
||||||
|
|
||||||
|
public class DefaultBodyTextTranspiler implements BodyTextTranspiler {
|
||||||
|
|
||||||
|
private final GroovyBodyNodeTranspiler groovyBodyNodeTranspiler;
|
||||||
|
private final PositionSetter positionSetter;
|
||||||
|
private final LeftShiftFactory leftShiftFactory;
|
||||||
|
private final boolean includeComments;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public DefaultBodyTextTranspiler(
|
||||||
|
GroovyBodyNodeTranspiler groovyBodyNodeTranspiler,
|
||||||
|
PositionSetter positionSetter,
|
||||||
|
LeftShiftFactory leftShiftFactory,
|
||||||
|
@Given boolean includeComments
|
||||||
|
) {
|
||||||
|
this.groovyBodyNodeTranspiler = groovyBodyNodeTranspiler;
|
||||||
|
this.positionSetter = positionSetter;
|
||||||
|
this.leftShiftFactory = leftShiftFactory;
|
||||||
|
this.includeComments = includeComments;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Statement handleStringLiteral(Token source) {
|
||||||
|
final ConstantExpression literal = getStringLiteral(source.getText());
|
||||||
|
this.positionSetter.setPosition(literal, source);
|
||||||
|
return this.leftShiftFactory.create(literal);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Statement handleStringLiteral(Node source, String content) {
|
||||||
|
final ConstantExpression literal = getStringLiteral(content);
|
||||||
|
this.positionSetter.setPosition(literal, source);
|
||||||
|
return this.leftShiftFactory.create(literal);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Statement> handleHtmlCommentChild(HtmlCommentChild child, TranspilerState state) {
|
||||||
|
return switch (child) {
|
||||||
|
case BodyTextChild bodyTextChild -> this.handleBodyTextChild(bodyTextChild, state);
|
||||||
|
default -> throw new WebViewComponentBugError(new UnsupportedOperationException(
|
||||||
|
"Unsupported HtmlCommentChild type " + child.getClass().getName()
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Statement> handleQuestionTagChild(QuestionTagChild child, TranspilerState state) {
|
||||||
|
return switch (child) {
|
||||||
|
case BodyTextChild bodyTextChild -> this.handleBodyTextChild(bodyTextChild, state);
|
||||||
|
default -> throw new WebViewComponentBugError(new UnsupportedOperationException(
|
||||||
|
"Unsupported QuestionTagChild type " + child.getClass().getName()
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Statement> handleBodyTextChild(BodyTextChild child, TranspilerState state) {
|
||||||
|
final List<Statement> result = new ArrayList<>();
|
||||||
|
switch (child) {
|
||||||
|
case QuestionNode questionNode -> {
|
||||||
|
result.add(this.handleStringLiteral(questionNode.getOpenToken()));
|
||||||
|
questionNode.getChildrenAsQuestionTagChildren().stream()
|
||||||
|
.map(questionChild -> this.handleQuestionTagChild(questionChild, state))
|
||||||
|
.forEach(result::addAll);
|
||||||
|
result.add(this.handleStringLiteral(questionNode.getCloseToken()));
|
||||||
|
}
|
||||||
|
case HtmlCommentNode commentNode -> {
|
||||||
|
if (this.includeComments) {
|
||||||
|
result.add(this.handleStringLiteral(commentNode.getOpenToken()));
|
||||||
|
commentNode.getChildrenAsHtmlCommentChildren().stream()
|
||||||
|
.map(commentChild -> this.handleHtmlCommentChild(commentChild, state))
|
||||||
|
.forEach(result::addAll);
|
||||||
|
result.add(this.handleStringLiteral(commentNode.getCloseToken()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case TextNode textNode -> {
|
||||||
|
result.add(this.handleStringLiteral(textNode, textNode.getContent()));
|
||||||
|
}
|
||||||
|
case GroovyBodyNode groovyBodyNode -> {
|
||||||
|
result.add(this.groovyBodyNodeTranspiler.createGroovyBodyNodeStatements(groovyBodyNode, state));
|
||||||
|
}
|
||||||
|
default -> throw new WebViewComponentBugError(new UnsupportedOperationException(
|
||||||
|
"BodyTextChild of type " + child.getClass().getName() + " is not supported."
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Statement> createBodyTextStatements(BodyTextNode bodyTextNode, TranspilerState state) {
|
||||||
|
final List<Statement> result = new ArrayList<>();
|
||||||
|
for (final BodyTextChild child : bodyTextNode.getChildrenAsBodyTextChildren()) {
|
||||||
|
result.addAll(this.handleBodyTextChild(child, state));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,26 +1,20 @@
|
|||||||
package groowt.view.component.web.transpile;
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
import groowt.view.component.web.WebViewComponentBugError;
|
import groowt.view.component.web.WebViewComponentBugError;
|
||||||
import groowt.view.component.web.ast.node.*;
|
import groowt.view.component.web.ast.node.BodyNode;
|
||||||
import jakarta.inject.Inject;
|
import groowt.view.component.web.ast.node.BodyTextNode;
|
||||||
import org.codehaus.groovy.ast.expr.GStringExpression;
|
import groowt.view.component.web.ast.node.ComponentNode;
|
||||||
|
import groowt.view.component.web.ast.node.Node;
|
||||||
import org.codehaus.groovy.ast.stmt.BlockStatement;
|
import org.codehaus.groovy.ast.stmt.BlockStatement;
|
||||||
|
|
||||||
public class DefaultBodyTranspiler implements BodyTranspiler {
|
public class DefaultBodyTranspiler implements BodyTranspiler {
|
||||||
|
|
||||||
private final GStringTranspiler gStringTranspiler;
|
|
||||||
private final JStringTranspiler jStringTranspiler;
|
|
||||||
private final ComponentTranspiler componentTranspiler;
|
private final ComponentTranspiler componentTranspiler;
|
||||||
|
private final BodyTextTranspiler bodyTextTranspiler;
|
||||||
|
|
||||||
@Inject
|
public DefaultBodyTranspiler(ComponentTranspiler componentTranspiler, BodyTextTranspiler bodyTextTranspiler) {
|
||||||
public DefaultBodyTranspiler(
|
|
||||||
GStringTranspiler gStringTranspiler,
|
|
||||||
JStringTranspiler jStringTranspiler,
|
|
||||||
ComponentTranspiler componentTranspiler
|
|
||||||
) {
|
|
||||||
this.gStringTranspiler = gStringTranspiler;
|
|
||||||
this.jStringTranspiler = jStringTranspiler;
|
|
||||||
this.componentTranspiler = componentTranspiler;
|
this.componentTranspiler = componentTranspiler;
|
||||||
|
this.bodyTextTranspiler = bodyTextTranspiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -33,27 +27,10 @@ public class DefaultBodyTranspiler implements BodyTranspiler {
|
|||||||
block.setVariableScope(state.pushScope());
|
block.setVariableScope(state.pushScope());
|
||||||
for (final Node child : bodyNode.getChildren()) {
|
for (final Node child : bodyNode.getChildren()) {
|
||||||
switch (child) {
|
switch (child) {
|
||||||
case GStringBodyTextNode gStringBodyTextNode -> {
|
case ComponentNode componentNode ->
|
||||||
final GStringExpression gString = this.gStringTranspiler.createGStringExpression(
|
block.addStatements(this.componentTranspiler.createComponentStatements(componentNode, state));
|
||||||
gStringBodyTextNode
|
case BodyTextNode bodyTextNode ->
|
||||||
);
|
block.addStatements(this.bodyTextTranspiler.createBodyTextStatements(bodyTextNode, state));
|
||||||
block.addStatement(addOrAppendCallback.createStatement(gStringBodyTextNode, gString));
|
|
||||||
}
|
|
||||||
case JStringBodyTextNode jStringBodyTextNode -> {
|
|
||||||
block.addStatement(
|
|
||||||
addOrAppendCallback.createStatement(
|
|
||||||
jStringBodyTextNode,
|
|
||||||
this.jStringTranspiler.createStringLiteral(jStringBodyTextNode)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
case ComponentNode componentNode -> {
|
|
||||||
// DO NOT add/append this, because the component transpiler does it already
|
|
||||||
block.addStatements(this.componentTranspiler.createComponentStatements(componentNode, state));
|
|
||||||
}
|
|
||||||
case PlainScriptletNode plainScriptletNode -> {
|
|
||||||
throw new UnsupportedOperationException("TODO");
|
|
||||||
}
|
|
||||||
default -> throw new WebViewComponentBugError(new UnsupportedOperationException(
|
default -> throw new WebViewComponentBugError(new UnsupportedOperationException(
|
||||||
"BodyNode child of type " + child.getClass().getSimpleName() + " is not supported."
|
"BodyNode child of type " + child.getClass().getSimpleName() + " is not supported."
|
||||||
));
|
));
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
|
import groowt.view.component.web.WebViewComponentBugError;
|
||||||
|
import groowt.view.component.web.ast.node.*;
|
||||||
|
import groowt.view.component.web.transpile.groovy.GroovyUtil;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.codehaus.groovy.ast.expr.*;
|
||||||
|
import org.codehaus.groovy.ast.stmt.BlockStatement;
|
||||||
|
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
|
||||||
|
import org.codehaus.groovy.ast.stmt.Statement;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DefaultGroovyBodyNodeTranspiler implements GroovyBodyNodeTranspiler {
|
||||||
|
|
||||||
|
private final PositionSetter positionSetter;
|
||||||
|
private final LeftShiftFactory leftShiftFactory;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public DefaultGroovyBodyNodeTranspiler(PositionSetter positionSetter, LeftShiftFactory leftShiftFactory) {
|
||||||
|
this.positionSetter = positionSetter;
|
||||||
|
this.leftShiftFactory = leftShiftFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ClosureExpression convertToClosure(Node node, String source) {
|
||||||
|
final GroovyUtil.ConvertResult convertResult = GroovyUtil.convert(
|
||||||
|
"def cl = {" + source + "}"
|
||||||
|
);
|
||||||
|
final BlockStatement convertBlock = convertResult.blockStatement();
|
||||||
|
|
||||||
|
if (convertBlock == null) {
|
||||||
|
throw new WebViewComponentBugError("Did not expect convertBlock to be null.");
|
||||||
|
}
|
||||||
|
if (convertBlock.isEmpty()) {
|
||||||
|
throw new WebViewComponentBugError("Did not expect convertBlock to be empty.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final ExpressionStatement clStmt = (ExpressionStatement) convertBlock.getStatements().getFirst();
|
||||||
|
final BinaryExpression clAssign = (BinaryExpression) clStmt.getExpression();
|
||||||
|
final ClosureExpression cl = (ClosureExpression) clAssign.getRightExpression();
|
||||||
|
|
||||||
|
final PositionVisitor positionVisitor = new PositionVisitor(
|
||||||
|
this.positionSetter.withOffset(0, -10), node
|
||||||
|
);
|
||||||
|
cl.visit(positionVisitor);
|
||||||
|
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Statement handleEqualsScriptlet(EqualsScriptletNode equalsScriptletNode, TranspilerState state) {
|
||||||
|
final ClosureExpression cl = this.convertToClosure(equalsScriptletNode, equalsScriptletNode.getGroovyCode());
|
||||||
|
final MethodCallExpression callExpr;
|
||||||
|
if (cl.getParameters() == null) {
|
||||||
|
callExpr = new MethodCallExpression(cl, "call", EmptyExpression.INSTANCE);
|
||||||
|
} else {
|
||||||
|
final ArgumentListExpression argsList = new ArgumentListExpression(
|
||||||
|
List.of(state.hasCurrentChildList() ? state.getCurrentChildList() : state.getWriter())
|
||||||
|
);
|
||||||
|
callExpr = new MethodCallExpression(cl, "call", argsList);
|
||||||
|
}
|
||||||
|
return this.leftShiftFactory.create(callExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Statement handlePlainScriptlet(PlainScriptletNode plainScriptletNode, TranspilerState state) {
|
||||||
|
final ClosureExpression cl = this.convertToClosure(plainScriptletNode, plainScriptletNode.getGroovyCode());
|
||||||
|
final MethodCallExpression callExpr;
|
||||||
|
if (cl.getParameters() == null) {
|
||||||
|
callExpr = new MethodCallExpression(cl, "call", EmptyExpression.INSTANCE);
|
||||||
|
} else {
|
||||||
|
final ArgumentListExpression argsList = new ArgumentListExpression(
|
||||||
|
List.of(state.hasCurrentChildList() ? state.getCurrentChildList() : state.getWriter())
|
||||||
|
);
|
||||||
|
callExpr = new MethodCallExpression(cl, "call", argsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ExpressionStatement(callExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Statement handleDollarScriptlet(DollarScriptletNode dollarScriptletNode) {
|
||||||
|
final ClosureExpression cl = this.convertToClosure(dollarScriptletNode, dollarScriptletNode.getGroovyCode());
|
||||||
|
final Expression toLeftShift;
|
||||||
|
if (cl.getParameters() == null) {
|
||||||
|
toLeftShift = cl;
|
||||||
|
} else {
|
||||||
|
final Statement stmt = cl.getCode();
|
||||||
|
if (stmt instanceof ExpressionStatement exprStmt) {
|
||||||
|
toLeftShift = exprStmt.getExpression();
|
||||||
|
} else {
|
||||||
|
toLeftShift = cl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.leftShiftFactory.create(toLeftShift);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Statement handleDollarReference(DollarReferenceNode dollarReferenceNode) {
|
||||||
|
VariableExpression root = null;
|
||||||
|
PropertyExpression propertyExpr = null;
|
||||||
|
for (final String part : dollarReferenceNode.getParts()) {
|
||||||
|
if (root == null) {
|
||||||
|
root = new VariableExpression(part);
|
||||||
|
} else if (propertyExpr == null) {
|
||||||
|
propertyExpr = new PropertyExpression(root, part);
|
||||||
|
} else {
|
||||||
|
propertyExpr = new PropertyExpression(propertyExpr, part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final var positionVisitor = new PositionVisitor(this.positionSetter, dollarReferenceNode);
|
||||||
|
if (propertyExpr != null) {
|
||||||
|
propertyExpr.visit(positionVisitor);
|
||||||
|
return this.leftShiftFactory.create(propertyExpr);
|
||||||
|
} else if (root != null) {
|
||||||
|
root.visit(positionVisitor);
|
||||||
|
return this.leftShiftFactory.create(root);
|
||||||
|
} else {
|
||||||
|
throw new WebViewComponentBugError("Did not expect root to be null.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Statement createGroovyBodyNodeStatements(GroovyBodyNode groovyBodyNode, TranspilerState state) {
|
||||||
|
return switch (groovyBodyNode) {
|
||||||
|
case EqualsScriptletNode equalsScriptletNode -> this.handleEqualsScriptlet(equalsScriptletNode, state);
|
||||||
|
case PlainScriptletNode plainScriptletNode -> this.handlePlainScriptlet(plainScriptletNode, state);
|
||||||
|
case DollarScriptletNode dollarScriptletNode -> this.handleDollarScriptlet(dollarScriptletNode);
|
||||||
|
case DollarReferenceNode dollarReferenceNode -> this.handleDollarReference(dollarReferenceNode);
|
||||||
|
default -> throw new WebViewComponentBugError(new UnsupportedOperationException(
|
||||||
|
"GroovyBodyNode of type " + groovyBodyNode.getClass().getName() + " is not supported."
|
||||||
|
));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,12 +3,11 @@ package groowt.view.component.web.transpile;
|
|||||||
import groowt.view.component.web.ast.node.JStringBodyTextNode;
|
import groowt.view.component.web.ast.node.JStringBodyTextNode;
|
||||||
import groowt.view.component.web.ast.node.JStringValueNode;
|
import groowt.view.component.web.ast.node.JStringValueNode;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Singleton;
|
|
||||||
import org.codehaus.groovy.ast.expr.ConstantExpression;
|
import org.codehaus.groovy.ast.expr.ConstantExpression;
|
||||||
|
|
||||||
import static org.apache.groovy.parser.antlr4.util.StringUtils.*;
|
import static org.apache.groovy.parser.antlr4.util.StringUtils.*;
|
||||||
|
|
||||||
@Singleton
|
@Deprecated
|
||||||
public class DefaultJStringTranspiler implements JStringTranspiler {
|
public class DefaultJStringTranspiler implements JStringTranspiler {
|
||||||
|
|
||||||
private final PositionSetter positionSetter;
|
private final PositionSetter positionSetter;
|
||||||
|
@ -28,7 +28,7 @@ public class DefaultTranspilerConfiguration implements TranspilerConfiguration {
|
|||||||
DefaultProvider.ofLazy(BodyTranspiler.class, this::getBodyTranspiler)
|
DefaultProvider.ofLazy(BodyTranspiler.class, this::getBodyTranspiler)
|
||||||
);
|
);
|
||||||
this.valueNodeTranspiler = new DefaultValueNodeTranspiler(componentTranspiler);
|
this.valueNodeTranspiler = new DefaultValueNodeTranspiler(componentTranspiler);
|
||||||
this.bodyTranspiler = new DefaultBodyTranspiler(gStringTranspiler, jStringTranspiler, componentTranspiler);
|
this.bodyTranspiler = new DefaultBodyTranspiler(componentTranspiler, null); // TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
|
import groowt.view.component.web.ast.node.GroovyBodyNode;
|
||||||
|
import org.codehaus.groovy.ast.stmt.Statement;
|
||||||
|
|
||||||
|
public interface GroovyBodyNodeTranspiler {
|
||||||
|
Statement createGroovyBodyNodeStatements(GroovyBodyNode groovyBodyNode, TranspilerState state);
|
||||||
|
}
|
@ -4,6 +4,7 @@ import groowt.view.component.web.ast.node.JStringBodyTextNode;
|
|||||||
import groowt.view.component.web.ast.node.JStringValueNode;
|
import groowt.view.component.web.ast.node.JStringValueNode;
|
||||||
import org.codehaus.groovy.ast.expr.ConstantExpression;
|
import org.codehaus.groovy.ast.expr.ConstantExpression;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public interface JStringTranspiler {
|
public interface JStringTranspiler {
|
||||||
ConstantExpression createStringLiteral(JStringBodyTextNode bodyTextNode);
|
ConstantExpression createStringLiteral(JStringBodyTextNode bodyTextNode);
|
||||||
ConstantExpression createStringLiteral(JStringValueNode jStringValueNode);
|
ConstantExpression createStringLiteral(JStringValueNode jStringValueNode);
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
|
import org.codehaus.groovy.ast.expr.Expression;
|
||||||
|
import org.codehaus.groovy.ast.stmt.Statement;
|
||||||
|
|
||||||
|
public interface LeftShiftFactory {
|
||||||
|
Statement create(Expression rightSide);
|
||||||
|
}
|
@ -2,6 +2,7 @@ package groowt.view.component.web.transpile;
|
|||||||
|
|
||||||
import groowt.view.component.web.ast.node.Node;
|
import groowt.view.component.web.ast.node.Node;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.codehaus.groovy.ast.ASTNode;
|
import org.codehaus.groovy.ast.ASTNode;
|
||||||
|
|
||||||
public interface PositionSetter {
|
public interface PositionSetter {
|
||||||
@ -24,8 +25,17 @@ public interface PositionSetter {
|
|||||||
*/
|
*/
|
||||||
void setPositionOffsetInContainer(ASTNode target, Node container);
|
void setPositionOffsetInContainer(ASTNode target, Node container);
|
||||||
|
|
||||||
|
void setPosition(ASTNode target, Token source);
|
||||||
|
|
||||||
void setPosition(ASTNode target, TokenRange tokenRange);
|
void setPosition(ASTNode target, TokenRange tokenRange);
|
||||||
void setPosition(ASTNode target, Node source);
|
void setPosition(ASTNode target, Node source);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
void setPosition(ASTNode target, Node start, Node end);
|
void setPosition(ASTNode target, Node start, Node end);
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
void setToStartOf(ASTNode target, Node source);
|
void setToStartOf(ASTNode target, Node source);
|
||||||
|
|
||||||
|
PositionSetter withOffset(int lineOffset, int columnOffset);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,35 @@ package groowt.view.component.web.transpile;
|
|||||||
import groowt.view.component.web.ast.node.Node;
|
import groowt.view.component.web.ast.node.Node;
|
||||||
import groowt.view.component.web.util.SourcePosition;
|
import groowt.view.component.web.util.SourcePosition;
|
||||||
import groowt.view.component.web.util.TokenRange;
|
import groowt.view.component.web.util.TokenRange;
|
||||||
|
import org.antlr.v4.runtime.Token;
|
||||||
import org.codehaus.groovy.ast.ASTNode;
|
import org.codehaus.groovy.ast.ASTNode;
|
||||||
|
|
||||||
|
import static groowt.view.component.web.util.SourcePosition.fromEndOfToken;
|
||||||
|
import static groowt.view.component.web.util.SourcePosition.fromStartOfToken;
|
||||||
|
|
||||||
public class SimplePositionSetter implements PositionSetter {
|
public class SimplePositionSetter implements PositionSetter {
|
||||||
|
|
||||||
protected void set(ASTNode target, int startLine, int startColumn, int endLine, int endColumn) {
|
private final int lineOffset;
|
||||||
target.setLineNumber(startLine);
|
private final int columnOffset;
|
||||||
target.setColumnNumber(startColumn);
|
|
||||||
target.setLastLineNumber(endLine);
|
public SimplePositionSetter(int lineOffset, int columnOffset) {
|
||||||
target.setLastColumnNumber(endColumn);
|
this.lineOffset = lineOffset;
|
||||||
|
this.columnOffset = columnOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void set(ASTNode target, SourcePosition start, SourcePosition end) {
|
public SimplePositionSetter() {
|
||||||
|
this.lineOffset = 0;
|
||||||
|
this.columnOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void set(ASTNode target, int startLine, int startColumn, int endLine, int endColumn) {
|
||||||
|
target.setLineNumber(startLine + this.lineOffset);
|
||||||
|
target.setColumnNumber(startColumn + this.columnOffset);
|
||||||
|
target.setLastLineNumber(endLine + this.lineOffset);
|
||||||
|
target.setLastColumnNumber(endColumn + this.columnOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void set(ASTNode target, SourcePosition start, SourcePosition end) {
|
||||||
this.set(target, start.line(), start.column(), end.line(), end.column());
|
this.set(target, start.line(), start.column(), end.line(), end.column());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +53,11 @@ public class SimplePositionSetter implements PositionSetter {
|
|||||||
this.set(target, startPosition, endPosition);
|
this.set(target, startPosition, endPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPosition(ASTNode target, Token source) {
|
||||||
|
this.set(target, fromStartOfToken(source), fromEndOfToken(source));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPosition(ASTNode target, TokenRange tokenRange) {
|
public void setPosition(ASTNode target, TokenRange tokenRange) {
|
||||||
this.set(target, tokenRange.getStartPosition(), tokenRange.getEndPosition());
|
this.set(target, tokenRange.getStartPosition(), tokenRange.getEndPosition());
|
||||||
@ -49,11 +71,8 @@ public class SimplePositionSetter implements PositionSetter {
|
|||||||
@Override
|
@Override
|
||||||
public void setPosition(ASTNode target, Node start, Node end) {
|
public void setPosition(ASTNode target, Node start, Node end) {
|
||||||
final var startPosition = start.getTokenRange().getStartPosition();
|
final var startPosition = start.getTokenRange().getStartPosition();
|
||||||
target.setLineNumber(startPosition.line());
|
|
||||||
target.setColumnNumber(startPosition.column());
|
|
||||||
final var endPosition = end.getTokenRange().getEndPosition();
|
final var endPosition = end.getTokenRange().getEndPosition();
|
||||||
target.setLastLineNumber(endPosition.line());
|
this.set(target, startPosition, endPosition);
|
||||||
target.setLastColumnNumber(endPosition.column());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -62,4 +81,9 @@ public class SimplePositionSetter implements PositionSetter {
|
|||||||
this.set(target, tokenRange.getStartPosition(), tokenRange.getStartPosition());
|
this.set(target, tokenRange.getStartPosition(), tokenRange.getStartPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionSetter withOffset(int lineOffset, int columnOffset) {
|
||||||
|
return new SimplePositionSetter(lineOffset, columnOffset);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import org.codehaus.groovy.ast.expr.ConstantExpression;
|
|||||||
import org.codehaus.groovy.syntax.Token;
|
import org.codehaus.groovy.syntax.Token;
|
||||||
import org.codehaus.groovy.syntax.Types;
|
import org.codehaus.groovy.syntax.Types;
|
||||||
|
|
||||||
|
import static org.apache.groovy.parser.antlr4.util.StringUtils.*;
|
||||||
|
|
||||||
public final class TranspilerUtil {
|
public final class TranspilerUtil {
|
||||||
|
|
||||||
public static final ClassNode COMPONENT_TEMPLATE = ClassHelper.make(ComponentTemplate.class);
|
public static final ClassNode COMPONENT_TEMPLATE = ClassHelper.make(ComponentTemplate.class);
|
||||||
@ -39,9 +41,11 @@ public final class TranspilerUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ConstantExpression getStringLiteral(String content) {
|
public static ConstantExpression getStringLiteral(String content) {
|
||||||
final var e = new ConstantExpression(content);
|
final var withoutCR = removeCR(content);
|
||||||
e.setNodeMetaData("_IS_STRING", true);
|
final var escaped = replaceEscapes(withoutCR, NONE_SLASHY);
|
||||||
return e;
|
final var expr = new ConstantExpression(escaped);
|
||||||
|
expr.setNodeMetaData("_IS_STRING", true);
|
||||||
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Token getAssignToken() {
|
public static Token getAssignToken() {
|
||||||
|
@ -4,10 +4,5 @@ import groowt.view.component.web.ast.node.ValueNode;
|
|||||||
import org.codehaus.groovy.ast.expr.Expression;
|
import org.codehaus.groovy.ast.expr.Expression;
|
||||||
|
|
||||||
public interface ValueNodeTranspiler {
|
public interface ValueNodeTranspiler {
|
||||||
|
Expression createExpression(ValueNode valueNode, TranspilerState state);
|
||||||
Expression createExpression(
|
|
||||||
ValueNode valueNode,
|
|
||||||
TranspilerState state
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -80,15 +80,25 @@ public abstract class NodeFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void questionTagNode(@Mock QuestionTagChild child, @Mock TreeNode childAsNode) {
|
public void questionTagNode(
|
||||||
|
@Mock Token open,
|
||||||
|
@Mock Token close,
|
||||||
|
@Mock QuestionTagChild child,
|
||||||
|
@Mock TreeNode childAsNode
|
||||||
|
) {
|
||||||
when(child.asNode()).thenReturn(childAsNode);
|
when(child.asNode()).thenReturn(childAsNode);
|
||||||
assertNotNull(this.nodeFactory.questionTagNode(this.getTokenRange(), List.of(child)));
|
assertNotNull(this.nodeFactory.questionTagNode(this.getTokenRange(), open, close, List.of(child)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void htmlCommentNode(@Mock HtmlCommentChild child, @Mock TreeNode childAsNode) {
|
public void htmlCommentNode(
|
||||||
|
@Mock Token open,
|
||||||
|
@Mock Token close,
|
||||||
|
@Mock HtmlCommentChild child,
|
||||||
|
@Mock TreeNode childAsNode
|
||||||
|
) {
|
||||||
when(child.asNode()).thenReturn(childAsNode);
|
when(child.asNode()).thenReturn(childAsNode);
|
||||||
assertNotNull(this.nodeFactory.htmlCommentNode(this.getTokenRange(), List.of(child)));
|
assertNotNull(this.nodeFactory.htmlCommentNode(this.getTokenRange(), open, close, List.of(child)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -218,7 +228,7 @@ public abstract class NodeFactoryTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void dollarScriptletNode() {
|
public void dollarScriptletNode() {
|
||||||
assertNotNull(this.nodeFactory.dollarScriptletNode(this.getTokenRange(), 0));
|
assertNotNull(this.nodeFactory.dollarScriptletNode(this.getTokenRange(), ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user