Auto-imports working for both Groovyc configuration and independent API.

This commit is contained in:
Jesse Brault 2025-01-26 15:34:45 -06:00
parent bd4dee98fa
commit 45d188d064
18 changed files with 54 additions and 164 deletions

View File

@ -10,41 +10,8 @@ public abstract class CachingComponentTemplateCompiler<U extends ComponentTempla
private final Map<Class<? extends ViewComponent>, ComponentTemplateCompileResult> cache = new HashMap<>(); private final Map<Class<? extends ViewComponent>, ComponentTemplateCompileResult> cache = new HashMap<>();
// private ComponentTemplate instantiate(
// GroovyClassLoader groovyClassLoader,
// CompileResult compileResult
// ) {
// for (final var groovyClass : compileResult.otherClasses()) {
// // Try to find it. If we can't, we need to load it via the groovy loader
// try {
// Class.forName(groovyClass.getName(), true, groovyClassLoader);
// } catch (ClassNotFoundException ignored) {
// groovyClassLoader.defineClass(groovyClass.getName(), groovyClass.getBytes());
// } catch (LinkageError ignored) {
// // no-op, because we already have it
// }
// }
// final GroovyClass templateGroovyClass = compileResult.templateClass();
// Class<?> templateClass;
// // Try to find it. If we can't, we need to load it via the groovy loader
// try {
// templateClass = Class.forName(templateGroovyClass.getName(), true, groovyClassLoader);
// } catch (ClassNotFoundException ignored) {
// templateClass = groovyClassLoader.defineClass(
// templateGroovyClass.getName(),
// templateGroovyClass.getBytes()
// );
// }
// try {
// return (ComponentTemplate) templateClass.getConstructor().newInstance();
// } catch (Exception e) {
// throw new RuntimeException("Unable to instantiate ComponentTemplate " + templateClass.getName(), e);
// }
// }
@Override @Override
public final ComponentTemplateCompileResult compile(U compileUnit) public final ComponentTemplateCompileResult compile(U compileUnit) throws ComponentTemplateCompileException {
throws ComponentTemplateCompileException {
if (this.cache.containsKey(compileUnit.getForClass())) { if (this.cache.containsKey(compileUnit.getForClass())) {
return this.cache.get(compileUnit.getForClass()); return this.cache.get(compileUnit.getForClass());
} else { } else {

View File

@ -4,16 +4,9 @@ import groowt.view.component.ViewComponent;
import groowt.view.component.compiler.source.ComponentTemplateSource; import groowt.view.component.compiler.source.ComponentTemplateSource;
public interface ComponentTemplateCompileUnit { public interface ComponentTemplateCompileUnit {
String getDescriptiveName(); String getDescriptiveName();
Class<? extends ViewComponent> getForClass(); Class<? extends ViewComponent> getForClass();
String getDefaultPackageName(); String getDefaultPackageName();
ComponentTemplateSource getSource(); ComponentTemplateSource getSource();
ComponentTemplateCompileResult compile(ComponentTemplateCompilerConfiguration configuration) ComponentTemplateCompileResult compile() throws ComponentTemplateCompileException;
throws ComponentTemplateCompileException;
default ComponentTemplateCompileResult compile() throws ComponentTemplateCompileException {
return this.compile(new DefaultComponentTemplateCompilerConfiguration());
}
} }

View File

@ -1,11 +0,0 @@
package groowt.view.component.compiler;
import groovy.lang.GroovyClassLoader;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.CompilerConfiguration;
public interface ComponentTemplateCompilerConfiguration {
GroovyClassLoader getGroovyClassLoader();
CompilerConfiguration getGroovyCompilerConfiguration();
CompilePhase getToCompilePhase();
}

View File

@ -1,48 +0,0 @@
package groowt.view.component.compiler;
import groovy.lang.GroovyClassLoader;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.CompilerConfiguration;
import static java.util.Objects.requireNonNull;
public class DefaultComponentTemplateCompilerConfiguration implements ComponentTemplateCompilerConfiguration {
private GroovyClassLoader groovyClassLoader;
private CompilerConfiguration groovyCompilerConfiguration;
private CompilePhase toCompilePhase;
public DefaultComponentTemplateCompilerConfiguration() {
this.groovyClassLoader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader());
this.groovyCompilerConfiguration = new CompilerConfiguration();
this.toCompilePhase = CompilePhase.CLASS_GENERATION;
}
@Override
public GroovyClassLoader getGroovyClassLoader() {
return this.groovyClassLoader;
}
public void setGroovyClassLoader(GroovyClassLoader groovyClassLoader) {
this.groovyClassLoader = requireNonNull(groovyClassLoader);
}
@Override
public CompilerConfiguration getGroovyCompilerConfiguration() {
return this.groovyCompilerConfiguration;
}
public void setGroovyCompilerConfiguration(CompilerConfiguration groovyCompilerConfiguration) {
this.groovyCompilerConfiguration = requireNonNull(groovyCompilerConfiguration);
}
@Override
public CompilePhase getToCompilePhase() {
return this.toCompilePhase;
}
public void setToCompilePhase(CompilePhase toCompilePhase) {
this.toCompilePhase = requireNonNull(toCompilePhase);
}
}

View File

@ -201,7 +201,6 @@ tasks.register('uberJar', Jar) {
from sourceSets.main.output from sourceSets.main.output
from sourceSets.main.runtimeClasspath from sourceSets.main.runtimeClasspath
.filter(File.&exists) .filter(File.&exists)
.filter { !(it.name =~ /groovy.*.jar/) }
.collect { it.isDirectory() ? it : zipTree(it) } .collect { it.isDirectory() ? it : zipTree(it) }
duplicatesStrategy = DuplicatesStrategy.EXCLUDE duplicatesStrategy = DuplicatesStrategy.EXCLUDE
} }

View File

@ -11,7 +11,8 @@ if [ "$1" == "--debug" ]; then
"$@" "$@"
else else
gradle -q uberJar && \ gradle -q uberJar && \
groovyc -cp build/libs/web-view-components-uber-0.1.2.jar \ java -cp build/libs/web-view-components-uber-0.1.2.jar \
org.codehaus.groovy.tools.FileSystemCompiler \
--configscript src/main/resources/groowt/view/component/web/groovyc/groovycConfigurationScript.groovy \ --configscript src/main/resources/groowt/view/component/web/groovyc/groovycConfigurationScript.groovy \
-d groovyc-out \ -d groovyc-out \
"$@" "$@"

View File

@ -0,0 +1 @@
<Echo>Hello, World!</Echo>

View File

@ -4,7 +4,6 @@ import groowt.view.component.compiler.*;
import groowt.view.component.web.WebViewComponentBugError; import groowt.view.component.web.WebViewComponentBugError;
import groowt.view.component.web.ast.node.CompilationUnitNode; import groowt.view.component.web.ast.node.CompilationUnitNode;
import groowt.view.component.web.transpile.DefaultGroovyTranspiler; import groowt.view.component.web.transpile.DefaultGroovyTranspiler;
import org.antlr.v4.runtime.ParserRuleContext;
import org.codehaus.groovy.control.CompilationFailedException; import org.codehaus.groovy.control.CompilationFailedException;
import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.tools.GroovyClass; import org.codehaus.groovy.tools.GroovyClass;
@ -16,25 +15,12 @@ public class DefaultWebViewComponentTemplateCompiler
extends CachingComponentTemplateCompiler<WebViewComponentTemplateCompileUnit> extends CachingComponentTemplateCompiler<WebViewComponentTemplateCompileUnit>
implements WebViewComponentTemplateCompiler { implements WebViewComponentTemplateCompiler {
private final ComponentTemplateCompilerConfiguration configuration; private final WebViewComponentTemplateCompilerConfiguration configuration;
public DefaultWebViewComponentTemplateCompiler(ComponentTemplateCompilerConfiguration configuration) { public DefaultWebViewComponentTemplateCompiler(WebViewComponentTemplateCompilerConfiguration configuration) {
this.configuration = configuration; this.configuration = configuration;
} }
protected WebViewComponentTemplateCompileException getException(
WebViewComponentTemplateCompileUnit compileUnit,
ParserRuleContext parserRuleContext
) {
final var exception = new WebViewComponentTemplateCompileException(
compileUnit,
"Parser error: " + parserRuleContext.exception.getMessage(),
parserRuleContext.exception
);
exception.setParserRuleContext(parserRuleContext);
return exception;
}
@Override @Override
protected ComponentTemplateCompileResult doCompile(WebViewComponentTemplateCompileUnit compileUnit) protected ComponentTemplateCompileResult doCompile(WebViewComponentTemplateCompileUnit compileUnit)
throws ComponentTemplateCompileException { throws ComponentTemplateCompileException {
@ -49,22 +35,12 @@ public class DefaultWebViewComponentTemplateCompiler
: "AnonymousWebViewComponent" + System.nanoTime(); : "AnonymousWebViewComponent" + System.nanoTime();
final var templateClassSimpleName = ownerComponentName + "Template"; final var templateClassSimpleName = ownerComponentName + "Template";
final SourceUnit sourceUnit = transpiler.transpile( final SourceUnit sourceUnit = transpiler.transpile(compileUnit, cuNode, templateClassSimpleName);
this.configuration,
compileUnit,
cuNode,
templateClassSimpleName
);
compileUnit.getGroovyCompilationUnit().addSource(sourceUnit); compileUnit.getGroovyCompilationUnit().addSource(sourceUnit);
// set the groovy compile unit's class loader to the configuration's classloader.
compileUnit.getGroovyCompilationUnit().setClassLoader(
this.configuration.getGroovyClassLoader()
);
// compile groovy // compile groovy
try { try {
compileUnit.getGroovyCompilationUnit().compile(this.configuration.getToCompilePhase().getPhaseNumber()); compileUnit.getGroovyCompilationUnit().compile(this.configuration.getCompilePhase().getPhaseNumber());
} catch (CompilationFailedException compilationFailedException) { } catch (CompilationFailedException compilationFailedException) {
throw new WebViewComponentTemplateCompileException( throw new WebViewComponentTemplateCompileException(
compileUnit, compileUnit,

View File

@ -1,11 +1,9 @@
package groowt.view.component.web.compiler; package groowt.view.component.web.compiler;
import groowt.view.component.compiler.ComponentTemplateCompilerConfiguration;
public class DefaultWebViewComponentTemplateCompilerFactory implements WebViewComponentTemplateCompilerFactory { public class DefaultWebViewComponentTemplateCompilerFactory implements WebViewComponentTemplateCompilerFactory {
@Override @Override
public WebViewComponentTemplateCompiler create(ComponentTemplateCompilerConfiguration configuration) { public WebViewComponentTemplateCompiler create(WebViewComponentTemplateCompilerConfiguration configuration) {
return new DefaultWebViewComponentTemplateCompiler(configuration); return new DefaultWebViewComponentTemplateCompiler(configuration);
} }

View File

@ -1,7 +1,6 @@
package groowt.view.component.web.groovyc; package groowt.view.component.web.groovyc;
import groowt.view.component.compiler.ComponentTemplateCompileException; import groowt.view.component.compiler.ComponentTemplateCompileException;
import groowt.view.component.compiler.DefaultComponentTemplateCompilerConfiguration;
import groowt.view.component.compiler.source.ComponentTemplateSource; import groowt.view.component.compiler.source.ComponentTemplateSource;
import groowt.view.component.web.WebViewComponentBugError; import groowt.view.component.web.WebViewComponentBugError;
import groowt.view.component.web.ast.node.CompilationUnitNode; import groowt.view.component.web.ast.node.CompilationUnitNode;
@ -80,13 +79,12 @@ public class DelegatingWebViewComponentTemplateParserPlugin implements ParserPlu
} }
final var groovyTranspiler = new DefaultGroovyTranspiler(); final var groovyTranspiler = new DefaultGroovyTranspiler();
final String teplateClassSimpleName = sourceUnitFileName.substring(0, sourceUnitFileName.length() - 4); final String templateClassName = sourceUnitFileName.substring(0, sourceUnitFileName.length() - 4);
try { try {
final SourceUnit transpiledSourceUnit = groovyTranspiler.transpile( final SourceUnit transpiledSourceUnit = groovyTranspiler.transpile(
new DefaultComponentTemplateCompilerConfiguration(),
compileUnit, compileUnit,
cuNode, cuNode,
teplateClassSimpleName templateClassName
); );
return transpiledSourceUnit.getAST(); return transpiledSourceUnit.getAST();
} catch (ComponentTemplateCompileException e) { } catch (ComponentTemplateCompileException e) {

View File

@ -2,7 +2,6 @@ package groowt.view.component.web.transpile;
import groowt.view.component.compiler.ComponentTemplateCompileException; import groowt.view.component.compiler.ComponentTemplateCompileException;
import groowt.view.component.compiler.ComponentTemplateCompileUnit; import groowt.view.component.compiler.ComponentTemplateCompileUnit;
import groowt.view.component.compiler.ComponentTemplateCompilerConfiguration;
import groowt.view.component.web.ast.node.BodyNode; import groowt.view.component.web.ast.node.BodyNode;
import groowt.view.component.web.ast.node.CompilationUnitNode; import groowt.view.component.web.ast.node.CompilationUnitNode;
import groowt.view.component.web.ast.node.PreambleNode; import groowt.view.component.web.ast.node.PreambleNode;
@ -49,18 +48,13 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
return moduleNode; return moduleNode;
} }
protected ClassNode initMainClassNode( protected ClassNode initMainClassNode(ComponentTemplateCompileUnit compileUnit, String templateClassName) {
ComponentTemplateCompileUnit compileUnit,
String templateClassName,
WebViewComponentModuleNode moduleNode
) {
final ClassNode mainClassNode = new ClassNode( final ClassNode mainClassNode = new ClassNode(
compileUnit.getDefaultPackageName() + templateClassName, compileUnit.getDefaultPackageName() + templateClassName,
ACC_PUBLIC, ACC_PUBLIC,
ClassHelper.OBJECT_TYPE ClassHelper.OBJECT_TYPE
); );
mainClassNode.addInterface(TranspilerUtil.COMPONENT_TEMPLATE); mainClassNode.addInterface(TranspilerUtil.COMPONENT_TEMPLATE);
moduleNode.addClass(mainClassNode);
return mainClassNode; return mainClassNode;
} }
@ -202,7 +196,6 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
@Override @Override
public WebViewComponentSourceUnit transpile( public WebViewComponentSourceUnit transpile(
ComponentTemplateCompilerConfiguration compilerConfiguration,
WebViewComponentTemplateCompileUnit compileUnit, WebViewComponentTemplateCompileUnit compileUnit,
CompilationUnitNode compilationUnitNode, CompilationUnitNode compilationUnitNode,
String templateClassSimpleName String templateClassSimpleName
@ -212,13 +205,13 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
final PositionSetter positionSetter = transpilerConfiguration.getPositionSetter(); final PositionSetter positionSetter = transpilerConfiguration.getPositionSetter();
// prepare sourceUnit // prepare sourceUnit
final CompilerConfiguration groovyCompilerConfiguration = final CompilerConfiguration groovyCompilerConfiguration = compileUnit.getGroovyCompilationUnit()
compilerConfiguration.getGroovyCompilerConfiguration(); .getConfiguration();
final WebViewComponentSourceUnit sourceUnit = new WebViewComponentSourceUnit( final WebViewComponentSourceUnit sourceUnit = new WebViewComponentSourceUnit(
compileUnit.getDescriptiveName(), compileUnit.getDescriptiveName(),
compileUnit.getGroovyReaderSource(), compileUnit.getGroovyReaderSource(),
groovyCompilerConfiguration, groovyCompilerConfiguration,
compilerConfiguration.getGroovyClassLoader(), compileUnit.getGroovyCompilationUnit().getClassLoader(),
new ErrorCollector(groovyCompilerConfiguration) new ErrorCollector(groovyCompilerConfiguration)
); );
@ -228,7 +221,7 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
); );
// prepare mainClassNode // prepare mainClassNode
final ClassNode mainClassNode = this.initMainClassNode(compileUnit, templateClassSimpleName, moduleNode); final ClassNode mainClassNode = this.initMainClassNode(compileUnit, templateClassSimpleName);
// handle preamble // handle preamble
final PreambleNode preambleNode = compilationUnitNode.getPreambleNode(); final PreambleNode preambleNode = compilationUnitNode.getPreambleNode();
@ -236,6 +229,9 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
this.handlePreamble(templateClassSimpleName, preambleNode, mainClassNode, moduleNode, positionSetter); this.handlePreamble(templateClassSimpleName, preambleNode, mainClassNode, moduleNode, positionSetter);
} }
// Moved here so that moduleNode#getMainClassName reflects fqn of mainClassName
moduleNode.addClass(mainClassNode);
// getRenderer method and render closure // getRenderer method and render closure
// first, getRenderer 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);

View File

@ -1,14 +1,12 @@
package groowt.view.component.web.transpile; package groowt.view.component.web.transpile;
import groowt.view.component.compiler.ComponentTemplateCompileException; import groowt.view.component.compiler.ComponentTemplateCompileException;
import groowt.view.component.compiler.ComponentTemplateCompilerConfiguration;
import groowt.view.component.web.ast.node.CompilationUnitNode; import groowt.view.component.web.ast.node.CompilationUnitNode;
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit; import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
public interface GroovyTranspiler { public interface GroovyTranspiler {
WebViewComponentSourceUnit transpile( WebViewComponentSourceUnit transpile(
ComponentTemplateCompilerConfiguration compilerConfiguration,
WebViewComponentTemplateCompileUnit compileUnit, WebViewComponentTemplateCompileUnit compileUnit,
CompilationUnitNode compilationUnitNode, CompilationUnitNode compilationUnitNode,
String templateClassSimpleName String templateClassSimpleName

View File

@ -1,5 +1,16 @@
package groowt.view.component.web.groovyc package groowt.view.component.web.groovyc
import org.codehaus.groovy.control.CompilerConfiguration import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.customizers.ImportCustomizer
(configuration as CompilerConfiguration).tap {
pluginFactory = new WebViewComponentParserPluginFactory()
addCompilationCustomizers(new ImportCustomizer().tap {
addStarImports(
"groowt.view.component.web.lib",
"groowt.view.component.web.runtime",
"groowt.view.component.runtime"
)
})
}
(configuration as CompilerConfiguration).pluginFactory = new WebViewComponentParserPluginFactory()

View File

@ -2,7 +2,6 @@ package groowt.view.component.web.transpiler;
import groovy.lang.Tuple2; import groovy.lang.Tuple2;
import groowt.view.component.compiler.ComponentTemplateCompileException; import groowt.view.component.compiler.ComponentTemplateCompileException;
import groowt.view.component.compiler.DefaultComponentTemplateCompilerConfiguration;
import groowt.view.component.compiler.source.StringSource; import groowt.view.component.compiler.source.StringSource;
import groowt.view.component.web.BaseWebViewComponent; import groowt.view.component.web.BaseWebViewComponent;
import groowt.view.component.web.antlr.ParserUtil; import groowt.view.component.web.antlr.ParserUtil;
@ -55,7 +54,6 @@ public abstract class GroovyTranspilerTests {
final var cuNode = astBuilder.buildCompilationUnit(parseResult.getCompilationUnitContext()); final var cuNode = astBuilder.buildCompilationUnit(parseResult.getCompilationUnitContext());
try { try {
this.transpiler.transpile( this.transpiler.transpile(
new DefaultComponentTemplateCompilerConfiguration(),
new DefaultWebViewComponentTemplateCompileUnit( new DefaultWebViewComponentTemplateCompileUnit(
"<anonymous string source>", "<anonymous string source>",
AnonymousWebViewComponent.class, AnonymousWebViewComponent.class,

View File

@ -4,7 +4,6 @@ import groowt.view.component.ViewComponent;
import groowt.view.component.compiler.AbstractComponentTemplateCompileUnit; import groowt.view.component.compiler.AbstractComponentTemplateCompileUnit;
import groowt.view.component.compiler.ComponentTemplateCompileException; import groowt.view.component.compiler.ComponentTemplateCompileException;
import groowt.view.component.compiler.ComponentTemplateCompileResult; import groowt.view.component.compiler.ComponentTemplateCompileResult;
import groowt.view.component.compiler.ComponentTemplateCompilerConfiguration;
import groowt.view.component.compiler.source.ComponentTemplateSource; import groowt.view.component.compiler.source.ComponentTemplateSource;
import groowt.view.component.compiler.source.FileSource; import groowt.view.component.compiler.source.FileSource;
import groowt.view.component.compiler.source.URISource; import groowt.view.component.compiler.source.URISource;
@ -68,9 +67,8 @@ public class DefaultWebViewComponentTemplateCompileUnit extends AbstractComponen
} }
@Override @Override
public ComponentTemplateCompileResult compile(ComponentTemplateCompilerConfiguration configuration) public ComponentTemplateCompileResult compile() throws ComponentTemplateCompileException {
throws ComponentTemplateCompileException { final WebViewComponentTemplateCompiler compiler = WebViewComponentTemplateCompiler.get();
final WebViewComponentTemplateCompiler compiler = WebViewComponentTemplateCompiler.get(configuration);
return compiler.compile(this); return compiler.compile(this);
} }

View File

@ -9,10 +9,10 @@ public interface WebViewComponentTemplateCompiler
extends ComponentTemplateCompiler<WebViewComponentTemplateCompileUnit> { extends ComponentTemplateCompiler<WebViewComponentTemplateCompileUnit> {
static WebViewComponentTemplateCompiler get() { static WebViewComponentTemplateCompiler get() {
return get(new DefaultComponentTemplateCompilerConfiguration()); return get(new WebViewComponentTemplateCompilerConfiguration());
} }
static WebViewComponentTemplateCompiler get(ComponentTemplateCompilerConfiguration configuration) { static WebViewComponentTemplateCompiler get(WebViewComponentTemplateCompilerConfiguration configuration) {
final ServiceLoader<WebViewComponentTemplateCompilerFactory> factoryServiceLoader = final ServiceLoader<WebViewComponentTemplateCompilerFactory> factoryServiceLoader =
ServiceLoader.load(WebViewComponentTemplateCompilerFactory.class); ServiceLoader.load(WebViewComponentTemplateCompilerFactory.class);
final var factory = factoryServiceLoader.findFirst() final var factory = factoryServiceLoader.findFirst()

View File

@ -0,0 +1,17 @@
package groowt.view.component.web.compiler;
import org.codehaus.groovy.control.CompilePhase;
public class WebViewComponentTemplateCompilerConfiguration {
private CompilePhase compilePhase = CompilePhase.CLASS_GENERATION;
public CompilePhase getCompilePhase() {
return this.compilePhase;
}
public void setCompilePhase(CompilePhase compilePhase) {
this.compilePhase = compilePhase;
}
}

View File

@ -1,7 +1,5 @@
package groowt.view.component.web.compiler; package groowt.view.component.web.compiler;
import groowt.view.component.compiler.ComponentTemplateCompilerConfiguration;
public interface WebViewComponentTemplateCompilerFactory { public interface WebViewComponentTemplateCompilerFactory {
WebViewComponentTemplateCompiler create(ComponentTemplateCompilerConfiguration configuration); WebViewComponentTemplateCompiler create(WebViewComponentTemplateCompilerConfiguration configuration);
} }