Groovyc can compile all sketching wvc.

This commit is contained in:
JesseBrault0709 2024-05-17 13:14:44 +02:00
parent 63720693a3
commit cdc96ffdff
16 changed files with 103 additions and 30 deletions

View File

@ -1 +1,2 @@
bin bin
groovyc-out

View File

@ -137,6 +137,7 @@ tasks.register('uberJar', Jar) {
group = 'build' group = 'build'
archiveBaseName = 'web-views-uber' archiveBaseName = 'web-views-uber'
from sourceSets.main.output from sourceSets.main.output
from sourceSets.sketching.output
from sourceSets.main.runtimeClasspath.filter(File.&exists).collect { from sourceSets.main.runtimeClasspath.filter(File.&exists).collect {
it.isDirectory() ? it : zipTree(it) it.isDirectory() ? it : zipTree(it)
} }

View File

@ -1,17 +1,18 @@
#!/usr/bin/env bash #!/usr/bin/env bash
if [ "$1" == "--debug" ]; then if [ "$1" == "--debug" ]; then
shift
gradle -q uberJar && \ gradle -q uberJar && \
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:8192 \ java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:8192 \
-cp build/libs/web-views-uber-0.1.0.jar \ -cp build/libs/web-views-uber-0.1.0.jar \
org.codehaus.groovy.tools.FileSystemCompiler \ org.codehaus.groovy.tools.FileSystemCompiler \
--configscript src/main/resources/groowt/view/web/groovyc/GroovycConfigurationScript.groovy \ --configscript src/main/resources/groowt/view/web/groovyc/GroovycConfigurationScript.groovy \
-d groovyc-out \ -d groovyc-out \
sketching/helloTarget.wvc "$@"
else else
gradle -q uberJar && \ gradle -q uberJar && \
groovyc -cp build/libs/web-views-uber-0.1.0.jar \ groovyc -cp build/libs/web-views-uber-0.1.0.jar \
--configscript src/main/resources/groowt/view/web/groovyc/GroovycConfigurationScript.groovy \ --configscript src/main/resources/groowt/view/web/groovyc/GroovycConfigurationScript.groovy \
-d groovyc-out \ -d groovyc-out \
sketching/helloTarget.wvc "$@"
fi fi

View File

@ -1,4 +1,4 @@
--- ---
import groowt.view.web.lib.Echo package sketching
--- ---
<Echo><p>$cliGreeting</p></Echo> <Echo><p>$cliGreeting</p></Echo>

View File

@ -1,9 +1,13 @@
--- ---
package sketching
import groovy.transform.Field
void consume(out) { void consume(out) {
out << 'World' out << 'World'
} }
@groovy.transform.Field @Field
String greeting = 'Hello' String greeting = 'Hello'
--- ---
$greeting, ${consume(it)}! $greeting, ${consume(it)}!

View File

@ -1,4 +1,6 @@
--- ---
package sketching
class Greeter extends BaseWebViewComponent { class Greeter extends BaseWebViewComponent {
String target String target

View File

@ -0,0 +1,6 @@
---
package groowt.view.web.sketching
---
<>
<Greeters.Simple greeting='Hello, one!' />&nbsp;<Greeters.Simple greeting='Hello, two!' />
</>

View File

@ -0,0 +1,4 @@
---
package sketching
---
${new Helper().help('My God, it works')}

View File

@ -1,3 +0,0 @@
<>
<Greeter greeting='Hello, one!' />&nbsp;<Greeter greeting='Hello, two!' />
</>

View File

@ -16,7 +16,7 @@ public class MultipleWebViewComponentCompileErrorsException extends ComponentTem
ComponentTemplateCompileUnit compileUnit, ComponentTemplateCompileUnit compileUnit,
List<? extends Throwable> errors List<? extends Throwable> errors
) { ) {
super(compileUnit, "There were multiple errors during compilation."); super(compileUnit, "There were multiple errors during compilation/transpilation.");
this.errors.addAll(errors); this.errors.addAll(errors);
} }

View File

@ -28,7 +28,11 @@ public class WebViewComponentTemplateCompileUnit extends AbstractComponentTempla
String defaultPackageName String defaultPackageName
) { ) {
super(forClass, source); super(forClass, source);
this.defaultPackageName = defaultPackageName; if (!defaultPackageName.isEmpty() && !defaultPackageName.endsWith(".")) {
this.defaultPackageName = defaultPackageName + ".";
} else {
this.defaultPackageName = defaultPackageName;
}
} }
@Override @Override

View File

@ -3,6 +3,7 @@ package groowt.view.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.DefaultComponentTemplateCompilerConfiguration;
import groowt.view.component.compiler.source.ComponentTemplateSource; import groowt.view.component.compiler.source.ComponentTemplateSource;
import groowt.view.web.WebViewComponentBugError;
import groowt.view.web.analysis.MismatchedComponentTypeAnalysis; import groowt.view.web.analysis.MismatchedComponentTypeAnalysis;
import groowt.view.web.analysis.MismatchedComponentTypeError; import groowt.view.web.analysis.MismatchedComponentTypeError;
import groowt.view.web.antlr.*; import groowt.view.web.antlr.*;
@ -26,13 +27,18 @@ import org.codehaus.groovy.control.ParserPlugin;
import org.codehaus.groovy.control.SourceUnit; import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.syntax.ParserException; import org.codehaus.groovy.syntax.ParserException;
import org.codehaus.groovy.syntax.Reduction; import org.codehaus.groovy.syntax.Reduction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.List; import java.util.List;
public class DelegatingWvcParserPlugin implements ParserPlugin { public class DelegatingWvcParserPlugin implements ParserPlugin {
private static final Logger logger = LoggerFactory.getLogger(DelegatingWvcParserPlugin.class);
private final Antlr4ParserPlugin groovyParserPlugin; private final Antlr4ParserPlugin groovyParserPlugin;
public DelegatingWvcParserPlugin(Antlr4ParserPlugin groovyParserPlugin) { public DelegatingWvcParserPlugin(Antlr4ParserPlugin groovyParserPlugin) {
@ -98,23 +104,41 @@ public class DelegatingWvcParserPlugin implements ParserPlugin {
} }
protected ParserException translateException(ComponentTemplateCompileException e) { protected ParserException translateException(ComponentTemplateCompileException e) {
final var actual = (WebViewComponentTemplateCompileException) e; if (e instanceof WebViewComponentTemplateCompileException single) {
final SourcePosition sourcePosition = actual.getSourcePosition(); final SourcePosition sourcePosition = single.getSourcePosition();
if (sourcePosition != null) { if (sourcePosition != null) {
return new ParserException(e.getMessage(), e, sourcePosition.line(), sourcePosition.column()); return new ParserException(e.getMessage(), e, sourcePosition.line(), sourcePosition.column());
} else {
return new ParserException(e.getMessage(), e, 1, 1);
}
} else if (e instanceof MultipleWebViewComponentCompileErrorsException multiple) {
return new ParserException("There were multiple errors during compilation/transpilation.", multiple, 1, 1);
} else { } else {
return new ParserException(e.getMessage(), e, -1, -1); throw new WebViewComponentBugError(
"Cannot determine the type of non-WebViewComponent compile exception: "
+ e.getClass().getName()
);
} }
} }
protected void logException(WebViewComponentTemplateCompileException e) {
logger.error(e.getMessage());
}
protected void logException(MultipleWebViewComponentCompileErrorsException e) {
logger.error(e.getMessage());
}
@Override @Override
public ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException { public ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException {
final String sourceUnitName = sourceUnit.getName(); final String sourceUnitFullName = sourceUnit.getName();
if (sourceUnitName.endsWith(".wvc")) { final int lastSlashIndex = sourceUnitFullName.lastIndexOf(File.separator);
final String sourceUnitFileName = sourceUnitFullName.substring(lastSlashIndex + 1);
if (sourceUnitFileName.endsWith(".wvc")) {
final var compileUnit = new WebViewComponentTemplateCompileUnit( final var compileUnit = new WebViewComponentTemplateCompileUnit(
AnonymousWebViewComponent.class, AnonymousWebViewComponent.class,
ComponentTemplateSource.of(sourceUnit.getSource().getURI()), ComponentTemplateSource.of(sourceUnit.getSource().getURI()),
"groowt.view.web.groovyc" "" // default package
); );
final CompilationUnitParseResult parseResult; final CompilationUnitParseResult parseResult;
@ -134,10 +158,12 @@ public class DelegatingWvcParserPlugin implements ParserPlugin {
final var errorExceptions = parseErrors.getAll().stream() final var errorExceptions = parseErrors.getAll().stream()
.map(errorNode -> getException(compileUnit, errorNode)) .map(errorNode -> getException(compileUnit, errorNode))
.toList(); .toList();
throw this.translateException(new MultipleWebViewComponentCompileErrorsException( final var multiple = new MultipleWebViewComponentCompileErrorsException(
compileUnit, compileUnit,
errorExceptions errorExceptions
)); );
this.logException(multiple);
throw this.translateException(multiple);
} }
} }
@ -152,10 +178,12 @@ public class DelegatingWvcParserPlugin implements ParserPlugin {
final var errorExceptions = mismatchedComponentTypeErrors.stream() final var errorExceptions = mismatchedComponentTypeErrors.stream()
.map(error -> getException(compileUnit, error)) .map(error -> getException(compileUnit, error))
.toList(); .toList();
throw this.translateException(new MultipleWebViewComponentCompileErrorsException( final var multiple = new MultipleWebViewComponentCompileErrorsException(
compileUnit, compileUnit,
errorExceptions errorExceptions
)); );
this.logException(multiple);
throw this.translateException(multiple);
} }
} }
@ -165,15 +193,26 @@ public class DelegatingWvcParserPlugin implements ParserPlugin {
final var cuNode = (CompilationUnitNode) astBuilder.build(parseResult.getCompilationUnitContext()); final var cuNode = (CompilationUnitNode) astBuilder.build(parseResult.getCompilationUnitContext());
final var groovyTranspiler = new DefaultGroovyTranspiler(); final var groovyTranspiler = new DefaultGroovyTranspiler();
final String nameWithoutExtension = 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,
sourceUnitName.substring(0, sourceUnitName.length() - 4) nameWithoutExtension
); );
return transpiledSourceUnit.getAST(); return transpiledSourceUnit.getAST();
} catch (ComponentTemplateCompileException e) { } catch (ComponentTemplateCompileException e) {
if (e instanceof WebViewComponentTemplateCompileException single) {
this.logException(single);
} else if (e instanceof MultipleWebViewComponentCompileErrorsException multiple) {
this.logException(multiple);
} else {
throw new WebViewComponentBugError(
"Could not determine type of non-WebViewComponent compile exception: "
+ e.getClass().getName()
);
}
throw this.translateException(e); throw this.translateException(e);
} }
} else { } else {

View File

@ -87,6 +87,7 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
classNode.getMixins() classNode.getMixins()
); );
icn.setDeclaringClass(mainClassNode); icn.setDeclaringClass(mainClassNode);
result.add(icn);
} }
} }
return result; return result;
@ -178,7 +179,10 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
final var moduleNode = new WebViewComponentModuleNode(sourceUnit); final var moduleNode = new WebViewComponentModuleNode(sourceUnit);
sourceUnit.setModuleNode(moduleNode); sourceUnit.setModuleNode(moduleNode);
moduleNode.setPackageName(compileUnit.getDefaultPackageName()); final String defaultPackageName = compileUnit.getDefaultPackageName();
if (!defaultPackageName.trim().isEmpty()) {
moduleNode.setPackageName(defaultPackageName);
}
moduleNode.addStarImport(GROOWT_VIEW_WEB + ".lib"); moduleNode.addStarImport(GROOWT_VIEW_WEB + ".lib");
moduleNode.addImport(COMPONENT_TEMPLATE.getNameWithoutPackage(), COMPONENT_TEMPLATE); moduleNode.addImport(COMPONENT_TEMPLATE.getNameWithoutPackage(), COMPONENT_TEMPLATE);
@ -187,7 +191,7 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
moduleNode.addStarImport(GROOWT_VIEW_WEB + ".runtime"); moduleNode.addStarImport(GROOWT_VIEW_WEB + ".runtime");
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
); );

View File

@ -32,7 +32,7 @@ public class ModuleNodeComponentClassNodeResolver extends CachingComponentClassN
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;
if (packageName.endsWith(".")) { if (!packageName.equals(".") && packageName.endsWith(".")) {
fqn = packageName + nameWithoutPackage; fqn = packageName + nameWithoutPackage;
} else { } else {
fqn = packageName + "." + nameWithoutPackage; fqn = packageName + "." + nameWithoutPackage;
@ -44,13 +44,23 @@ public class ModuleNodeComponentClassNodeResolver extends CachingComponentClassN
} }
// try pre-pending package and asking for fqn // try pre-pending package and asking for fqn
final var packageName = this.moduleNode.getPackageName(); final String moduleNodePackageName = this.moduleNode.getPackageName();
final String fqn; final String packageName;
if (packageName.endsWith(".")) { if (moduleNodePackageName != null) {
fqn = this.moduleNode.getPackageName() + nameWithoutPackage; packageName = moduleNodePackageName;
} else { } else {
fqn = this.moduleNode.getPackageName() + "." + nameWithoutPackage; packageName = "";
} }
final String fqn;
if (packageName.equals(".") || packageName.isEmpty()) {
fqn = nameWithoutPackage;
} else if (packageName.endsWith(".")) {
fqn = packageName + nameWithoutPackage;
} else {
fqn = packageName + "." + nameWithoutPackage;
}
final var withPackage = this.getClassForFqn(fqn); final var withPackage = this.getClassForFqn(fqn);
if (withPackage.isRight()) { if (withPackage.isRight()) {
return withPackage; return withPackage;