Refactoring DefaultGroovyTranspiler.
This commit is contained in:
parent
449c83975f
commit
3f45609236
@ -6,17 +6,25 @@ import groowt.view.component.compiler.source.ComponentTemplateSource;
|
|||||||
public abstract class AbstractComponentTemplateCompileUnit implements
|
public abstract class AbstractComponentTemplateCompileUnit implements
|
||||||
ComponentTemplateCompileUnit {
|
ComponentTemplateCompileUnit {
|
||||||
|
|
||||||
|
private final String descriptiveName;
|
||||||
private final Class<? extends ViewComponent> forClass;
|
private final Class<? extends ViewComponent> forClass;
|
||||||
private final ComponentTemplateSource source;
|
private final ComponentTemplateSource source;
|
||||||
|
|
||||||
public AbstractComponentTemplateCompileUnit(
|
public AbstractComponentTemplateCompileUnit(
|
||||||
|
String descriptiveName,
|
||||||
Class<? extends ViewComponent> forClass,
|
Class<? extends ViewComponent> forClass,
|
||||||
ComponentTemplateSource source
|
ComponentTemplateSource source
|
||||||
) {
|
) {
|
||||||
|
this.descriptiveName = descriptiveName;
|
||||||
this.forClass = forClass;
|
this.forClass = forClass;
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescriptiveName() {
|
||||||
|
return this.descriptiveName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends ViewComponent> getForClass() {
|
public Class<? extends ViewComponent> getForClass() {
|
||||||
return this.forClass;
|
return this.forClass;
|
||||||
|
@ -22,7 +22,7 @@ public class ComponentTemplateCompileException extends Exception {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
final var sb = new StringBuilder("Error in ").append(compileUnit.getSource().getDescription());
|
final var sb = new StringBuilder("Error in ").append(compileUnit.getSource().getDescriptiveName());
|
||||||
final @Nullable String position = this.formatPosition();
|
final @Nullable String position = this.formatPosition();
|
||||||
if (position != null) {
|
if (position != null) {
|
||||||
sb.append(" at ").append(position);
|
sb.append(" at ").append(position);
|
||||||
|
@ -5,6 +5,7 @@ import groowt.view.component.compiler.source.ComponentTemplateSource;
|
|||||||
|
|
||||||
public interface ComponentTemplateCompileUnit {
|
public interface ComponentTemplateCompileUnit {
|
||||||
|
|
||||||
|
String getDescriptiveName();
|
||||||
Class<? extends ViewComponent> getForClass();
|
Class<? extends ViewComponent> getForClass();
|
||||||
String getDefaultPackageName();
|
String getDefaultPackageName();
|
||||||
ComponentTemplateSource getSource();
|
ComponentTemplateSource getSource();
|
||||||
|
@ -46,7 +46,7 @@ public interface ComponentTemplateSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Reader toReader() throws Exception;
|
Reader toReader() throws Exception;
|
||||||
String getDescription();
|
String getDescriptiveName();
|
||||||
boolean canReopen();
|
boolean canReopen();
|
||||||
List<String> getLines();
|
List<String> getLines();
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ public class FileSource implements ComponentTemplateSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescriptiveName() {
|
||||||
return this.templateFile.toString();
|
return this.templateFile.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public class InputStreamSource implements ComponentTemplateSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescriptiveName() {
|
||||||
return this.description != null ? this.description : "<anonymous InputStream source>";
|
return this.description != null ? this.description : "<anonymous InputStream source>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ public class ReaderSource implements ComponentTemplateSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescriptiveName() {
|
||||||
return this.description != null ? this.description : "<anonymous Reader source>";
|
return this.description != null ? this.description : "<anonymous Reader source>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ public class StringSource implements ComponentTemplateSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescriptiveName() {
|
||||||
return this.name != null ? this.name : "<anonymous string source>";
|
return this.name != null ? this.name : "<anonymous string source>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ public class URISource implements ComponentTemplateSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescriptiveName() {
|
||||||
return this.templateURI.toString();
|
return this.templateURI.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ public class URLSource implements ComponentTemplateSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescriptiveName() {
|
||||||
return this.url.toString();
|
return this.url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ public class DelegatingWebViewComponentTemplateParserPlugin implements ParserPlu
|
|||||||
final String sourceUnitFileName = sourceUnitFullName.substring(lastSlashIndex + 1);
|
final String sourceUnitFileName = sourceUnitFullName.substring(lastSlashIndex + 1);
|
||||||
if (sourceUnitFileName.endsWith(".wvc")) {
|
if (sourceUnitFileName.endsWith(".wvc")) {
|
||||||
final var compileUnit = new DefaultWebViewComponentTemplateCompileUnit(
|
final var compileUnit = new DefaultWebViewComponentTemplateCompileUnit(
|
||||||
|
sourceUnitFileName,
|
||||||
AnonymousWebViewComponent.class,
|
AnonymousWebViewComponent.class,
|
||||||
ComponentTemplateSource.of(sourceUnit.getSource().getURI()),
|
ComponentTemplateSource.of(sourceUnit.getSource().getURI()),
|
||||||
"" // default package
|
"" // default package
|
||||||
@ -79,13 +80,13 @@ public class DelegatingWebViewComponentTemplateParserPlugin implements ParserPlu
|
|||||||
}
|
}
|
||||||
|
|
||||||
final var groovyTranspiler = new DefaultGroovyTranspiler();
|
final var groovyTranspiler = new DefaultGroovyTranspiler();
|
||||||
final String nameWithoutExtension = sourceUnitFileName.substring(0, sourceUnitFileName.length() - 4);
|
final String teplateClassSimpleName = sourceUnitFileName.substring(0, sourceUnitFileName.length() - 4);
|
||||||
try {
|
try {
|
||||||
final SourceUnit transpiledSourceUnit = groovyTranspiler.transpile(
|
final SourceUnit transpiledSourceUnit = groovyTranspiler.transpile(
|
||||||
new DefaultComponentTemplateCompilerConfiguration(),
|
new DefaultComponentTemplateCompilerConfiguration(),
|
||||||
compileUnit,
|
compileUnit,
|
||||||
cuNode,
|
cuNode,
|
||||||
nameWithoutExtension
|
teplateClassSimpleName
|
||||||
);
|
);
|
||||||
return transpiledSourceUnit.getAST();
|
return transpiledSourceUnit.getAST();
|
||||||
} catch (ComponentTemplateCompileException e) {
|
} catch (ComponentTemplateCompileException e) {
|
||||||
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public class DefaultGStringTranspiler implements GStringTranspiler {
|
public class DefaultGStringTranspiler implements GStringTranspiler {
|
||||||
|
|
||||||
private final PositionSetter positionSetter;
|
private final PositionSetter positionSetter;
|
||||||
|
@ -2,6 +2,7 @@ package groowt.view.component.web.transpile;
|
|||||||
|
|
||||||
import groovy.transform.Field;
|
import groovy.transform.Field;
|
||||||
import groowt.view.component.compiler.ComponentTemplateCompileException;
|
import groowt.view.component.compiler.ComponentTemplateCompileException;
|
||||||
|
import groowt.view.component.compiler.ComponentTemplateCompileUnit;
|
||||||
import groowt.view.component.compiler.ComponentTemplateCompilerConfiguration;
|
import groowt.view.component.compiler.ComponentTemplateCompilerConfiguration;
|
||||||
import groowt.view.component.web.WebViewComponentBugError;
|
import groowt.view.component.web.WebViewComponentBugError;
|
||||||
import groowt.view.component.web.ast.node.BodyNode;
|
import groowt.view.component.web.ast.node.BodyNode;
|
||||||
@ -10,7 +11,7 @@ import groowt.view.component.web.ast.node.PreambleNode;
|
|||||||
import groowt.view.component.web.compiler.MultipleWebViewComponentCompileErrorsException;
|
import groowt.view.component.web.compiler.MultipleWebViewComponentCompileErrorsException;
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileException;
|
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileException;
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
||||||
import groowt.view.component.web.runtime.DefaultWebViewRenderContext;
|
import groowt.view.component.web.transpile.BodyTranspiler.AddOrAppendCallback;
|
||||||
import groowt.view.component.web.transpile.groovy.GroovyUtil;
|
import groowt.view.component.web.transpile.groovy.GroovyUtil;
|
||||||
import groowt.view.component.web.transpile.resolve.ClassLoaderComponentClassNodeResolver;
|
import groowt.view.component.web.transpile.resolve.ClassLoaderComponentClassNodeResolver;
|
||||||
import org.codehaus.groovy.ast.*;
|
import org.codehaus.groovy.ast.*;
|
||||||
@ -19,9 +20,8 @@ import org.codehaus.groovy.ast.stmt.BlockStatement;
|
|||||||
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
|
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
|
||||||
import org.codehaus.groovy.ast.stmt.ReturnStatement;
|
import org.codehaus.groovy.ast.stmt.ReturnStatement;
|
||||||
import org.codehaus.groovy.ast.stmt.Statement;
|
import org.codehaus.groovy.ast.stmt.Statement;
|
||||||
import org.codehaus.groovy.control.CompilationUnit;
|
import org.codehaus.groovy.control.CompilerConfiguration;
|
||||||
import org.codehaus.groovy.control.ErrorCollector;
|
import org.codehaus.groovy.control.ErrorCollector;
|
||||||
import org.codehaus.groovy.control.SourceUnit;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -30,29 +30,58 @@ import java.util.List;
|
|||||||
import static groowt.view.component.web.transpile.TranspilerUtil.*;
|
import static groowt.view.component.web.transpile.TranspilerUtil.*;
|
||||||
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes a Groovy {@link CompilationUnit} in the constructor and adds a {@link SourceUnit} representing the target
|
|
||||||
* Groovy code for the template represented by the AST passed to {@link #transpile}.
|
|
||||||
* <p>
|
|
||||||
* Note that while the terminology is similar, a Groovy {@link CompilationUnit} is distinct from our own
|
|
||||||
* {@link CompilationUnitNode}.
|
|
||||||
*/
|
|
||||||
public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DefaultGroovyTranspiler.class);
|
private static final Logger logger = LoggerFactory.getLogger(DefaultGroovyTranspiler.class);
|
||||||
|
|
||||||
private static final ClassNode FIELD_ANNOTATION = ClassHelper.make(Field.class);
|
private static final ClassNode FIELD_ANNOTATION = ClassHelper.make(Field.class);
|
||||||
private static final ClassNode RENDER_CONTEXT_IMPLEMENTATION =
|
|
||||||
ClassHelper.make(DefaultWebViewRenderContext.class);
|
|
||||||
|
|
||||||
protected TranspilerConfiguration getConfiguration(
|
protected TranspilerConfiguration getConfiguration(
|
||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
WebViewComponentTemplateCompileUnit compileUnit,
|
||||||
ModuleNode moduleNode,
|
|
||||||
ClassLoader classLoader
|
ClassLoader classLoader
|
||||||
) {
|
) {
|
||||||
return new DefaultTranspilerConfiguration(new ClassLoaderComponentClassNodeResolver(
|
return new DefaultTranspilerConfiguration(new ClassLoaderComponentClassNodeResolver(compileUnit, classLoader));
|
||||||
compileUnit, moduleNode, classLoader
|
}
|
||||||
|
|
||||||
|
protected void addAutomaticImports(WebViewComponentModuleNode moduleNode, TranspilerConfiguration configuration) {
|
||||||
|
configuration.getImports().forEach(moduleNode::addImport);
|
||||||
|
configuration.getStaticImports().forEach(staticImport -> moduleNode.addStaticImport(
|
||||||
|
staticImport.getV1(), staticImport.getV2(), staticImport.getV3()
|
||||||
));
|
));
|
||||||
|
configuration.getStarImports().forEach(moduleNode::addStarImport);
|
||||||
|
configuration.getStaticStarImports().forEach(moduleNode::addStaticStarImport);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WebViewComponentModuleNode initModuleNode(
|
||||||
|
ComponentTemplateCompileUnit compileUnit,
|
||||||
|
WebViewComponentSourceUnit sourceUnit,
|
||||||
|
TranspilerConfiguration configuration
|
||||||
|
) {
|
||||||
|
final var moduleNode = new WebViewComponentModuleNode(sourceUnit);
|
||||||
|
sourceUnit.setModuleNode(moduleNode);
|
||||||
|
|
||||||
|
final String defaultPackageName = compileUnit.getDefaultPackageName();
|
||||||
|
if (!defaultPackageName.trim().isEmpty()) {
|
||||||
|
moduleNode.setPackageName(defaultPackageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addAutomaticImports(moduleNode, configuration);
|
||||||
|
return moduleNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ClassNode initMainClassNode(
|
||||||
|
ComponentTemplateCompileUnit compileUnit,
|
||||||
|
String templateClassName,
|
||||||
|
WebViewComponentModuleNode moduleNode
|
||||||
|
) {
|
||||||
|
final ClassNode mainClassNode = new ClassNode(
|
||||||
|
compileUnit.getDefaultPackageName() + templateClassName,
|
||||||
|
ACC_PUBLIC,
|
||||||
|
ClassHelper.OBJECT_TYPE
|
||||||
|
);
|
||||||
|
mainClassNode.addInterface(TranspilerUtil.COMPONENT_TEMPLATE);
|
||||||
|
moduleNode.addClass(mainClassNode);
|
||||||
|
return mainClassNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkPreambleClasses(String templateName, List<ClassNode> classNodes) {
|
protected void checkPreambleClasses(String templateName, List<ClassNode> classNodes) {
|
||||||
@ -72,17 +101,27 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
String templateClassName,
|
String templateClassName,
|
||||||
PreambleNode preambleNode,
|
PreambleNode preambleNode,
|
||||||
ClassNode mainClassNode,
|
ClassNode mainClassNode,
|
||||||
WebViewComponentModuleNode moduleNode
|
WebViewComponentModuleNode moduleNode,
|
||||||
|
PositionSetter positionSetter
|
||||||
) {
|
) {
|
||||||
final GroovyUtil.ConvertResult convertResult = GroovyUtil.convert(
|
final GroovyUtil.ConvertResult convertResult = GroovyUtil.convert(
|
||||||
preambleNode.getGroovyCode().getAsValidGroovyCode()
|
preambleNode.getGroovyCode().getAsValidGroovyCode()
|
||||||
);
|
);
|
||||||
|
final ModuleNode convertModuleNode = convertResult.moduleNode();
|
||||||
|
|
||||||
WebViewComponentModuleNode.copyTo(convertResult.moduleNode(), moduleNode);
|
final PositionVisitor positionVisitor = new PositionVisitor(positionSetter, preambleNode);
|
||||||
|
|
||||||
|
convertModuleNode.getImports().forEach(moduleNode::addImport);
|
||||||
|
convertModuleNode.getStarImports().forEach(moduleNode::addStarImport);
|
||||||
|
convertModuleNode.getStaticImports().forEach(moduleNode::addStaticImport);
|
||||||
|
convertModuleNode.getStaticStarImports().forEach(moduleNode::addStaticStarImport);
|
||||||
|
positionVisitor.visitImports(moduleNode);
|
||||||
|
|
||||||
|
// if user supplied a package, use it
|
||||||
if (convertResult.moduleNode().hasPackage()) {
|
if (convertResult.moduleNode().hasPackage()) {
|
||||||
moduleNode.setPackage(convertResult.moduleNode().getPackage());
|
moduleNode.setPackage(convertResult.moduleNode().getPackage());
|
||||||
mainClassNode.setName(moduleNode.getPackageName() + templateClassName);
|
mainClassNode.setName(moduleNode.getPackageName() + templateClassName);
|
||||||
|
positionVisitor.visitPackage(moduleNode.getPackage());
|
||||||
}
|
}
|
||||||
|
|
||||||
final BlockStatement preambleBlock = convertResult.blockStatement();
|
final BlockStatement preambleBlock = convertResult.blockStatement();
|
||||||
@ -100,6 +139,7 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
if (declarationsWithField.size() != preambleStatements.size()) {
|
if (declarationsWithField.size() != preambleStatements.size()) {
|
||||||
|
// TODO: figure out why we have extraneous statements sometimes when it seems otherwise not
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"{} contains script statements which are not supported. " +
|
"{} contains script statements which are not supported. " +
|
||||||
"Currently, only classes, methods, and field declarations " +
|
"Currently, only classes, methods, and field declarations " +
|
||||||
@ -110,13 +150,19 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
}
|
}
|
||||||
declarationsWithField.forEach(declaration -> {
|
declarationsWithField.forEach(declaration -> {
|
||||||
declaration.setDeclaringClass(mainClassNode);
|
declaration.setDeclaringClass(mainClassNode);
|
||||||
|
positionVisitor.visitDeclarationExpression(declaration);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// move methods from script class
|
// move methods from script class
|
||||||
final ClassNode scriptClass = convertResult.scriptClass();
|
final ClassNode scriptClass = convertResult.scriptClass();
|
||||||
if (scriptClass != null) {
|
if (scriptClass != null) {
|
||||||
scriptClass.getMethods().forEach(mainClassNode::addMethod);
|
scriptClass.getMethods().stream()
|
||||||
|
.filter(method -> !(method.getName().equals("main") || method.getName().equals("run")))
|
||||||
|
.forEach(method -> {
|
||||||
|
mainClassNode.addMethod(method);
|
||||||
|
positionVisitor.visitMethod(method);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle classes
|
// handle classes
|
||||||
@ -124,62 +170,127 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
this.checkPreambleClasses(templateClassName, classNodes);
|
this.checkPreambleClasses(templateClassName, classNodes);
|
||||||
classNodes.stream()
|
classNodes.stream()
|
||||||
.filter(classNode -> classNode != convertResult.scriptClass())
|
.filter(classNode -> classNode != convertResult.scriptClass())
|
||||||
.forEach(moduleNode::addClass);
|
.forEach(classNode -> {
|
||||||
|
moduleNode.addClass(classNode);
|
||||||
|
positionVisitor.visitClass(classNode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ExpressionStatement constructRenderContext(
|
||||||
|
ClassNode renderContextImplementation,
|
||||||
|
Variable componentContextParam,
|
||||||
|
Variable writerParam,
|
||||||
|
VariableExpression renderContextVariableExpr
|
||||||
|
) {
|
||||||
|
final ConstructorCallExpression renderContextConstructor = new ConstructorCallExpression(
|
||||||
|
renderContextImplementation,
|
||||||
|
new ArgumentListExpression(
|
||||||
|
new VariableExpression(componentContextParam),
|
||||||
|
new VariableExpression(writerParam)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
final BinaryExpression renderContextAssignExpr = new DeclarationExpression(
|
||||||
|
renderContextVariableExpr,
|
||||||
|
getAssignToken(),
|
||||||
|
renderContextConstructor
|
||||||
|
);
|
||||||
|
return new ExpressionStatement(renderContextAssignExpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ExpressionStatement assignComponentContextRenderContext(
|
||||||
|
Parameter componentContextParam,
|
||||||
|
VariableExpression renderContextVariableExpr
|
||||||
|
) {
|
||||||
|
final BinaryExpression componentContextRenderContextAssign = new BinaryExpression(
|
||||||
|
new PropertyExpression(new VariableExpression(componentContextParam), "renderContext"),
|
||||||
|
getAssignToken(),
|
||||||
|
renderContextVariableExpr
|
||||||
|
);
|
||||||
|
return new ExpressionStatement(componentContextRenderContextAssign);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ExpressionStatement assignWriterRenderContext(
|
||||||
|
Parameter writerParam,
|
||||||
|
VariableExpression renderContextVariableExpr
|
||||||
|
) {
|
||||||
|
final BinaryExpression writerRenderContextAssign = new BinaryExpression(
|
||||||
|
new PropertyExpression(new VariableExpression(writerParam), "renderContext"),
|
||||||
|
getAssignToken(),
|
||||||
|
renderContextVariableExpr
|
||||||
|
);
|
||||||
|
return new ExpressionStatement(writerRenderContextAssign);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ExpressionStatement assignWriterComponentContext(Parameter writerParam, Parameter componentContextParam) {
|
||||||
|
final BinaryExpression writerComponentContextAssign = new BinaryExpression(
|
||||||
|
new PropertyExpression(new VariableExpression(writerParam), "componentContext"),
|
||||||
|
getAssignToken(),
|
||||||
|
new VariableExpression(componentContextParam)
|
||||||
|
);
|
||||||
|
return new ExpressionStatement(writerComponentContextAssign);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Statement handleBody(
|
||||||
|
BodyNode bodyNode,
|
||||||
|
TranspilerConfiguration transpilerConfiguration,
|
||||||
|
TranspilerState state
|
||||||
|
) {
|
||||||
|
final var appendOrAddStatementFactory = transpilerConfiguration.getAppendOrAddStatementFactory();
|
||||||
|
final AddOrAppendCallback callback = (source, expr) -> appendOrAddStatementFactory.addOrAppend(
|
||||||
|
source,
|
||||||
|
state,
|
||||||
|
action -> {
|
||||||
|
if (action == AppendOrAddStatementFactory.Action.ADD) {
|
||||||
|
throw new WebViewComponentBugError(new IllegalStateException(
|
||||||
|
"Should not be adding from document root, only appending!"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return transpilerConfiguration.getBodyTranspiler().transpileBody(bodyNode, callback, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cases:
|
|
||||||
// - no preamble -> create our own class
|
|
||||||
// - some preamble, but no script -> create our own class but use imports/packageName from preamble
|
|
||||||
// - preamble with script -> use the script class from the converted preamble,
|
|
||||||
// and don't forget to call run in our render method
|
|
||||||
@Override
|
@Override
|
||||||
public WebViewComponentSourceUnit transpile(
|
public WebViewComponentSourceUnit transpile(
|
||||||
ComponentTemplateCompilerConfiguration compilerConfiguration,
|
ComponentTemplateCompilerConfiguration compilerConfiguration,
|
||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
WebViewComponentTemplateCompileUnit compileUnit,
|
||||||
CompilationUnitNode compilationUnitNode,
|
CompilationUnitNode compilationUnitNode,
|
||||||
String templateClassName
|
String templateClassSimpleName
|
||||||
) throws ComponentTemplateCompileException {
|
) throws ComponentTemplateCompileException {
|
||||||
final var groovyCompilerConfiguration = compilerConfiguration.getGroovyCompilerConfiguration();
|
// transpilerConfiguration and positionSetter
|
||||||
final var sourceUnit = new WebViewComponentSourceUnit(
|
final var transpilerConfiguration = this.getConfiguration(
|
||||||
templateClassName,
|
compileUnit, compileUnit.getGroovyCompilationUnit().getClassLoader()
|
||||||
|
);
|
||||||
|
final PositionSetter positionSetter = transpilerConfiguration.getPositionSetter();
|
||||||
|
|
||||||
|
// prepare sourceUnit
|
||||||
|
final CompilerConfiguration groovyCompilerConfiguration =
|
||||||
|
compilerConfiguration.getGroovyCompilerConfiguration();
|
||||||
|
final WebViewComponentSourceUnit sourceUnit = new WebViewComponentSourceUnit(
|
||||||
|
compileUnit.getDescriptiveName(),
|
||||||
compileUnit.getGroovyReaderSource(),
|
compileUnit.getGroovyReaderSource(),
|
||||||
groovyCompilerConfiguration,
|
groovyCompilerConfiguration,
|
||||||
compilerConfiguration.getGroovyClassLoader(),
|
compilerConfiguration.getGroovyClassLoader(),
|
||||||
new ErrorCollector(groovyCompilerConfiguration)
|
new ErrorCollector(groovyCompilerConfiguration)
|
||||||
);
|
);
|
||||||
|
|
||||||
final var moduleNode = new WebViewComponentModuleNode(sourceUnit);
|
// prepare moduleNode
|
||||||
sourceUnit.setModuleNode(moduleNode);
|
final WebViewComponentModuleNode moduleNode = this.initModuleNode(
|
||||||
|
compileUnit, sourceUnit, transpilerConfiguration
|
||||||
final String defaultPackageName = compileUnit.getDefaultPackageName();
|
|
||||||
if (!defaultPackageName.trim().isEmpty()) {
|
|
||||||
moduleNode.setPackageName(defaultPackageName);
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleNode.addStarImport(GROOWT_VIEW_COMPONENT_WEB + ".lib");
|
|
||||||
moduleNode.addImport(COMPONENT_TEMPLATE.getNameWithoutPackage(), COMPONENT_TEMPLATE);
|
|
||||||
moduleNode.addImport(COMPONENT_CONTEXT_TYPE.getNameWithoutPackage(), COMPONENT_CONTEXT_TYPE);
|
|
||||||
moduleNode.addStarImport("groowt.view.component.runtime");
|
|
||||||
moduleNode.addStarImport(GROOWT_VIEW_COMPONENT_WEB + ".runtime");
|
|
||||||
|
|
||||||
final ClassNode mainClassNode = new ClassNode(
|
|
||||||
compileUnit.getDefaultPackageName() + templateClassName,
|
|
||||||
ACC_PUBLIC,
|
|
||||||
ClassHelper.OBJECT_TYPE
|
|
||||||
);
|
);
|
||||||
mainClassNode.setScript(true);
|
|
||||||
mainClassNode.addInterface(TranspilerUtil.COMPONENT_TEMPLATE);
|
|
||||||
|
|
||||||
moduleNode.addClass(mainClassNode);
|
// prepare mainClassNode
|
||||||
|
final ClassNode mainClassNode = this.initMainClassNode(compileUnit, templateClassSimpleName, moduleNode);
|
||||||
|
|
||||||
// preamble
|
// handle preamble
|
||||||
final PreambleNode preambleNode = compilationUnitNode.getPreambleNode();
|
final PreambleNode preambleNode = compilationUnitNode.getPreambleNode();
|
||||||
if (preambleNode != null) {
|
if (preambleNode != null) {
|
||||||
this.handlePreamble(templateClassName, preambleNode, mainClassNode, moduleNode);
|
this.handlePreamble(templateClassSimpleName, preambleNode, mainClassNode, moduleNode, positionSetter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRenderer
|
// getRenderer method and render closure
|
||||||
// params
|
// first, getRenderer params
|
||||||
final Parameter componentContextParam = new Parameter(COMPONENT_CONTEXT_TYPE, COMPONENT_CONTEXT_NAME);
|
final Parameter componentContextParam = new Parameter(COMPONENT_CONTEXT_TYPE, COMPONENT_CONTEXT_NAME);
|
||||||
final Parameter writerParam = new Parameter(COMPONENT_WRITER_TYPE, COMPONENT_WRITER_NAME);
|
final Parameter writerParam = new Parameter(COMPONENT_WRITER_TYPE, COMPONENT_WRITER_NAME);
|
||||||
final VariableExpression renderContextVariable = new VariableExpression(
|
final VariableExpression renderContextVariable = new VariableExpression(
|
||||||
@ -187,98 +298,53 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
WEB_VIEW_COMPONENT_RENDER_CONTEXT_TYPE
|
WEB_VIEW_COMPONENT_RENDER_CONTEXT_TYPE
|
||||||
);
|
);
|
||||||
|
|
||||||
// closure body
|
// returned closure body
|
||||||
final BlockStatement renderBlock = new BlockStatement();
|
final BlockStatement renderBlock = new BlockStatement();
|
||||||
|
|
||||||
|
// init renderContext, componentContext, and writer properties
|
||||||
|
renderBlock.addStatement(this.constructRenderContext(
|
||||||
|
transpilerConfiguration.getRenderContextImplementation(),
|
||||||
|
componentContextParam,
|
||||||
|
writerParam,
|
||||||
|
renderContextVariable
|
||||||
|
));
|
||||||
|
renderBlock.addStatement(this.assignComponentContextRenderContext(
|
||||||
|
componentContextParam, renderContextVariable
|
||||||
|
));
|
||||||
|
renderBlock.addStatement(this.assignWriterRenderContext(writerParam, renderContextVariable));
|
||||||
|
renderBlock.addStatement(this.assignWriterComponentContext(writerParam, componentContextParam));
|
||||||
|
|
||||||
|
// init transpiler state
|
||||||
final TranspilerState state = TranspilerState.withRootScope(
|
final TranspilerState state = TranspilerState.withRootScope(
|
||||||
componentContextParam,
|
componentContextParam,
|
||||||
writerParam,
|
writerParam,
|
||||||
renderContextVariable
|
renderContextVariable
|
||||||
);
|
);
|
||||||
renderBlock.setVariableScope(state.getCurrentScope());
|
renderBlock.setVariableScope(state.getCurrentScope()); // root scope
|
||||||
|
|
||||||
// init: construct RenderContext
|
// body
|
||||||
final ConstructorCallExpression renderContextConstructor = new ConstructorCallExpression(
|
|
||||||
RENDER_CONTEXT_IMPLEMENTATION,
|
|
||||||
new ArgumentListExpression(
|
|
||||||
new VariableExpression(componentContextParam), // component context
|
|
||||||
new VariableExpression(writerParam)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
final BinaryExpression renderContextAssignExpr = new DeclarationExpression(
|
|
||||||
renderContextVariable,
|
|
||||||
getAssignToken(),
|
|
||||||
renderContextConstructor
|
|
||||||
);
|
|
||||||
renderBlock.addStatement(new ExpressionStatement(renderContextAssignExpr));
|
|
||||||
|
|
||||||
// init: componentContext.renderContext = renderContext
|
|
||||||
final BinaryExpression componentContextRenderContextAssign = new BinaryExpression(
|
|
||||||
new PropertyExpression(new VariableExpression(componentContextParam), "renderContext"),
|
|
||||||
getAssignToken(),
|
|
||||||
renderContextVariable
|
|
||||||
);
|
|
||||||
renderBlock.addStatement(new ExpressionStatement(componentContextRenderContextAssign));
|
|
||||||
|
|
||||||
// init: writer.renderContext = renderContext
|
|
||||||
final BinaryExpression writerRenderContextAssign = new BinaryExpression(
|
|
||||||
new PropertyExpression(new VariableExpression(writerParam), "renderContext"),
|
|
||||||
getAssignToken(),
|
|
||||||
renderContextVariable
|
|
||||||
);
|
|
||||||
renderBlock.addStatement(new ExpressionStatement(writerRenderContextAssign));
|
|
||||||
|
|
||||||
// init: writer.componentContext = componentContext
|
|
||||||
final BinaryExpression writerComponentContextAssign = new BinaryExpression(
|
|
||||||
new PropertyExpression(new VariableExpression(writerParam), "componentContext"),
|
|
||||||
getAssignToken(),
|
|
||||||
new VariableExpression(componentContextParam)
|
|
||||||
);
|
|
||||||
renderBlock.addStatement(new ExpressionStatement(writerComponentContextAssign));
|
|
||||||
|
|
||||||
// actual rendering of body
|
|
||||||
final var configuration = this.getConfiguration(
|
|
||||||
compileUnit,
|
|
||||||
moduleNode,
|
|
||||||
compilerConfiguration.getGroovyClassLoader()
|
|
||||||
);
|
|
||||||
final BodyNode bodyNode = compilationUnitNode.getBodyNode();
|
final BodyNode bodyNode = compilationUnitNode.getBodyNode();
|
||||||
if (bodyNode != null) {
|
if (bodyNode != null) {
|
||||||
final var appendOrAddStatementFactory = configuration.getAppendOrAddStatementFactory();
|
renderBlock.addStatement(this.handleBody(bodyNode, transpilerConfiguration, state));
|
||||||
renderBlock.addStatement(
|
|
||||||
configuration.getBodyTranspiler()
|
|
||||||
.transpileBody(
|
|
||||||
compilationUnitNode.getBodyNode(),
|
|
||||||
(source, expr) -> appendOrAddStatementFactory.addOrAppend(
|
|
||||||
source,
|
|
||||||
state,
|
|
||||||
action -> {
|
|
||||||
if (action == AppendOrAddStatementFactory.Action.ADD) {
|
|
||||||
throw new WebViewComponentBugError(new IllegalStateException(
|
|
||||||
"Should not be adding from document root!"
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return expr;
|
|
||||||
}
|
|
||||||
),
|
|
||||||
state
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return null from render closure
|
||||||
renderBlock.addStatement(new ReturnStatement(ConstantExpression.NULL));
|
renderBlock.addStatement(new ReturnStatement(ConstantExpression.NULL));
|
||||||
|
|
||||||
|
// make the closure
|
||||||
final ClosureExpression renderer = new ClosureExpression(
|
final ClosureExpression renderer = new ClosureExpression(
|
||||||
new Parameter[] { componentContextParam, writerParam },
|
new Parameter[] { componentContextParam, writerParam },
|
||||||
renderBlock
|
renderBlock
|
||||||
);
|
);
|
||||||
|
|
||||||
// getRenderer()
|
// getRenderer() return statement
|
||||||
final Statement returnRendererStmt = new ReturnStatement(renderer);
|
final Statement returnRendererStmt = new ReturnStatement(renderer);
|
||||||
|
|
||||||
|
// getRenderer() return type is Closure<Void>
|
||||||
final var voidClosure = ClassHelper.CLOSURE_TYPE.getPlainNodeReference();
|
final var voidClosure = ClassHelper.CLOSURE_TYPE.getPlainNodeReference();
|
||||||
voidClosure.setGenericsTypes(new GenericsType[] { new GenericsType(ClassHelper.void_WRAPPER_TYPE) });
|
voidClosure.setGenericsTypes(new GenericsType[] { new GenericsType(ClassHelper.void_WRAPPER_TYPE) });
|
||||||
|
|
||||||
|
// getRenderer method
|
||||||
final var getRenderer = new MethodNode(
|
final var getRenderer = new MethodNode(
|
||||||
GET_RENDERER,
|
GET_RENDERER,
|
||||||
ACC_PUBLIC,
|
ACC_PUBLIC,
|
||||||
@ -289,6 +355,7 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
);
|
);
|
||||||
mainClassNode.addMethod(getRenderer);
|
mainClassNode.addMethod(getRenderer);
|
||||||
|
|
||||||
|
// check for errors
|
||||||
if (state.hasErrors()) {
|
if (state.hasErrors()) {
|
||||||
final List<ComponentTemplateCompileException> errors = state.getErrors();
|
final List<ComponentTemplateCompileException> errors = state.getErrors();
|
||||||
if (errors.size() == 1) {
|
if (errors.size() == 1) {
|
||||||
@ -298,6 +365,7 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return the sourceUnit for later processing
|
||||||
return sourceUnit;
|
return sourceUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,26 @@
|
|||||||
package groowt.view.component.web.transpile;
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
|
import groovy.lang.Tuple3;
|
||||||
import groowt.util.fp.provider.DefaultProvider;
|
import groowt.util.fp.provider.DefaultProvider;
|
||||||
import groowt.view.component.web.transpile.resolve.ComponentClassNodeResolver;
|
import groowt.view.component.web.transpile.resolve.ComponentClassNodeResolver;
|
||||||
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static groowt.view.component.web.transpile.TranspilerUtil.*;
|
||||||
|
|
||||||
public class DefaultTranspilerConfiguration implements TranspilerConfiguration {
|
public class DefaultTranspilerConfiguration implements TranspilerConfiguration {
|
||||||
|
|
||||||
|
private final PositionSetter positionSetter;
|
||||||
private final AppendOrAddStatementFactory appendOrAddStatementFactory = new DefaultAppendOrAddStatementFactory();
|
private final AppendOrAddStatementFactory appendOrAddStatementFactory = new DefaultAppendOrAddStatementFactory();
|
||||||
private final BodyTranspiler bodyTranspiler;
|
private final BodyTranspiler bodyTranspiler;
|
||||||
private final ValueNodeTranspiler valueNodeTranspiler;
|
private final ValueNodeTranspiler valueNodeTranspiler;
|
||||||
|
|
||||||
public DefaultTranspilerConfiguration(ComponentClassNodeResolver classNodeResolver) {
|
public DefaultTranspilerConfiguration(ComponentClassNodeResolver classNodeResolver) {
|
||||||
final var positionSetter = new SimplePositionSetter();
|
this.positionSetter = new SimplePositionSetter();
|
||||||
final var jStringTranspiler = new DefaultJStringTranspiler(positionSetter);
|
final var jStringTranspiler = new DefaultJStringTranspiler(this.positionSetter);
|
||||||
final var gStringTranspiler = new DefaultGStringTranspiler(positionSetter, jStringTranspiler);
|
final var gStringTranspiler = new DefaultGStringTranspiler(this.positionSetter, jStringTranspiler);
|
||||||
final var componentTranspiler = new DefaultComponentTranspiler(
|
final var componentTranspiler = new DefaultComponentTranspiler(
|
||||||
DefaultProvider.of(this.appendOrAddStatementFactory),
|
DefaultProvider.of(this.appendOrAddStatementFactory),
|
||||||
DefaultProvider.of(classNodeResolver),
|
DefaultProvider.of(classNodeResolver),
|
||||||
@ -23,6 +31,11 @@ public class DefaultTranspilerConfiguration implements TranspilerConfiguration {
|
|||||||
this.bodyTranspiler = new DefaultBodyTranspiler(gStringTranspiler, jStringTranspiler, componentTranspiler);
|
this.bodyTranspiler = new DefaultBodyTranspiler(gStringTranspiler, jStringTranspiler, componentTranspiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PositionSetter getPositionSetter() {
|
||||||
|
return this.positionSetter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BodyTranspiler getBodyTranspiler() {
|
public BodyTranspiler getBodyTranspiler() {
|
||||||
return this.bodyTranspiler;
|
return this.bodyTranspiler;
|
||||||
@ -37,4 +50,36 @@ public class DefaultTranspilerConfiguration implements TranspilerConfiguration {
|
|||||||
return this.valueNodeTranspiler;
|
return this.valueNodeTranspiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ClassNode> getImports() {
|
||||||
|
return Map.of(
|
||||||
|
COMPONENT_TEMPLATE.getNameWithoutPackage(), COMPONENT_TEMPLATE,
|
||||||
|
COMPONENT_CONTEXT_TYPE.getNameWithoutPackage(), COMPONENT_CONTEXT_TYPE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getStarImports() {
|
||||||
|
return Set.of(
|
||||||
|
GROOWT_VIEW_COMPONENT_WEB + ".lib",
|
||||||
|
"groowt.view.component.runtime",
|
||||||
|
GROOWT_VIEW_COMPONENT_WEB + ".runtime"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<Tuple3<ClassNode, String, String>> getStaticImports() {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ClassNode> getStaticStarImports() {
|
||||||
|
return Map.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassNode getRenderContextImplementation() {
|
||||||
|
return DEFAULT_RENDER_CONTEXT_IMPLEMENTATION;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package groowt.view.component.web.transpile;
|
|||||||
import groowt.view.component.web.ast.node.GStringBodyTextNode;
|
import groowt.view.component.web.ast.node.GStringBodyTextNode;
|
||||||
import org.codehaus.groovy.ast.expr.GStringExpression;
|
import org.codehaus.groovy.ast.expr.GStringExpression;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public interface GStringTranspiler {
|
public interface GStringTranspiler {
|
||||||
GStringExpression createGStringExpression(GStringBodyTextNode parent);
|
GStringExpression createGStringExpression(GStringBodyTextNode parent);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ public interface GroovyTranspiler {
|
|||||||
ComponentTemplateCompilerConfiguration compilerConfiguration,
|
ComponentTemplateCompilerConfiguration compilerConfiguration,
|
||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
WebViewComponentTemplateCompileUnit compileUnit,
|
||||||
CompilationUnitNode compilationUnitNode,
|
CompilationUnitNode compilationUnitNode,
|
||||||
String templateClassName
|
String templateClassSimpleName
|
||||||
) throws ComponentTemplateCompileException;
|
) throws ComponentTemplateCompileException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,25 @@ import groowt.view.component.web.util.TokenRange;
|
|||||||
import org.codehaus.groovy.ast.ASTNode;
|
import org.codehaus.groovy.ast.ASTNode;
|
||||||
|
|
||||||
public interface PositionSetter {
|
public interface PositionSetter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the position of the Groovy node off-set from the start
|
||||||
|
* of the start of the Wvc node. The formula is
|
||||||
|
* thus:
|
||||||
|
* <pre>
|
||||||
|
* target.line = container.line + target.line - 1
|
||||||
|
* target.column = target.line == 1 ? container.column + target.column - 1 : target.column
|
||||||
|
* target.lastLine = container.line + target.lastLine - 1
|
||||||
|
* target.lastColumn = target.lastLine == 1 ? container.column + target.lastColumn - 1 : target.lastColumn
|
||||||
|
* </pre>
|
||||||
|
* For example, if the container has 2,1..4,1 and the target has
|
||||||
|
* 3,1..3,1 (in its source), the target will be adjusted to 4,1..4,1.
|
||||||
|
*
|
||||||
|
* @param target The (Groovy) node whose position is to be set.
|
||||||
|
* @param container The containing (Wvc) node.
|
||||||
|
*/
|
||||||
|
void setPositionOffsetInContainer(ASTNode target, Node container);
|
||||||
|
|
||||||
void setPosition(ASTNode target, TokenRange tokenRange);
|
void setPosition(ASTNode target, TokenRange tokenRange);
|
||||||
void setPosition(ASTNode target, Node source);
|
void setPosition(ASTNode target, Node source);
|
||||||
void setPosition(ASTNode target, Node start, Node end);
|
void setPosition(ASTNode target, Node start, Node end);
|
||||||
|
@ -0,0 +1,426 @@
|
|||||||
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
|
import groowt.view.component.web.ast.node.Node;
|
||||||
|
import org.codehaus.groovy.ast.*;
|
||||||
|
import org.codehaus.groovy.ast.expr.*;
|
||||||
|
import org.codehaus.groovy.ast.stmt.*;
|
||||||
|
import org.codehaus.groovy.classgen.BytecodeExpression;
|
||||||
|
import org.codehaus.groovy.control.SourceUnit;
|
||||||
|
|
||||||
|
// TODO: create a utility walker-visitor class to make this much simpler
|
||||||
|
public class PositionVisitor extends ClassCodeVisitorSupport {
|
||||||
|
|
||||||
|
private final PositionSetter positionSetter;
|
||||||
|
private final Node container;
|
||||||
|
|
||||||
|
public PositionVisitor(PositionSetter positionSetter, Node container) {
|
||||||
|
this.positionSetter = positionSetter;
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SourceUnit getSourceUnit() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitClass(ClassNode node) {
|
||||||
|
super.visitClass(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitAnnotations(AnnotatedNode node) {
|
||||||
|
super.visitAnnotations(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void visitAnnotation(AnnotationNode node) {
|
||||||
|
super.visitAnnotation(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitPackage(PackageNode node) {
|
||||||
|
super.visitPackage(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitImports(ModuleNode node) {
|
||||||
|
super.visitImports(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitConstructor(ConstructorNode node) {
|
||||||
|
super.visitConstructor(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMethod(MethodNode node) {
|
||||||
|
super.visitMethod(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
|
||||||
|
super.visitConstructorOrMethod(node, isConstructor);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitField(FieldNode node) {
|
||||||
|
super.visitField(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitProperty(PropertyNode node) {
|
||||||
|
super.visitProperty(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void visitObjectInitializerStatements(ClassNode node) {
|
||||||
|
super.visitObjectInitializerStatements(node);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(node, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitDeclarationExpression(DeclarationExpression expression) {
|
||||||
|
super.visitDeclarationExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitAssertStatement(AssertStatement statement) {
|
||||||
|
super.visitAssertStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBlockStatement(BlockStatement statement) {
|
||||||
|
super.visitBlockStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBreakStatement(BreakStatement statement) {
|
||||||
|
super.visitBreakStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCaseStatement(CaseStatement statement) {
|
||||||
|
super.visitCaseStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCatchStatement(CatchStatement statement) {
|
||||||
|
super.visitCatchStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitContinueStatement(ContinueStatement statement) {
|
||||||
|
super.visitContinueStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitDoWhileLoop(DoWhileStatement statement) {
|
||||||
|
super.visitDoWhileLoop(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitExpressionStatement(ExpressionStatement statement) {
|
||||||
|
super.visitExpressionStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitForLoop(ForStatement statement) {
|
||||||
|
super.visitForLoop(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitIfElse(IfStatement statement) {
|
||||||
|
super.visitIfElse(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitReturnStatement(ReturnStatement statement) {
|
||||||
|
super.visitReturnStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitSwitch(SwitchStatement statement) {
|
||||||
|
super.visitSwitch(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitSynchronizedStatement(SynchronizedStatement statement) {
|
||||||
|
super.visitSynchronizedStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitThrowStatement(ThrowStatement statement) {
|
||||||
|
super.visitThrowStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTryCatchFinally(TryCatchStatement statement) {
|
||||||
|
super.visitTryCatchFinally(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitWhileLoop(WhileStatement statement) {
|
||||||
|
super.visitWhileLoop(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEmptyStatement(EmptyStatement statement) {
|
||||||
|
super.visitEmptyStatement(statement);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(statement, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMethodCallExpression(MethodCallExpression call) {
|
||||||
|
super.visitMethodCallExpression(call);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(call, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitStaticMethodCallExpression(StaticMethodCallExpression call) {
|
||||||
|
super.visitStaticMethodCallExpression(call);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(call, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitConstructorCallExpression(ConstructorCallExpression call) {
|
||||||
|
super.visitConstructorCallExpression(call);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(call, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBinaryExpression(BinaryExpression expression) {
|
||||||
|
super.visitBinaryExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTernaryExpression(TernaryExpression expression) {
|
||||||
|
super.visitTernaryExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitShortTernaryExpression(ElvisOperatorExpression expression) {
|
||||||
|
super.visitShortTernaryExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitPostfixExpression(PostfixExpression expression) {
|
||||||
|
super.visitPostfixExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitPrefixExpression(PrefixExpression expression) {
|
||||||
|
super.visitPrefixExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBooleanExpression(BooleanExpression expression) {
|
||||||
|
super.visitBooleanExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitNotExpression(NotExpression expression) {
|
||||||
|
super.visitNotExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitClosureExpression(ClosureExpression expression) {
|
||||||
|
super.visitClosureExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitLambdaExpression(LambdaExpression expression) {
|
||||||
|
super.visitLambdaExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitTupleExpression(TupleExpression expression) {
|
||||||
|
super.visitTupleExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitListExpression(ListExpression expression) {
|
||||||
|
super.visitListExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitArrayExpression(ArrayExpression expression) {
|
||||||
|
super.visitArrayExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMapExpression(MapExpression expression) {
|
||||||
|
super.visitMapExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMapEntryExpression(MapEntryExpression expression) {
|
||||||
|
super.visitMapEntryExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitRangeExpression(RangeExpression expression) {
|
||||||
|
super.visitRangeExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitSpreadExpression(SpreadExpression expression) {
|
||||||
|
super.visitSpreadExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitSpreadMapExpression(SpreadMapExpression expression) {
|
||||||
|
super.visitSpreadMapExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMethodPointerExpression(MethodPointerExpression expression) {
|
||||||
|
super.visitMethodPointerExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitMethodReferenceExpression(MethodReferenceExpression expression) {
|
||||||
|
super.visitMethodReferenceExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitUnaryMinusExpression(UnaryMinusExpression expression) {
|
||||||
|
super.visitUnaryMinusExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitUnaryPlusExpression(UnaryPlusExpression expression) {
|
||||||
|
super.visitUnaryPlusExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBitwiseNegationExpression(BitwiseNegationExpression expression) {
|
||||||
|
super.visitBitwiseNegationExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitCastExpression(CastExpression expression) {
|
||||||
|
super.visitCastExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitConstantExpression(ConstantExpression expression) {
|
||||||
|
super.visitConstantExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitClassExpression(ClassExpression expression) {
|
||||||
|
super.visitClassExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitVariableExpression(VariableExpression expression) {
|
||||||
|
super.visitVariableExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitPropertyExpression(PropertyExpression expression) {
|
||||||
|
super.visitPropertyExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitAttributeExpression(AttributeExpression expression) {
|
||||||
|
super.visitAttributeExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitFieldExpression(FieldExpression expression) {
|
||||||
|
super.visitFieldExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitGStringExpression(GStringExpression expression) {
|
||||||
|
super.visitGStringExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitArgumentlistExpression(ArgumentListExpression expression) {
|
||||||
|
super.visitArgumentlistExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitClosureListExpression(ClosureListExpression expression) {
|
||||||
|
super.visitClosureListExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitBytecodeExpression(BytecodeExpression expression) {
|
||||||
|
super.visitBytecodeExpression(expression);
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(Statement statement) {
|
||||||
|
super.visit(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitEmptyExpression(EmptyExpression expression) {
|
||||||
|
this.positionSetter.setPositionOffsetInContainer(expression, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -18,6 +18,24 @@ public class SimplePositionSetter implements PositionSetter {
|
|||||||
this.set(target, start.line(), start.column(), end.line(), end.column());
|
this.set(target, start.line(), start.column(), end.line(), end.column());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPositionOffsetInContainer(ASTNode target, Node container) {
|
||||||
|
final SourcePosition containerStart = container.getTokenRange().getStartPosition();
|
||||||
|
final SourcePosition startPosition = new SourcePosition(
|
||||||
|
containerStart.line() + target.getLineNumber() - 1,
|
||||||
|
target.getLineNumber() == 1
|
||||||
|
? containerStart.column() + target.getColumnNumber() - 1
|
||||||
|
: target.getColumnNumber()
|
||||||
|
);
|
||||||
|
final SourcePosition endPosition = new SourcePosition(
|
||||||
|
containerStart.line() + target.getLastLineNumber() - 1,
|
||||||
|
target.getLastLineNumber() == 1
|
||||||
|
? containerStart.column() + target.getLastColumnNumber() - 1
|
||||||
|
: target.getLastColumnNumber()
|
||||||
|
);
|
||||||
|
this.set(target, startPosition, endPosition);
|
||||||
|
}
|
||||||
|
|
||||||
@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());
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
package groowt.view.component.web.transpile;
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
|
import groovy.lang.Tuple3;
|
||||||
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public interface TranspilerConfiguration {
|
public interface TranspilerConfiguration {
|
||||||
|
PositionSetter getPositionSetter();
|
||||||
BodyTranspiler getBodyTranspiler();
|
BodyTranspiler getBodyTranspiler();
|
||||||
AppendOrAddStatementFactory getAppendOrAddStatementFactory();
|
AppendOrAddStatementFactory getAppendOrAddStatementFactory();
|
||||||
|
Map<String, ClassNode> getImports();
|
||||||
|
Set<String> getStarImports();
|
||||||
|
Set<Tuple3<ClassNode, String, String>> getStaticImports();
|
||||||
|
Map<String, ClassNode> getStaticStarImports();
|
||||||
|
ClassNode getRenderContextImplementation();
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import groowt.view.component.ComponentTemplate;
|
|||||||
import groowt.view.component.compiler.ComponentTemplateCompileException;
|
import groowt.view.component.compiler.ComponentTemplateCompileException;
|
||||||
import groowt.view.component.context.ComponentContext;
|
import groowt.view.component.context.ComponentContext;
|
||||||
import groowt.view.component.runtime.ComponentWriter;
|
import groowt.view.component.runtime.ComponentWriter;
|
||||||
import groowt.view.component.web.WebViewComponent;
|
import groowt.view.component.web.runtime.DefaultWebViewRenderContext;
|
||||||
import groowt.view.component.web.runtime.WebViewComponentRenderContext;
|
import groowt.view.component.web.runtime.WebViewComponentRenderContext;
|
||||||
import groowt.view.component.web.util.SourcePosition;
|
import groowt.view.component.web.util.SourcePosition;
|
||||||
import org.codehaus.groovy.ast.*;
|
import org.codehaus.groovy.ast.*;
|
||||||
@ -23,8 +23,10 @@ public final class TranspilerUtil {
|
|||||||
public static final ClassNode COMPONENT_TEMPLATE = ClassHelper.make(ComponentTemplate.class);
|
public static final ClassNode COMPONENT_TEMPLATE = ClassHelper.make(ComponentTemplate.class);
|
||||||
public static final ClassNode COMPONENT_CONTEXT_TYPE = ClassHelper.make(ComponentContext.class);
|
public static final ClassNode COMPONENT_CONTEXT_TYPE = ClassHelper.make(ComponentContext.class);
|
||||||
public static final ClassNode COMPONENT_WRITER_TYPE = ClassHelper.make(ComponentWriter.class);
|
public static final ClassNode COMPONENT_WRITER_TYPE = ClassHelper.make(ComponentWriter.class);
|
||||||
public static final ClassNode WEB_VIEW_COMPONENT_RENDER_CONTEXT_TYPE = ClassHelper.make(WebViewComponentRenderContext.class);
|
public static final ClassNode WEB_VIEW_COMPONENT_RENDER_CONTEXT_TYPE =
|
||||||
public static final ClassNode WEB_VIEW_COMPONENT_TYPE = ClassHelper.make(WebViewComponent.class);
|
ClassHelper.make(WebViewComponentRenderContext.class);
|
||||||
|
public static final ClassNode DEFAULT_RENDER_CONTEXT_IMPLEMENTATION =
|
||||||
|
ClassHelper.make(DefaultWebViewRenderContext.class);
|
||||||
|
|
||||||
public static final String GROOWT_VIEW_COMPONENT_WEB = "groowt.view.component.web";
|
public static final String GROOWT_VIEW_COMPONENT_WEB = "groowt.view.component.web";
|
||||||
public static final String COMPONENT_CONTEXT_NAME = "componentContext";
|
public static final String COMPONENT_CONTEXT_NAME = "componentContext";
|
||||||
|
@ -11,13 +11,6 @@ import java.util.*;
|
|||||||
|
|
||||||
public class WebViewComponentModuleNode extends ModuleNode {
|
public class WebViewComponentModuleNode extends ModuleNode {
|
||||||
|
|
||||||
public static void copyTo(ModuleNode from, WebViewComponentModuleNode to) {
|
|
||||||
from.getImports().forEach(to::addImport);
|
|
||||||
from.getStarImports().forEach(to::addStarImport);
|
|
||||||
from.getStaticImports().forEach(to::addStaticImport);
|
|
||||||
from.getStaticStarImports().forEach(to::addStaticStarImport);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final List<ImportNode> imports = new ArrayList<>();
|
protected final List<ImportNode> imports = new ArrayList<>();
|
||||||
protected final List<ImportNode> starImports = new ArrayList<>();
|
protected final List<ImportNode> starImports = new ArrayList<>();
|
||||||
protected final Map<String, ImportNode> staticImports = new LinkedHashMap<>();
|
protected final Map<String, ImportNode> staticImports = new LinkedHashMap<>();
|
||||||
|
@ -3,7 +3,6 @@ package groowt.view.component.web.transpile.resolve;
|
|||||||
import groowt.util.fp.either.Either;
|
import groowt.util.fp.either.Either;
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
import org.codehaus.groovy.ast.ModuleNode;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -15,10 +14,9 @@ public class ClassLoaderComponentClassNodeResolver extends ModuleNodeComponentCl
|
|||||||
|
|
||||||
public ClassLoaderComponentClassNodeResolver(
|
public ClassLoaderComponentClassNodeResolver(
|
||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
WebViewComponentTemplateCompileUnit compileUnit,
|
||||||
ModuleNode moduleNode,
|
|
||||||
ClassLoader classLoader
|
ClassLoader classLoader
|
||||||
) {
|
) {
|
||||||
super(compileUnit, moduleNode);
|
super(compileUnit);
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,30 +5,36 @@ import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
|||||||
import org.codehaus.groovy.ast.ClassNode;
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
import org.codehaus.groovy.ast.ModuleNode;
|
import org.codehaus.groovy.ast.ModuleNode;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ModuleNodeComponentClassNodeResolver extends CachingComponentClassNodeResolver {
|
public class ModuleNodeComponentClassNodeResolver extends CachingComponentClassNodeResolver {
|
||||||
|
|
||||||
private final ModuleNode moduleNode;
|
private ModuleNode moduleNode;
|
||||||
|
|
||||||
public ModuleNodeComponentClassNodeResolver(
|
public ModuleNodeComponentClassNodeResolver(WebViewComponentTemplateCompileUnit compileUnit) {
|
||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
|
||||||
ModuleNode moduleNode
|
|
||||||
) {
|
|
||||||
super(compileUnit);
|
super(compileUnit);
|
||||||
this.moduleNode = moduleNode;
|
}
|
||||||
|
|
||||||
|
public ModuleNode getModuleNode() {
|
||||||
|
return Objects.requireNonNull(this.moduleNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setModuleNode(ModuleNode moduleNode) {
|
||||||
|
this.moduleNode = Objects.requireNonNull(moduleNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Either<ClassNodeResolveException, ClassNode> getClassForNameWithoutPackage(String nameWithoutPackage) {
|
public Either<ClassNodeResolveException, ClassNode> getClassForNameWithoutPackage(String nameWithoutPackage) {
|
||||||
return super.getClassForNameWithoutPackage(nameWithoutPackage).flatMapLeft(ignored -> {
|
return super.getClassForNameWithoutPackage(nameWithoutPackage).flatMapLeft(ignored -> {
|
||||||
// try regular imports first
|
// try regular imports first
|
||||||
final var importedClassNode = this.moduleNode.getImportType(nameWithoutPackage);
|
final var importedClassNode = this.getModuleNode().getImportType(nameWithoutPackage);
|
||||||
if (importedClassNode != null) {
|
if (importedClassNode != null) {
|
||||||
this.addClassNode(importedClassNode);
|
this.addClassNode(importedClassNode);
|
||||||
return Either.right(importedClassNode);
|
return Either.right(importedClassNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try star imports
|
// try star imports
|
||||||
final var starImports = this.moduleNode.getStarImports();
|
final var starImports = this.getModuleNode().getStarImports();
|
||||||
for (final var starImport : starImports) {
|
for (final var starImport : starImports) {
|
||||||
final var packageName = starImport.getPackageName();
|
final var packageName = starImport.getPackageName();
|
||||||
final String fqn;
|
final String fqn;
|
||||||
@ -44,7 +50,7 @@ public class ModuleNodeComponentClassNodeResolver extends CachingComponentClassN
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try pre-pending package and asking for fqn
|
// try pre-pending package and asking for fqn
|
||||||
final String moduleNodePackageName = this.moduleNode.getPackageName();
|
final String moduleNodePackageName = this.getModuleNode().getPackageName();
|
||||||
final String packageName;
|
final String packageName;
|
||||||
if (moduleNodePackageName != null) {
|
if (moduleNodePackageName != null) {
|
||||||
packageName = moduleNodePackageName;
|
packageName = moduleNodePackageName;
|
||||||
|
@ -57,6 +57,7 @@ public abstract class GroovyTranspilerTests {
|
|||||||
this.transpiler.transpile(
|
this.transpiler.transpile(
|
||||||
new DefaultComponentTemplateCompilerConfiguration(),
|
new DefaultComponentTemplateCompilerConfiguration(),
|
||||||
new DefaultWebViewComponentTemplateCompileUnit(
|
new DefaultWebViewComponentTemplateCompileUnit(
|
||||||
|
"<anonymous string source>",
|
||||||
AnonymousWebViewComponent.class,
|
AnonymousWebViewComponent.class,
|
||||||
new StringSource(source, null),
|
new StringSource(source, null),
|
||||||
"groowt.view.component.web.transpiler"
|
"groowt.view.component.web.transpiler"
|
||||||
|
@ -37,7 +37,7 @@ public abstract class AbstractWebViewComponent extends AbstractViewComponent imp
|
|||||||
|
|
||||||
public AbstractWebViewComponent(ComponentTemplateSource source) {
|
public AbstractWebViewComponent(ComponentTemplateSource source) {
|
||||||
this(selfClass -> new DefaultWebViewComponentTemplateCompileUnit(
|
this(selfClass -> new DefaultWebViewComponentTemplateCompileUnit(
|
||||||
selfClass, source, selfClass.getPackageName())
|
source.getDescriptiveName(), selfClass, source, selfClass.getPackageName())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,11 +24,12 @@ public class DefaultWebViewComponentTemplateCompileUnit extends AbstractComponen
|
|||||||
private final CompilationUnit groovyCompilationUnit = new CompilationUnit();
|
private final CompilationUnit groovyCompilationUnit = new CompilationUnit();
|
||||||
|
|
||||||
public DefaultWebViewComponentTemplateCompileUnit(
|
public DefaultWebViewComponentTemplateCompileUnit(
|
||||||
|
String descriptiveName,
|
||||||
Class<? extends ViewComponent> forClass,
|
Class<? extends ViewComponent> forClass,
|
||||||
ComponentTemplateSource source,
|
ComponentTemplateSource source,
|
||||||
String defaultPackageName
|
String defaultPackageName
|
||||||
) {
|
) {
|
||||||
super(forClass, source);
|
super(descriptiveName, forClass, source);
|
||||||
if (!defaultPackageName.isEmpty() && !defaultPackageName.endsWith(".")) {
|
if (!defaultPackageName.isEmpty() && !defaultPackageName.endsWith(".")) {
|
||||||
this.defaultPackageName = defaultPackageName + ".";
|
this.defaultPackageName = defaultPackageName + ".";
|
||||||
} else {
|
} else {
|
||||||
|
@ -26,6 +26,7 @@ public interface WebViewComponentTemplateCompiler
|
|||||||
default ComponentTemplateCompileResult compileAnonymous(ComponentTemplateSource source, String packageName)
|
default ComponentTemplateCompileResult compileAnonymous(ComponentTemplateSource source, String packageName)
|
||||||
throws ComponentTemplateCompileException {
|
throws ComponentTemplateCompileException {
|
||||||
return this.compile(new DefaultWebViewComponentTemplateCompileUnit(
|
return this.compile(new DefaultWebViewComponentTemplateCompileUnit(
|
||||||
|
source.getDescriptiveName(),
|
||||||
AnonymousWebViewComponent.class,
|
AnonymousWebViewComponent.class,
|
||||||
source,
|
source,
|
||||||
packageName
|
packageName
|
||||||
|
Loading…
Reference in New Issue
Block a user