Compare commits
38 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3202e51d7f | ||
![]() |
abc4b971d6 | ||
![]() |
eb77f0a3d7 | ||
![]() |
71f1547c6a | ||
![]() |
1b63f2807c | ||
![]() |
0c4b42e0ee | ||
![]() |
eb444dda02 | ||
![]() |
dcc1d6e53e | ||
![]() |
1d0de99e1d | ||
![]() |
b4ef7d7da3 | ||
![]() |
21e933d681 | ||
![]() |
7105686f80 | ||
![]() |
0390d15fce | ||
![]() |
9495849dc9 | ||
![]() |
f6071909b6 | ||
![]() |
2b3cd3120c | ||
![]() |
369dc51779 | ||
![]() |
148ced050b | ||
![]() |
589bbca889 | ||
![]() |
2b935da385 | ||
![]() |
7a28b0530d | ||
![]() |
45d188d064 | ||
![]() |
bd4dee98fa | ||
![]() |
1a528465f9 | ||
![]() |
5ce934b3fe | ||
![]() |
74c5698d1b | ||
![]() |
525932668f | ||
![]() |
04866b4d3a | ||
![]() |
8bc3d9d793 | ||
![]() |
55adf223d2 | ||
![]() |
22b929225f | ||
![]() |
49ead642c4 | ||
![]() |
b55cea174d | ||
![]() |
c709932af2 | ||
![]() |
389b0d072c | ||
![]() |
0076ae6627 | ||
![]() |
301f00e9a4 | ||
![]() |
3af495d458 |
36
.gitea/workflows/gitea-ci.yml
Normal file
36
.gitea/workflows/gitea-ci.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: Groowt Check and Publish
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
jobs:
|
||||||
|
ci:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout the code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup Java.
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 21
|
||||||
|
- name: Check libraries
|
||||||
|
run: ./gradlew check
|
||||||
|
- name: Publish to git.jessebrault.com
|
||||||
|
run: >
|
||||||
|
./gradlew publishViewsPublicationToGiteaRepository &&
|
||||||
|
./gradlew publishViewComponentsPublicationToGiteaRepository &&
|
||||||
|
./gradlew publishWebViewComponentsPublicationToGiteaRepository &&
|
||||||
|
./gradlew publishWebViewComponentsCompilerPublicationToGiteaRepository &&
|
||||||
|
./gradlew publishDiPublicationToGiteaRepository &&
|
||||||
|
./gradlew publishExtensiblePublicationToGiteaRepository &&
|
||||||
|
./gradlew publishFpPublicationToGiteaRepository
|
||||||
|
- name: Publish to archiva.jessebrault.com
|
||||||
|
run: >
|
||||||
|
./gradlew publishViewsPublicationToJbArchivaInternalRepository &&
|
||||||
|
./gradlew publishViewComponentsPublicationToJbArchivaInternalRepository &&
|
||||||
|
./gradlew publishWebViewComponentsPublicationToJbArchivaInternalRepository &&
|
||||||
|
./gradlew publishWebViewComponentsCompilerPublicationToJbArchivaInternalRepository &&
|
||||||
|
./gradlew publishDiPublicationToJbArchivaInternalRepository &&
|
||||||
|
./gradlew publishExtensiblePublicationToJbArchivaInternalRepository &&
|
||||||
|
./gradlew publishFpPublicationToJbArchivaInternalRepository
|
36
TODO.md
36
TODO.md
@ -1,5 +1,17 @@
|
|||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
## 0.3.0
|
||||||
|
- [ ] Explore slightly different syntax for web view components to allow better InteliJ and Groovy integration.
|
||||||
|
For example:
|
||||||
|
```
|
||||||
|
@package mysite
|
||||||
|
@import mysite.Component
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<Component componentAttrWithParams={ key, value -> <Echo>$key: $value</Echo>} />
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
## 0.2.0
|
## 0.2.0
|
||||||
- [ ] Separate out the following into separate, non-Groowt projects with their own repositories and the com.jessebrault
|
- [ ] Separate out the following into separate, non-Groowt projects with their own repositories and the com.jessebrault
|
||||||
namespace:
|
namespace:
|
||||||
@ -8,9 +20,31 @@
|
|||||||
- di
|
- di
|
||||||
- extensible
|
- extensible
|
||||||
- fp
|
- fp
|
||||||
|
- [x] Remove cli, groowt-all, groowt-gradle, groowt-gradle-model.
|
||||||
|
- [ ] Get rid of wvc compiler dependency on fp, di.
|
||||||
|
- [ ] Remove as much cruft as possible from web-view-components-compiler, etc.
|
||||||
|
- [ ] Use new namespaces (i.e., packages) the individual projects:
|
||||||
|
- `com.jessebrault.groowt`: for views
|
||||||
|
- `com.jessebrault.groowt.component`: for view-components
|
||||||
|
- `com.jessebrault.groowt.web`: for web-view-components and web-view-components-compiler
|
||||||
|
|
||||||
|
## 0.1.3
|
||||||
|
- [ ] ~~refactor tools/gradle start scripts to use dist instead of custom bin script~~
|
||||||
|
- [ ] ~~have custom bin/* scripts which point to dist(s) for convenience~~
|
||||||
|
- [x] di bug: @Singleton toSelf() causes stack overflow
|
||||||
|
- [x] wvcc bug: Nested static view classes are not seen by compiler
|
||||||
|
- This required tweaking how the configurations are passed around. Ultimately, we should strive for less complexity
|
||||||
|
in this regard.
|
||||||
|
- [x] `OutletContainer` trait or interface for components which can contain an `<Outlet />` child.
|
||||||
|
- [x] `Context` should have methods for simply finding an ancestor of a certain type without the need for a predicate.
|
||||||
|
|
||||||
## 0.1.2
|
## 0.1.2
|
||||||
- [ ] di bug: @Singleton toSelf() causes stack overflow
|
- [x] `Outlet` component for rendering children like so:
|
||||||
|
```
|
||||||
|
<Outlet children={children} />
|
||||||
|
```
|
||||||
|
- [x] `Render` component
|
||||||
|
- [x] `data-` attributes need to function correctly (really any attribute with hyphen).
|
||||||
|
|
||||||
## 0.1.1
|
## 0.1.1
|
||||||
- [x] `Switch` and `Case` components
|
- [x] `Switch` and `Case` components
|
||||||
|
@ -4,7 +4,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = 'groowt'
|
group = 'groowt'
|
||||||
version = '0.1.1'
|
version = '0.1.3'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -4,6 +4,8 @@ import com.jessebrault.jbarchiva.JbArchivaPlugin
|
|||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
|
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
|
||||||
|
import org.gradle.api.credentials.HttpHeaderCredentials
|
||||||
|
import org.gradle.authentication.http.HttpHeaderAuthentication
|
||||||
|
|
||||||
class GroowtPublishPlugin implements Plugin<Project> {
|
class GroowtPublishPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
@ -11,6 +13,25 @@ class GroowtPublishPlugin implements Plugin<Project> {
|
|||||||
void apply(Project project) {
|
void apply(Project project) {
|
||||||
project.plugins.apply(MavenPublishPlugin)
|
project.plugins.apply(MavenPublishPlugin)
|
||||||
project.plugins.apply(JbArchivaPlugin)
|
project.plugins.apply(JbArchivaPlugin)
|
||||||
|
project.with {
|
||||||
|
publishing {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = "Gitea"
|
||||||
|
url = uri("https://git.jessebrault.com/api/packages/jessebrault/maven")
|
||||||
|
|
||||||
|
credentials(HttpHeaderCredentials) {
|
||||||
|
name = "Authorization"
|
||||||
|
value = "token ${System.getenv("GITEA_ACCESS_TOKEN")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
authentication {
|
||||||
|
header(HttpHeaderAuthentication)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'groowt-conventions'
|
|
||||||
id 'groowt-logging'
|
|
||||||
id 'groowt-publish'
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
maven {
|
|
||||||
url 'https://repo.gradle.org/gradle/libs-releases'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation libs.gradle.tooling
|
|
||||||
implementation libs.picocli
|
|
||||||
implementation project(':groowt-gradle-model')
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('jar', Jar) {
|
|
||||||
manifest {
|
|
||||||
attributes('Main-Class': 'groowt.cli.GroowtCli')
|
|
||||||
}
|
|
||||||
from sourceSets.main.runtimeClasspath.filter(File.&exists).collect { it.isDirectory() ? it : zipTree(it) }
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
dependsOn ':groowt-gradle-model:jar'
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(GenerateModuleMetadata).configureEach {
|
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
create('groowtCli', MavenPublication) {
|
|
||||||
artifactId = 'groowt-cli'
|
|
||||||
from components.java
|
|
||||||
pom {
|
|
||||||
withXml {
|
|
||||||
def rootNode = asNode()
|
|
||||||
def dependenciesNode = rootNode.get('dependencies')
|
|
||||||
rootNode.remove(dependenciesNode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package groowt.cli;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
public final class FileAndPathUtil {
|
|
||||||
|
|
||||||
public static File packageNameToFile(String packageName) {
|
|
||||||
return new File(packageName.replace(".", File.separator));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File resolve(File from, File to) {
|
|
||||||
return from.toPath().resolve(to.toPath()).toFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
private FileAndPathUtil() {}
|
|
||||||
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
package groowt.cli;
|
|
||||||
|
|
||||||
import picocli.CommandLine;
|
|
||||||
import picocli.CommandLine.Command;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
@Command(name = "generate", aliases = "gen", description = "Generate a component, template, model, etc.")
|
|
||||||
public final class Generate implements Callable<Integer> {
|
|
||||||
|
|
||||||
@CommandLine.ParentCommand
|
|
||||||
private GroowtCli cli;
|
|
||||||
|
|
||||||
@CommandLine.Option(
|
|
||||||
names = { "-c", "--component" },
|
|
||||||
description = "Create a component with the given name."
|
|
||||||
)
|
|
||||||
private String componentName;
|
|
||||||
|
|
||||||
@CommandLine.Option(
|
|
||||||
names = { "-s", "--sourceSet" },
|
|
||||||
description = "The source set in which to generate the component, etc.",
|
|
||||||
defaultValue = "main"
|
|
||||||
)
|
|
||||||
private String sourceSet;
|
|
||||||
|
|
||||||
@CommandLine.Option(
|
|
||||||
names = { "-d", "--srcDir", "--sourceDir", "--sourceDirectory" },
|
|
||||||
description = "The directory in the source set in which to generate the component, etc."
|
|
||||||
)
|
|
||||||
private File sourceDir;
|
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
|
||||||
@Override
|
|
||||||
public Integer call() {
|
|
||||||
if (this.componentName != null) {
|
|
||||||
GradleUtil.doWithGroowtGradleModel(this.cli.getProjectDir(), model -> {
|
|
||||||
if (this.sourceDir == null) {
|
|
||||||
this.sourceDir = new File(String.join(File.separator, "src", this.sourceSet, "groovy"));
|
|
||||||
}
|
|
||||||
final File packageDir = FileAndPathUtil.resolve(
|
|
||||||
this.sourceDir,
|
|
||||||
FileAndPathUtil.packageNameToFile(model.getBasePackage())
|
|
||||||
);
|
|
||||||
packageDir.mkdirs();
|
|
||||||
final File componentFile = new File(packageDir, this.componentName + ".txt");
|
|
||||||
try (final OutputStream componentFileOutputStream = new FileOutputStream(componentFile)) {
|
|
||||||
componentFileOutputStream.write("Hello, Groowt!".getBytes());
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package groowt.cli;
|
|
||||||
|
|
||||||
import groowt.gradle.model.GroowtGradleModel;
|
|
||||||
import org.gradle.tooling.GradleConnector;
|
|
||||||
import org.gradle.tooling.ProjectConnection;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public final class GradleUtil {
|
|
||||||
|
|
||||||
public static void doWith(File projectDir, Consumer<? super ProjectConnection> action) {
|
|
||||||
final var gradleConnector = GradleConnector.newConnector().forProjectDirectory(projectDir);
|
|
||||||
try (final var projectConnection = gradleConnector.connect()) {
|
|
||||||
action.accept(projectConnection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> void doWith(File projectDir, Class<? extends T> modelClass, Consumer<? super T> modelConsumer) {
|
|
||||||
doWith(projectDir, projectConnection -> {
|
|
||||||
final T model = projectConnection.getModel(modelClass);
|
|
||||||
modelConsumer.accept(model);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void doWithGroowtGradleModel(File projectDir, Consumer<? super GroowtGradleModel> modelConsumer) {
|
|
||||||
doWith(projectDir, GroowtGradleModel.class, modelConsumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private GradleUtil() {}
|
|
||||||
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
package groowt.cli;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import picocli.CommandLine;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
@CommandLine.Command(
|
|
||||||
name = "groowt",
|
|
||||||
description = "The command line interface facilitating development of a Groowt project.",
|
|
||||||
mixinStandardHelpOptions = true,
|
|
||||||
version = "0.1.0",
|
|
||||||
subcommands = { Generate.class }
|
|
||||||
)
|
|
||||||
public final class GroowtCli {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(GroowtCli.class);
|
|
||||||
|
|
||||||
@CommandLine.Option(
|
|
||||||
names = { "-v", "--verbose" },
|
|
||||||
description = "Log verbosely to standard out."
|
|
||||||
)
|
|
||||||
private boolean verbose;
|
|
||||||
|
|
||||||
@CommandLine.Option(
|
|
||||||
names = { "--projectDir" },
|
|
||||||
defaultValue = ".",
|
|
||||||
description = "The root directory of the groowt project."
|
|
||||||
)
|
|
||||||
private File projectDir;
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
logger.info("Hello from Groowt! Version 0.1.0");
|
|
||||||
System.exit(new CommandLine(new GroowtCli()).execute(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isVerbose() {
|
|
||||||
return this.verbose;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getProjectDir() {
|
|
||||||
return this.projectDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">
|
|
||||||
<Appenders>
|
|
||||||
<Console name="root">
|
|
||||||
<PatternLayout>
|
|
||||||
<LevelPatternSelector defaultPattern="[%t] %-5level %logger{1.} %msg%n">
|
|
||||||
<PatternMatch key="DEBUG" pattern="[%t] %-5level %logger{1.}.%M() %msg%n"/>
|
|
||||||
</LevelPatternSelector>
|
|
||||||
</PatternLayout>
|
|
||||||
</Console>
|
|
||||||
</Appenders>
|
|
||||||
<Loggers>
|
|
||||||
<Root level="INFO">
|
|
||||||
<AppenderRef ref="root"/>
|
|
||||||
</Root>
|
|
||||||
</Loggers>
|
|
||||||
</Configuration>
|
|
@ -2,34 +2,31 @@
|
|||||||
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
|
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
|
||||||
|
|
||||||
[versions]
|
[versions]
|
||||||
antlr = '4.13.1'
|
antlr = '4.13.2'
|
||||||
groovy = '4.0.21'
|
groovy = '4.0.25'
|
||||||
junit = '5.10.2'
|
junit = '5.11.4'
|
||||||
kotlin = '1.9.23'
|
kotlin = '1.9.25'
|
||||||
log4j = '2.23.1'
|
log4j = '2.24.3'
|
||||||
mockito = '5.11.0'
|
mockito = '5.15.2'
|
||||||
slf4j = '2.0.12'
|
slf4j = '2.0.16'
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
antlr = { module = 'org.antlr:antlr4', version.ref = 'antlr' }
|
antlr = { module = 'org.antlr:antlr4', version.ref = 'antlr' }
|
||||||
antlr-runtime = { module = 'org.antlr:antlr4-runtime', version.ref = 'antlr' }
|
antlr-runtime = { module = 'org.antlr:antlr4-runtime', version.ref = 'antlr' }
|
||||||
asm = 'org.ow2.asm:asm:9.7'
|
asm = 'org.ow2.asm:asm:9.7.1'
|
||||||
classgraph = 'io.github.classgraph:classgraph:4.8.172'
|
gradle-tooling = 'org.gradle:gradle-tooling-api:8.12.1'
|
||||||
gradle-tooling = 'org.gradle:gradle-tooling-api:8.6'
|
|
||||||
groovy = { module = 'org.apache.groovy:groovy', version.ref = 'groovy' }
|
groovy = { module = 'org.apache.groovy:groovy', version.ref = 'groovy' }
|
||||||
groovy-all = { module = 'org.apache.groovy:groovy-all', version.ref = 'groovy' }
|
|
||||||
groovy-console = { module = 'org.apache.groovy:groovy-console', version.ref = 'groovy' }
|
groovy-console = { module = 'org.apache.groovy:groovy-console', version.ref = 'groovy' }
|
||||||
groovy-templates = { module = 'org.apache.groovy:groovy-templates', version.ref = 'groovy' }
|
groovy-templates = { module = 'org.apache.groovy:groovy-templates', version.ref = 'groovy' }
|
||||||
jakarta-inject = 'jakarta.inject:jakarta.inject-api:2.0.1'
|
jakarta-inject = 'jakarta.inject:jakarta.inject-api:2.0.1'
|
||||||
jansi = 'org.fusesource.jansi:jansi:2.4.1'
|
jansi = 'org.fusesource.jansi:jansi:2.4.1'
|
||||||
jbarchiva = 'com.jessebrault.jbarchiva:jbarchiva:0.2.1'
|
jbarchiva = 'com.jessebrault.jbarchiva:jbarchiva:0.2.2'
|
||||||
jetbrains-anotations = 'org.jetbrains:annotations:24.1.0'
|
jetbrains-anotations = 'org.jetbrains:annotations:26.0.2'
|
||||||
junit-jupiter-api = { module = 'org.junit.jupiter:junit-jupiter-api', version.ref = 'junit' }
|
junit-jupiter-api = { module = 'org.junit.jupiter:junit-jupiter-api', version.ref = 'junit' }
|
||||||
kotlin-stdlib = { module = 'org.jetbrains.kotlin:kotlin-stdlib', version.ref = 'kotlin' }
|
kotlin-stdlib = { module = 'org.jetbrains.kotlin:kotlin-stdlib', version.ref = 'kotlin' }
|
||||||
kotlin-test = { module = 'org.jetbrains.kotlin:kotlin-test', version.ref = 'kotlin' }
|
|
||||||
log4j-core = { module = 'org.apache.logging.log4j:log4j-core', version.ref = 'log4j' }
|
log4j-core = { module = 'org.apache.logging.log4j:log4j-core', version.ref = 'log4j' }
|
||||||
log4j-slf4jBinding = { module = 'org.apache.logging.log4j:log4j-slf4j2-impl', version.ref = 'log4j' }
|
log4j-slf4jBinding = { module = 'org.apache.logging.log4j:log4j-slf4j2-impl', version.ref = 'log4j' }
|
||||||
mockito-core = { module = 'org.mockito:mockito-core', version.ref = 'mockito' }
|
mockito-core = { module = 'org.mockito:mockito-core', version.ref = 'mockito' }
|
||||||
mockito-junit = { module = 'org.mockito:mockito-junit-jupiter', version.ref = 'mockito' }
|
mockito-junit = { module = 'org.mockito:mockito-junit-jupiter', version.ref = 'mockito' }
|
||||||
picocli = 'info.picocli:picocli:4.7.5'
|
picocli = 'info.picocli:picocli:4.7.6'
|
||||||
slf4j-api = { module = 'org.slf4j:slf4j-api', version.ref = 'slf4j' }
|
slf4j-api = { module = 'org.slf4j:slf4j-api', version.ref = 'slf4j' }
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
6
gradlew
vendored
6
gradlew
vendored
@ -15,6 +15,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
@ -55,7 +57,7 @@
|
|||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (3) This script is generated from the Groovy template
|
||||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
# within the Gradle project.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
@ -84,7 +86,7 @@ done
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
2
gradlew.bat
vendored
2
gradlew.bat
vendored
@ -13,6 +13,8 @@
|
|||||||
@rem See the License for the specific language governing permissions and
|
@rem See the License for the specific language governing permissions and
|
||||||
@rem limitations under the License.
|
@rem limitations under the License.
|
||||||
@rem
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%"=="" @echo off
|
@if "%DEBUG%"=="" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'groowt-conventions'
|
|
||||||
id 'groowt-publish'
|
|
||||||
id 'java-library'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
api project(':views')
|
|
||||||
api project(':view-components')
|
|
||||||
api project(':web-view-components')
|
|
||||||
api project(':di')
|
|
||||||
api project(':extensible')
|
|
||||||
api project(':fp')
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
create('groowtAll', MavenPublication) {
|
|
||||||
artifactId = 'groowt-all'
|
|
||||||
from components.java
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'groowt-conventions'
|
|
||||||
id 'java-library'
|
|
||||||
id 'groowt-publish'
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
create('groowtGradleModel', MavenPublication) {
|
|
||||||
artifactId = 'groowt-gradle-model'
|
|
||||||
from components.java
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package groowt.gradle.model;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class DefaultGroowtGradleModel implements GroowtGradleModel, Serializable {
|
|
||||||
|
|
||||||
private String basePackage;
|
|
||||||
private Map<String, Set<File>> sourceSetToTemplatesDirs;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getBasePackage() {
|
|
||||||
return this.basePackage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBasePackage(String basePackage) {
|
|
||||||
this.basePackage = Objects.requireNonNull(basePackage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, Set<File>> getSourceSetToTemplatesDirs() {
|
|
||||||
return Objects.requireNonNull(this.sourceSetToTemplatesDirs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSourceFileSets(Map<String, Set<File>> sourceSetToTemplateDir) {
|
|
||||||
this.sourceSetToTemplatesDirs = sourceSetToTemplateDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package groowt.gradle.model;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public interface GroowtGradleModel {
|
|
||||||
String getBasePackage();
|
|
||||||
Map<String, Set<File>> getSourceSetToTemplatesDirs();
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'groowt-conventions'
|
|
||||||
id 'java-gradle-plugin'
|
|
||||||
id 'groowt-publish'
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation libs.groovy
|
|
||||||
implementation project(':groowt-gradle-model')
|
|
||||||
}
|
|
||||||
|
|
||||||
gradlePlugin {
|
|
||||||
plugins {
|
|
||||||
create('groowtGradle') {
|
|
||||||
id = 'groowt-gradle'
|
|
||||||
implementationClass = 'groowt.gradle.GroowtGradlePlugin'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
create('groowtGradlePlugin', MavenPublication) {
|
|
||||||
artifactId = 'groowt-gradle'
|
|
||||||
from components.java
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package groowt.gradle;
|
|
||||||
|
|
||||||
import org.gradle.api.model.ObjectFactory;
|
|
||||||
import org.gradle.api.provider.Property;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public class DefaultGroowtExtension implements GroowtExtension {
|
|
||||||
|
|
||||||
private final Property<String> basePackage;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public DefaultGroowtExtension(ObjectFactory objectFactory) {
|
|
||||||
this.basePackage = objectFactory.property(String.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Property<String> getBasePackage() {
|
|
||||||
return this.basePackage;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package groowt.gradle;
|
|
||||||
|
|
||||||
import org.gradle.api.file.SourceDirectorySet;
|
|
||||||
import org.gradle.api.internal.file.DefaultSourceDirectorySet;
|
|
||||||
import org.gradle.api.internal.tasks.TaskDependencyFactory;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public class DefaultTemplateSourceDirectorySet extends DefaultSourceDirectorySet implements TemplateSourceDirectorySet {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public DefaultTemplateSourceDirectorySet(
|
|
||||||
SourceDirectorySet delegate,
|
|
||||||
TaskDependencyFactory taskDependencyFactory
|
|
||||||
) {
|
|
||||||
super(delegate, taskDependencyFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
package groowt.gradle;
|
|
||||||
|
|
||||||
import groovy.lang.Closure;
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.file.SourceDirectorySet;
|
|
||||||
import org.gradle.api.model.ObjectFactory;
|
|
||||||
import org.gradle.api.reflect.HasPublicType;
|
|
||||||
import org.gradle.api.reflect.TypeOf;
|
|
||||||
import org.gradle.util.internal.ConfigureUtil;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public class DefaultTemplateSourceSet implements TemplateSourceSet, HasPublicType {
|
|
||||||
|
|
||||||
private final TemplateSourceDirectorySet templateSourceDirectorySet;
|
|
||||||
private final SourceDirectorySet allTemplates;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public DefaultTemplateSourceSet(ObjectFactory objectFactory, String name, String displayName) {
|
|
||||||
this.templateSourceDirectorySet = objectFactory.newInstance(
|
|
||||||
DefaultTemplateSourceDirectorySet.class,
|
|
||||||
objectFactory.sourceDirectorySet(name, displayName + " ComponentTemplate sources")
|
|
||||||
);
|
|
||||||
this.templateSourceDirectorySet.getFilter().include("**/*.wvc", "**/*.gst");
|
|
||||||
this.allTemplates = objectFactory.sourceDirectorySet(
|
|
||||||
"all" + name,
|
|
||||||
displayName + " ComponentTemplate sources"
|
|
||||||
);
|
|
||||||
this.allTemplates.source(this.templateSourceDirectorySet);
|
|
||||||
this.allTemplates.getFilter().include("**/*.wvc", "**/*.gst");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TypeOf<?> getPublicType() {
|
|
||||||
return TypeOf.typeOf(TemplateSourceSet.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TemplateSourceDirectorySet getTemplates() {
|
|
||||||
return this.templateSourceDirectorySet;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TemplateSourceSet templates(Action<? super TemplateSourceDirectorySet> action) {
|
|
||||||
action.execute(this.templateSourceDirectorySet);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
@Override
|
|
||||||
public TemplateSourceSet templates(Closure closure) {
|
|
||||||
ConfigureUtil.configure(closure, this.templateSourceDirectorySet);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SourceDirectorySet getAllTemplates() {
|
|
||||||
return this.allTemplates;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package groowt.gradle;
|
|
||||||
|
|
||||||
import org.gradle.api.provider.Property;
|
|
||||||
|
|
||||||
public interface GroowtExtension {
|
|
||||||
Property<String> getBasePackage();
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
package groowt.gradle;
|
|
||||||
|
|
||||||
import groowt.gradle.model.GroowtGradleModelBuilder;
|
|
||||||
import org.gradle.api.Plugin;
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
import org.gradle.api.artifacts.Configuration;
|
|
||||||
import org.gradle.api.file.FileCollection;
|
|
||||||
import org.gradle.api.internal.tasks.DefaultSourceSet;
|
|
||||||
import org.gradle.api.plugins.GroovyPlugin;
|
|
||||||
import org.gradle.api.plugins.JavaPlugin;
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension;
|
|
||||||
import org.gradle.api.provider.Provider;
|
|
||||||
import org.gradle.api.tasks.SourceSetContainer;
|
|
||||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import static org.gradle.api.internal.lambdas.SerializableLambdas.spec;
|
|
||||||
|
|
||||||
public class GroowtGradlePlugin implements Plugin<Project> {
|
|
||||||
|
|
||||||
private final ToolingModelBuilderRegistry modelBuilderRegistry;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public GroowtGradlePlugin(ToolingModelBuilderRegistry modelBuilderRegistry) {
|
|
||||||
this.modelBuilderRegistry = modelBuilderRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void apply(Project project) {
|
|
||||||
// Apply java and groovy plugins, if not done already
|
|
||||||
final var pluginManager = project.getPluginManager();
|
|
||||||
pluginManager.apply(JavaPlugin.class);
|
|
||||||
pluginManager.apply(GroovyPlugin.class);
|
|
||||||
|
|
||||||
// Create our groowt configuration for storing the groowt dependencies
|
|
||||||
final Provider<Configuration> groowtConfigurationProvider = project.getConfigurations()
|
|
||||||
.register("groowt", configuration -> {
|
|
||||||
configuration.setCanBeConsumed(false);
|
|
||||||
configuration.setCanBeResolved(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create groowt extension and source sets.
|
|
||||||
final GroowtExtension groowtExtension = project.getExtensions().create(
|
|
||||||
GroowtExtension.class,
|
|
||||||
"groowt",
|
|
||||||
DefaultGroowtExtension.class
|
|
||||||
);
|
|
||||||
groowtExtension.getBasePackage().convention("");
|
|
||||||
|
|
||||||
final JavaPluginExtension javaExtension = project.getExtensions().getByType(JavaPluginExtension.class);
|
|
||||||
final SourceSetContainer javaSourceSets = javaExtension.getSourceSets();
|
|
||||||
|
|
||||||
// data resources, such as texts, json files, sqlite-databases, etc.
|
|
||||||
javaSourceSets.getByName("main", mainSourceSet -> {
|
|
||||||
mainSourceSet.getResources().srcDir("src/data");
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: figure out how we can set the compile behavior for all of these.
|
|
||||||
javaSourceSets.forEach(sourceSet -> {
|
|
||||||
final TemplateSourceSet templateSourceSet = project.getObjects().newInstance(
|
|
||||||
DefaultTemplateSourceSet.class,
|
|
||||||
"wvc",
|
|
||||||
((DefaultSourceSet) sourceSet).getDisplayName()
|
|
||||||
);
|
|
||||||
final TemplateSourceDirectorySet templateSourceDirectorySet = templateSourceSet.getTemplates();
|
|
||||||
sourceSet.getExtensions().add(
|
|
||||||
TemplateSourceDirectorySet.class,
|
|
||||||
"templates",
|
|
||||||
templateSourceDirectorySet
|
|
||||||
);
|
|
||||||
templateSourceDirectorySet.srcDir("src/" + sourceSet.getName() + "/templates");
|
|
||||||
|
|
||||||
// Explicitly capture only a FileCollection in the lambda below for compatibility with configuration-cache.
|
|
||||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
|
||||||
final FileCollection templateSourceFiles = templateSourceDirectorySet;
|
|
||||||
sourceSet.getResources().getFilter().exclude(
|
|
||||||
spec(element -> templateSourceFiles.contains(element.getFile()))
|
|
||||||
);
|
|
||||||
sourceSet.getAllJava().source(templateSourceDirectorySet);
|
|
||||||
sourceSet.getAllSource().source(templateSourceDirectorySet);
|
|
||||||
});
|
|
||||||
|
|
||||||
// create init task
|
|
||||||
project.getTasks().create("groowtInit", GroowtInitTask.class, groowtConfigurationProvider);
|
|
||||||
|
|
||||||
// tooling models for cli
|
|
||||||
this.modelBuilderRegistry.register(new GroowtGradleModelBuilder());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
package groowt.gradle;
|
|
||||||
|
|
||||||
import org.gradle.api.DefaultTask;
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
import org.gradle.api.artifacts.Configuration;
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension;
|
|
||||||
import org.gradle.api.provider.Provider;
|
|
||||||
import org.gradle.api.tasks.TaskAction;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class GroowtInitTask extends DefaultTask {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(GroowtInitTask.class);
|
|
||||||
|
|
||||||
private static final Set<String> srcDirsToMake = Set.of("groovy", "templates");
|
|
||||||
|
|
||||||
private final Provider<Configuration> groowtConfigurationProvider;
|
|
||||||
private final File binDir;
|
|
||||||
private final File groowtDir;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public GroowtInitTask(Project project, Provider<Configuration> groowtConfigurationProvider) {
|
|
||||||
this.groowtConfigurationProvider = groowtConfigurationProvider;
|
|
||||||
this.binDir = new File(project.getRootDir(), "bin");
|
|
||||||
this.groowtDir = new File(project.getRootDir(), "groowt");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void createBin() throws IOException {
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
this.binDir.mkdirs();
|
|
||||||
final var groowtFile = new File(this.binDir, "groowt");
|
|
||||||
try (final InputStream bootstrapInputStream = this.getClass().getResourceAsStream("groowt")) {
|
|
||||||
if (bootstrapInputStream != null) {
|
|
||||||
try (final OutputStream bootstrapOutputStream = new FileOutputStream(groowtFile)) {
|
|
||||||
bootstrapInputStream.transferTo(bootstrapOutputStream);
|
|
||||||
}
|
|
||||||
if (!groowtFile.setExecutable(true)) {
|
|
||||||
logger.warn("Could not set bin/groowt to executable; you will have to do this yourself.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("Could not find groowt shell script.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void createGroowtFolder() throws IOException {
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
this.groowtDir.mkdirs();
|
|
||||||
final var groowtConfiguration = this.groowtConfigurationProvider.get();
|
|
||||||
final Set<File> groowtCliFiles = groowtConfiguration.files(dependency -> {
|
|
||||||
final var group = dependency.getGroup();
|
|
||||||
if (group == null || !group.equals("groowt")) {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return dependency.getName().equals("groowt-cli");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
final File groowtCliJarFile = groowtCliFiles.stream()
|
|
||||||
.filter(file -> file.getName().endsWith(".jar"))
|
|
||||||
.findFirst()
|
|
||||||
.orElseThrow(() -> new RuntimeException("Could not find groowt-cli jar file."));
|
|
||||||
final File groowtCliJarOutputFile = new File(this.groowtDir, "groowt-cli.jar");
|
|
||||||
try (final InputStream groowtCliJarInputStream = new FileInputStream(groowtCliJarFile)) {
|
|
||||||
try (final OutputStream groowtCliJarOutputStream = new FileOutputStream(groowtCliJarOutputFile)) {
|
|
||||||
groowtCliJarInputStream.transferTo(groowtCliJarOutputStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void createSrcDirs() {
|
|
||||||
final var javaPluginExtension = this.getProject().getExtensions().getByType(JavaPluginExtension.class);
|
|
||||||
javaPluginExtension.getSourceSets().forEach(sourceSet -> {
|
|
||||||
final var srcDirs = sourceSet.getAllSource().getSrcDirs();
|
|
||||||
srcDirs.forEach(srcDir -> {
|
|
||||||
if (!sourceSet.getName().contains("test") && srcDirsToMake.contains(srcDir.getName())) {
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
srcDir.mkdirs();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@TaskAction
|
|
||||||
public void doInit() throws IOException {
|
|
||||||
this.createBin();
|
|
||||||
this.createGroowtFolder();
|
|
||||||
this.createSrcDirs();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package groowt.gradle;
|
|
||||||
|
|
||||||
import org.gradle.api.file.SourceDirectorySet;
|
|
||||||
|
|
||||||
public interface TemplateSourceDirectorySet extends SourceDirectorySet {}
|
|
@ -1,18 +0,0 @@
|
|||||||
package groowt.gradle;
|
|
||||||
|
|
||||||
import groovy.lang.Closure;
|
|
||||||
import org.gradle.api.Action;
|
|
||||||
import org.gradle.api.file.SourceDirectorySet;
|
|
||||||
|
|
||||||
public interface TemplateSourceSet {
|
|
||||||
|
|
||||||
TemplateSourceDirectorySet getTemplates();
|
|
||||||
|
|
||||||
SourceDirectorySet getAllTemplates();
|
|
||||||
|
|
||||||
TemplateSourceSet templates(Action<? super TemplateSourceDirectorySet> action);
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
TemplateSourceSet templates(Closure closure);
|
|
||||||
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package groowt.gradle.model;
|
|
||||||
|
|
||||||
import groowt.gradle.GroowtExtension;
|
|
||||||
import groowt.gradle.TemplateSourceDirectorySet;
|
|
||||||
import org.gradle.api.Project;
|
|
||||||
import org.gradle.api.plugins.JavaPluginExtension;
|
|
||||||
import org.gradle.api.provider.Property;
|
|
||||||
import org.gradle.tooling.provider.model.ToolingModelBuilder;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class GroowtGradleModelBuilder implements ToolingModelBuilder {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canBuild(String modelName) {
|
|
||||||
return modelName.equals(GroowtGradleModel.class.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Object buildAll(@NotNull String modelName, Project project) {
|
|
||||||
final DefaultGroowtGradleModel model = new DefaultGroowtGradleModel();
|
|
||||||
final var groowtExtension = project.getExtensions().getByType(GroowtExtension.class);
|
|
||||||
|
|
||||||
// base package
|
|
||||||
final Property<String> basePackage = groowtExtension.getBasePackage();
|
|
||||||
if (!basePackage.isPresent()) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"The property 'basePackage' must be set under the 'groowt' extension in build.gradle"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
model.setBasePackage(basePackage.get());
|
|
||||||
|
|
||||||
// templates dirs
|
|
||||||
final Map<String, Set<File>> sourceSetToTemplatesDirs = new HashMap<>();
|
|
||||||
final var javaExtension = project.getExtensions().getByType(JavaPluginExtension.class);
|
|
||||||
javaExtension.getSourceSets().forEach(sourceSet -> {
|
|
||||||
final TemplateSourceDirectorySet templateSourceDirectorySet =
|
|
||||||
sourceSet.getExtensions().getByType(TemplateSourceDirectorySet.class);
|
|
||||||
sourceSetToTemplatesDirs.put(sourceSet.getName(), templateSourceDirectorySet.getFiles());
|
|
||||||
});
|
|
||||||
model.setSourceFileSets(sourceSetToTemplatesDirs);
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
java -jar groowt/groowt-cli.jar "$@"
|
|
@ -6,8 +6,7 @@ pluginManagement {
|
|||||||
|
|
||||||
rootProject.name = 'groowt'
|
rootProject.name = 'groowt'
|
||||||
|
|
||||||
include 'cli', 'groowt-all', 'groowt-gradle', 'groowt-gradle-model', 'views', 'view-components',
|
include 'views', 'view-components', 'web-view-components', 'web-view-components-compiler'
|
||||||
'web-view-components', 'web-view-components-compiler'
|
|
||||||
|
|
||||||
file('util').eachDir {
|
file('util').eachDir {
|
||||||
include it.name
|
include it.name
|
||||||
|
@ -24,7 +24,7 @@ jar {
|
|||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create('di', MavenPublication) {
|
create('di', MavenPublication) {
|
||||||
artifactId = 'groowt-util-di'
|
artifactId = 'util-di'
|
||||||
from components.java
|
from components.java
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,31 +3,58 @@ package groowt.util.di;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class DefaultRegistry implements Registry {
|
public class DefaultRegistry implements Registry {
|
||||||
|
|
||||||
protected record ClassKeyBinding<T>(Class<T> key, Binding<T> binding) {}
|
protected static class BindingContainer {
|
||||||
|
|
||||||
protected final Collection<ClassKeyBinding<?>> classBindings = new ArrayList<>();
|
private final Map<Class<?>, Binding<?>> bindings = new HashMap<>();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> @Nullable Binding<T> get(Class<T> key) {
|
||||||
|
for (final var entry : bindings.entrySet()) {
|
||||||
|
if (entry.getKey().isAssignableFrom(key)) {
|
||||||
|
return (Binding<T>) entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void put(Class<T> key, Binding<T> binding) {
|
||||||
|
this.bindings.put(key, binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(Class<?> key) {
|
||||||
|
this.bindings.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> void removeIf(Class<T> key, Predicate<? super Binding<T>> filter) {
|
||||||
|
if (filter.test(this.get(key))) {
|
||||||
|
this.bindings.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
this.bindings.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final BindingContainer bindingContainer = new BindingContainer();
|
||||||
protected final Collection<RegistryExtension> extensions = new ArrayList<>();
|
protected final Collection<RegistryExtension> extensions = new ArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeBinding(Class<?> key) {
|
public void removeBinding(Class<?> key) {
|
||||||
this.classBindings.removeIf(classKeyBinding -> classKeyBinding.key().equals(key));
|
this.bindingContainer.remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void removeBindingIf(Class<T> key, Predicate<Binding<T>> filter) {
|
public <T> void removeBindingIf(Class<T> key, Predicate<Binding<T>> filter) {
|
||||||
this.classBindings.removeIf(classKeyBinding ->
|
this.bindingContainer.removeIf(key, filter);
|
||||||
classKeyBinding.key().equals(key) && filter.test((Binding<T>) classKeyBinding.binding())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private <E extends RegistryExtension> List<E> getAllRegistryExtensions(Class<E> extensionType) {
|
private <E extends RegistryExtension> List<E> getAllRegistryExtensions(Class<E> extensionType) {
|
||||||
@ -117,18 +144,12 @@ public class DefaultRegistry implements Registry {
|
|||||||
public <T> void bind(Class<T> key, Consumer<? super BindingConfigurator<T>> configure) {
|
public <T> void bind(Class<T> key, Consumer<? super BindingConfigurator<T>> configure) {
|
||||||
final var configurator = new SimpleBindingConfigurator<>(key);
|
final var configurator = new SimpleBindingConfigurator<>(key);
|
||||||
configure.accept(configurator);
|
configure.accept(configurator);
|
||||||
this.classBindings.add(new ClassKeyBinding<>(key, configurator.getBinding()));
|
this.bindingContainer.put(key, configurator.getBinding());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable <T> Binding<T> getBinding(Class<T> key) {
|
public <T> @Nullable Binding<T> getBinding(Class<T> key) {
|
||||||
for (final var classKeyBinding : this.classBindings) {
|
return this.bindingContainer.get(key);
|
||||||
if (key.isAssignableFrom(classKeyBinding.key())) {
|
|
||||||
return (Binding<T>) classKeyBinding.binding();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeyBinder<?> findKeyBinder(Class<?> keyClass) {
|
private KeyBinder<?> findKeyBinder(Class<?> keyClass) {
|
||||||
@ -189,7 +210,7 @@ public class DefaultRegistry implements Registry {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearAllBindings() {
|
public void clearAllBindings() {
|
||||||
this.classBindings.clear();
|
this.bindingContainer.clear();
|
||||||
for (final var extension : this.extensions) {
|
for (final var extension : this.extensions) {
|
||||||
if (extension instanceof KeyBinder<?> keyBinder) {
|
if (extension instanceof KeyBinder<?> keyBinder) {
|
||||||
keyBinder.clearAllBindings();
|
keyBinder.clearAllBindings();
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package groowt.util.di;
|
package groowt.util.di;
|
||||||
|
|
||||||
|
import jakarta.inject.Provider;
|
||||||
import jakarta.inject.Singleton;
|
import jakarta.inject.Singleton;
|
||||||
|
|
||||||
import static groowt.util.di.BindingUtil.toSingleton;
|
import static groowt.util.di.BindingUtil.toLazySingleton;
|
||||||
|
|
||||||
public final class SingletonScopeHandler implements ScopeHandler<Singleton> {
|
public final class SingletonScopeHandler implements ScopeHandler<Singleton> {
|
||||||
|
|
||||||
@ -19,12 +20,22 @@ public final class SingletonScopeHandler implements ScopeHandler<Singleton> {
|
|||||||
RegistryObjectFactory objectFactory
|
RegistryObjectFactory objectFactory
|
||||||
) {
|
) {
|
||||||
final Binding<T> potentialBinding = this.owner.getBinding(dependencyClass);
|
final Binding<T> potentialBinding = this.owner.getBinding(dependencyClass);
|
||||||
if (potentialBinding != null) {
|
return switch (potentialBinding) {
|
||||||
return potentialBinding;
|
case ClassBinding<T>(Class<T> from, Class<? extends T> to) -> {
|
||||||
} else {
|
this.owner.bind(from, toLazySingleton(() -> objectFactory.createInstance(to)));
|
||||||
this.owner.bind(dependencyClass, toSingleton(objectFactory.createInstance(dependencyClass)));
|
yield this.owner.getBinding(from);
|
||||||
return this.owner.getBinding(dependencyClass);
|
}
|
||||||
}
|
case ProviderBinding<T>(Class<T> from, Provider<? extends T> provider) -> {
|
||||||
|
this.owner.bind(from, toLazySingleton(provider::get));
|
||||||
|
yield this.owner.getBinding(from);
|
||||||
|
}
|
||||||
|
case SingletonBinding<T> singletonBinding -> singletonBinding;
|
||||||
|
case LazySingletonBinding<T> lazySingletonBinding -> lazySingletonBinding;
|
||||||
|
case null -> {
|
||||||
|
this.owner.bind(dependencyClass, toLazySingleton(() -> objectFactory.createInstance(dependencyClass)));
|
||||||
|
yield this.owner.getBinding(dependencyClass);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,6 +2,7 @@ package groowt.util.di;
|
|||||||
|
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.inject.Named;
|
import jakarta.inject.Named;
|
||||||
|
import jakarta.inject.Singleton;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static groowt.util.di.BindingUtil.*;
|
import static groowt.util.di.BindingUtil.*;
|
||||||
@ -250,4 +251,25 @@ public class DefaultRegistryObjectFactoryTests {
|
|||||||
assertEquals("Given Greeting", g.greet());
|
assertEquals("Given Greeting", g.greet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public static final class SingletonGreeter implements Greeter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String greet() {
|
||||||
|
return "Hello, World!";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singletonDoesNotOverflow() {
|
||||||
|
final var b = DefaultRegistryObjectFactory.Builder.withDefaults();
|
||||||
|
b.configureRegistry(r -> {
|
||||||
|
r.bind(SingletonGreeter.class, toSelf());
|
||||||
|
});
|
||||||
|
final var f = b.build();
|
||||||
|
final var g = f.get(SingletonGreeter.class);
|
||||||
|
assertEquals("Hello, World!", g.greet());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ jar {
|
|||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create('extensible', MavenPublication) {
|
create('extensible', MavenPublication) {
|
||||||
artifactId = 'groowt-util-extensible'
|
artifactId = 'util-extensible'
|
||||||
from components.java
|
from components.java
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ jar {
|
|||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create('fp', MavenPublication) {
|
create('fp', MavenPublication) {
|
||||||
artifactId = 'groowt-util-fp'
|
artifactId = 'util-fp'
|
||||||
from components.java
|
from components.java
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,14 @@ java {
|
|||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
archiveBaseName = 'groowt-view-components'
|
||||||
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create('viewComponents', MavenPublication) {
|
create('viewComponents', MavenPublication) {
|
||||||
artifactId = 'groowt-view-components'
|
artifactId = 'view-components'
|
||||||
from components.java
|
from components.java
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
}
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -99,6 +99,23 @@ public interface ComponentContext {
|
|||||||
return ancestorClass.cast(this.findNearestAncestor(matching.and(ancestorClass::isInstance)));
|
return ancestorClass.cast(this.findNearestAncestor(matching.and(ancestorClass::isInstance)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default <T extends ViewComponent> @Nullable T findNearestAncestor(Class<T> ancestorClass) {
|
||||||
|
return ancestorClass.cast(this.findNearestAncestor(ancestorClass::isInstance));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hasAncestor(Predicate<? super ViewComponent> matching);
|
||||||
|
|
||||||
|
default <T extends ViewComponent> boolean hasAncestor(
|
||||||
|
Class<T> ancestorClass,
|
||||||
|
Predicate<? super ViewComponent> matching
|
||||||
|
) {
|
||||||
|
return this.hasAncestor(matching.and(ancestorClass::isInstance));
|
||||||
|
}
|
||||||
|
|
||||||
|
default <T extends ViewComponent> boolean hasAncestor(Class<T> ancestorClass) {
|
||||||
|
return this.hasAncestor(ancestorClass::isInstance);
|
||||||
|
}
|
||||||
|
|
||||||
List<ViewComponent> getAllAncestors();
|
List<ViewComponent> getAllAncestors();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,10 @@ public class DefaultComponentContext implements ComponentContext {
|
|||||||
public @Nullable ViewComponent findNearestAncestor(Predicate<? super ViewComponent> matching) {
|
public @Nullable ViewComponent findNearestAncestor(Predicate<? super ViewComponent> matching) {
|
||||||
final List<ViewComponent> componentStack = this.getRenderContext().getComponentStack();
|
final List<ViewComponent> componentStack = this.getRenderContext().getComponentStack();
|
||||||
if (componentStack.size() > 1) {
|
if (componentStack.size() > 1) {
|
||||||
for (final var ancestor : componentStack.subList(1, componentStack.size() -1)) {
|
// 1/27/25: earlier this was originally componentStack.size() - 1 as the second argument to sublist().
|
||||||
|
// On examination today, it didn't make sense, because it would be chopping off the farthest ancestor from
|
||||||
|
// search. So I removed it, in accordance with the implementation in hasAncestor().
|
||||||
|
for (final var ancestor : componentStack.subList(1, componentStack.size())) {
|
||||||
if (matching.test(ancestor)) {
|
if (matching.test(ancestor)) {
|
||||||
return ancestor;
|
return ancestor;
|
||||||
}
|
}
|
||||||
@ -79,6 +82,19 @@ public class DefaultComponentContext implements ComponentContext {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasAncestor(Predicate<? super ViewComponent> matching) {
|
||||||
|
final List<ViewComponent> componentStack = this.getRenderContext().getComponentStack();
|
||||||
|
if (componentStack.size() > 1) {
|
||||||
|
for (final var ancestor : componentStack.subList(1, componentStack.size())) {
|
||||||
|
if (matching.test(ancestor)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ViewComponent> getAllAncestors() {
|
public List<ViewComponent> getAllAncestors() {
|
||||||
final List<ViewComponent> componentStack = this.getRenderContext().getComponentStack();
|
final List<ViewComponent> componentStack = this.getRenderContext().getComponentStack();
|
||||||
|
@ -25,10 +25,14 @@ java {
|
|||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
archiveBaseName = 'groowt-views'
|
||||||
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create('views', MavenPublication) {
|
create('views', MavenPublication) {
|
||||||
artifactId = 'groowt-views'
|
artifactId = 'views'
|
||||||
from components.java
|
from components.java
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,9 @@ tasks.register('uberJar', Jar) {
|
|||||||
group 'groovyc'
|
group 'groovyc'
|
||||||
archiveBaseName = 'web-view-components-uber'
|
archiveBaseName = 'web-view-components-uber'
|
||||||
from sourceSets.main.output
|
from sourceSets.main.output
|
||||||
from sourceSets.main.runtimeClasspath.filter(File.&exists).collect { it.isDirectory() ? it : zipTree(it) }
|
from sourceSets.main.runtimeClasspath
|
||||||
|
.filter(File.&exists)
|
||||||
|
.collect { it.isDirectory() ? it : zipTree(it) }
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,6 +219,10 @@ tasks.named('sourcesJar', Jar) {
|
|||||||
dependsOn 'generateAllAntlr'
|
dependsOn 'generateAllAntlr'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
archiveBaseName = 'groowt-web-view-components-compiler'
|
||||||
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create('webViewComponentsCompiler', MavenPublication) {
|
create('webViewComponentsCompiler', MavenPublication) {
|
||||||
|
@ -4,14 +4,15 @@ if [ "$1" == "--debug" ]; then
|
|||||||
shift
|
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-view-components-uber-0.1.0.jar \
|
-cp build/libs/web-view-components-uber-0.1.2.jar \
|
||||||
org.codehaus.groovy.tools.FileSystemCompiler \
|
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 \
|
||||||
"$@"
|
"$@"
|
||||||
else
|
else
|
||||||
gradle -q uberJar && \
|
gradle -q uberJar && \
|
||||||
groovyc -cp build/libs/web-view-components-uber-0.1.0.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 \
|
||||||
"$@"
|
"$@"
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
<Echo>Hello, World!</Echo>
|
@ -307,7 +307,7 @@ AttributeIdentifierStartChar
|
|||||||
|
|
||||||
fragment
|
fragment
|
||||||
AttributeIdentifierChar
|
AttributeIdentifierChar
|
||||||
: [\p{L}_$0-9]
|
: [-\p{L}_$0-9]
|
||||||
;
|
;
|
||||||
|
|
||||||
Equals
|
Equals
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -6,7 +6,6 @@ import groowt.view.component.web.WebViewComponentBugError;
|
|||||||
import groowt.view.component.web.ast.node.*;
|
import groowt.view.component.web.ast.node.*;
|
||||||
import groowt.view.component.web.transpile.groovy.GroovyUtil;
|
import groowt.view.component.web.transpile.groovy.GroovyUtil;
|
||||||
import groowt.view.component.web.transpile.groovy.GroovyUtil.ConvertResult;
|
import groowt.view.component.web.transpile.groovy.GroovyUtil.ConvertResult;
|
||||||
import groowt.view.component.web.transpile.resolve.ComponentClassNodeResolver;
|
|
||||||
import groowt.view.component.web.util.SourcePosition;
|
import groowt.view.component.web.util.SourcePosition;
|
||||||
import org.codehaus.groovy.ast.*;
|
import org.codehaus.groovy.ast.*;
|
||||||
import org.codehaus.groovy.ast.expr.*;
|
import org.codehaus.groovy.ast.expr.*;
|
||||||
@ -15,7 +14,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import static groowt.view.component.web.transpile.TranspilerUtil.*;
|
import static groowt.view.component.web.transpile.TranspilerUtil.*;
|
||||||
|
|
||||||
@ -25,13 +23,9 @@ public class DefaultComponentTranspiler implements ComponentTranspiler {
|
|||||||
private static final ClassNode COMPONENT_RESOLVE_EXCEPTION_TYPE = ClassHelper.make(ComponentResolveException.class);
|
private static final ClassNode COMPONENT_RESOLVE_EXCEPTION_TYPE = ClassHelper.make(ComponentResolveException.class);
|
||||||
private static final ClassNode COMPONENT_CREATE_EXCEPTION_TYPE = ClassHelper.make(ComponentCreateException.class);
|
private static final ClassNode COMPONENT_CREATE_EXCEPTION_TYPE = ClassHelper.make(ComponentCreateException.class);
|
||||||
|
|
||||||
private static final Pattern isFqn = Pattern.compile("^(\\p{Ll}.+\\.)+\\p{Lu}.+$");
|
|
||||||
private static final Pattern isWithPackage = Pattern.compile("^\\p{Ll}.+\\.");
|
|
||||||
|
|
||||||
private LeftShiftFactory leftShiftFactory;
|
private LeftShiftFactory leftShiftFactory;
|
||||||
private ValueNodeTranspiler valueNodeTranspiler;
|
private ValueNodeTranspiler valueNodeTranspiler;
|
||||||
private BodyTranspiler bodyTranspiler;
|
private BodyTranspiler bodyTranspiler;
|
||||||
private ComponentClassNodeResolver componentClassNodeResolver;
|
|
||||||
|
|
||||||
public void setLeftShiftFactory(LeftShiftFactory leftShiftFactory) {
|
public void setLeftShiftFactory(LeftShiftFactory leftShiftFactory) {
|
||||||
this.leftShiftFactory = leftShiftFactory;
|
this.leftShiftFactory = leftShiftFactory;
|
||||||
@ -45,10 +39,6 @@ public class DefaultComponentTranspiler implements ComponentTranspiler {
|
|||||||
this.bodyTranspiler = bodyTranspiler;
|
this.bodyTranspiler = bodyTranspiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setComponentClassNodeResolver(ComponentClassNodeResolver componentClassNodeResolver) {
|
|
||||||
this.componentClassNodeResolver = componentClassNodeResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UTIL */
|
/* UTIL */
|
||||||
|
|
||||||
protected String getComponentName(int componentNumber) {
|
protected String getComponentName(int componentNumber) {
|
||||||
@ -74,49 +64,14 @@ public class DefaultComponentTranspiler implements ComponentTranspiler {
|
|||||||
|
|
||||||
/* RESOLVE */
|
/* RESOLVE */
|
||||||
|
|
||||||
protected List<Expression> getArgsAsList(
|
protected List<Expression> getArgsAsList(TypedComponentNode componentNode) {
|
||||||
TypedComponentNode componentNode,
|
|
||||||
TranspilerState state
|
|
||||||
) {
|
|
||||||
return switch (componentNode.getArgs().getType()) {
|
return switch (componentNode.getArgs().getType()) {
|
||||||
case ClassComponentTypeNode classComponentTypeNode -> {
|
case ClassComponentTypeNode classComponentTypeNode -> {
|
||||||
final String identifier = classComponentTypeNode.getIdentifier();
|
final String identifier = classComponentTypeNode.getIdentifier();
|
||||||
final ConstantExpression alias = getStringLiteral(identifier);
|
final ConstantExpression alias = getStringLiteral(identifier);
|
||||||
final var matcher = isFqn.matcher(identifier);
|
final ClassNode classNode = ClassHelper.make(identifier);
|
||||||
if (matcher.matches()) {
|
final var classExpression = new ClassExpression(classNode);
|
||||||
final ClassNode classNode = ClassHelper.make(identifier);
|
yield List.of(alias, classExpression);
|
||||||
final ClassExpression classExpression = new ClassExpression(classNode);
|
|
||||||
yield List.of(alias, classExpression);
|
|
||||||
} else {
|
|
||||||
// we need to resolve it
|
|
||||||
final var isWithPackageMatcher = isWithPackage.matcher(identifier);
|
|
||||||
if (isWithPackageMatcher.matches()) {
|
|
||||||
final var resolveResult = this.componentClassNodeResolver.getClassForFqn(identifier);
|
|
||||||
if (resolveResult.isLeft()) {
|
|
||||||
final var error = resolveResult.getLeft();
|
|
||||||
error.setNode(componentNode.getArgs().getType());
|
|
||||||
state.addError(error);
|
|
||||||
yield List.of();
|
|
||||||
} else {
|
|
||||||
final ClassNode classNode = resolveResult.getRight();
|
|
||||||
final ClassExpression classExpression = new ClassExpression(classNode); // TODO: pos
|
|
||||||
yield List.of(alias, classExpression);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
final var resolveResult =
|
|
||||||
this.componentClassNodeResolver.getClassForNameWithoutPackage(identifier);
|
|
||||||
if (resolveResult.isLeft()) {
|
|
||||||
final var error = resolveResult.getLeft();
|
|
||||||
error.setNode(componentNode.getArgs().getType());
|
|
||||||
state.addError(error);
|
|
||||||
yield List.of();
|
|
||||||
} else {
|
|
||||||
final ClassNode classNode = resolveResult.getRight();
|
|
||||||
final ClassExpression classExpression = new ClassExpression(classNode); // TODO: pos
|
|
||||||
yield List.of(alias, classExpression);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
case StringComponentTypeNode stringComponentTypeNode -> {
|
case StringComponentTypeNode stringComponentTypeNode -> {
|
||||||
final String identifier = stringComponentTypeNode.getIdentifier();
|
final String identifier = stringComponentTypeNode.getIdentifier();
|
||||||
@ -127,8 +82,8 @@ public class DefaultComponentTranspiler implements ComponentTranspiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 'h1' | 'MyComponent', MyComponent(.class)
|
// 'h1' | 'MyComponent', MyComponent(.class)
|
||||||
protected ArgumentListExpression getResolveArgs(TypedComponentNode componentNode, TranspilerState state) {
|
protected ArgumentListExpression getResolveArgs(TypedComponentNode componentNode) {
|
||||||
final List<Expression> args = this.getArgsAsList(componentNode, state);
|
final List<Expression> args = this.getArgsAsList(componentNode);
|
||||||
final ArgumentListExpression argsListExpr = new ArgumentListExpression();
|
final ArgumentListExpression argsListExpr = new ArgumentListExpression();
|
||||||
args.forEach(argsListExpr::addExpression);
|
args.forEach(argsListExpr::addExpression);
|
||||||
return argsListExpr;
|
return argsListExpr;
|
||||||
@ -142,7 +97,7 @@ public class DefaultComponentTranspiler implements ComponentTranspiler {
|
|||||||
return new MethodCallExpression(
|
return new MethodCallExpression(
|
||||||
new VariableExpression(state.getRenderContext()),
|
new VariableExpression(state.getRenderContext()),
|
||||||
"resolve",
|
"resolve",
|
||||||
this.getResolveArgs(componentNode, state)
|
this.getResolveArgs(componentNode)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
@ -10,7 +9,6 @@ import groowt.view.component.web.compiler.MultipleWebViewComponentCompileErrorsE
|
|||||||
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.transpile.groovy.GroovyUtil;
|
import groowt.view.component.web.transpile.groovy.GroovyUtil;
|
||||||
import groowt.view.component.web.transpile.resolve.ClassLoaderComponentClassNodeResolver;
|
|
||||||
import org.codehaus.groovy.ast.*;
|
import org.codehaus.groovy.ast.*;
|
||||||
import org.codehaus.groovy.ast.expr.*;
|
import org.codehaus.groovy.ast.expr.*;
|
||||||
import org.codehaus.groovy.ast.stmt.BlockStatement;
|
import org.codehaus.groovy.ast.stmt.BlockStatement;
|
||||||
@ -31,25 +29,13 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DefaultGroovyTranspiler.class);
|
private static final Logger logger = LoggerFactory.getLogger(DefaultGroovyTranspiler.class);
|
||||||
|
|
||||||
protected TranspilerConfiguration getConfiguration(
|
protected TranspilerConfiguration getConfiguration() {
|
||||||
ClassLoaderComponentClassNodeResolver classLoaderComponentClassNodeResolver
|
return SimpleTranspilerConfiguration.withDefaults();
|
||||||
) {
|
|
||||||
return SimpleTranspilerConfiguration.withDefaults(classLoaderComponentClassNodeResolver);
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
protected WebViewComponentModuleNode initModuleNode(
|
||||||
ComponentTemplateCompileUnit compileUnit,
|
ComponentTemplateCompileUnit compileUnit,
|
||||||
WebViewComponentSourceUnit sourceUnit,
|
WebViewComponentSourceUnit sourceUnit
|
||||||
TranspilerConfiguration configuration
|
|
||||||
) {
|
) {
|
||||||
final var moduleNode = new WebViewComponentModuleNode(sourceUnit);
|
final var moduleNode = new WebViewComponentModuleNode(sourceUnit);
|
||||||
sourceUnit.setModuleNode(moduleNode);
|
sourceUnit.setModuleNode(moduleNode);
|
||||||
@ -59,22 +45,16 @@ public class DefaultGroovyTranspiler implements GroovyTranspiler {
|
|||||||
moduleNode.setPackageName(defaultPackageName);
|
moduleNode.setPackageName(defaultPackageName);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addAutomaticImports(moduleNode, configuration);
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,40 +196,32 @@ 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
|
||||||
) throws ComponentTemplateCompileException {
|
) throws ComponentTemplateCompileException {
|
||||||
// resolver, transpilerConfiguration, and positionSetter
|
// transpilerConfiguration, and positionSetter
|
||||||
final ClassLoaderComponentClassNodeResolver resolver = new ClassLoaderComponentClassNodeResolver(
|
final var transpilerConfiguration = this.getConfiguration();
|
||||||
compileUnit,
|
|
||||||
compilerConfiguration.getGroovyClassLoader()
|
|
||||||
);
|
|
||||||
final var transpilerConfiguration = this.getConfiguration(resolver);
|
|
||||||
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)
|
||||||
);
|
);
|
||||||
|
|
||||||
// prepare moduleNode
|
// prepare moduleNode
|
||||||
final WebViewComponentModuleNode moduleNode = this.initModuleNode(
|
final WebViewComponentModuleNode moduleNode = this.initModuleNode(
|
||||||
compileUnit, sourceUnit, transpilerConfiguration
|
compileUnit, sourceUnit
|
||||||
);
|
);
|
||||||
|
|
||||||
// set resolver's moduleNode
|
|
||||||
resolver.setModuleNode(moduleNode);
|
|
||||||
|
|
||||||
// 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();
|
||||||
@ -257,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);
|
||||||
|
@ -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
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package groowt.view.component.web.transpile;
|
package groowt.view.component.web.transpile;
|
||||||
|
|
||||||
import groovy.lang.Tuple3;
|
import groovy.lang.Tuple3;
|
||||||
import groowt.view.component.web.transpile.resolve.ComponentClassNodeResolver;
|
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
import org.codehaus.groovy.ast.ClassNode;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -12,9 +11,8 @@ import static groowt.view.component.web.transpile.TranspilerUtil.*;
|
|||||||
|
|
||||||
public class SimpleTranspilerConfiguration implements TranspilerConfiguration {
|
public class SimpleTranspilerConfiguration implements TranspilerConfiguration {
|
||||||
|
|
||||||
public static TranspilerConfiguration withDefaults(ComponentClassNodeResolver componentClassNodeResolver) {
|
public static TranspilerConfiguration withDefaults() {
|
||||||
final var c = new SimpleTranspilerConfiguration();
|
final var c = new SimpleTranspilerConfiguration();
|
||||||
c.setComponentClassNodeResolver(componentClassNodeResolver);
|
|
||||||
|
|
||||||
final var ct = new DefaultComponentTranspiler();
|
final var ct = new DefaultComponentTranspiler();
|
||||||
final PositionSetter ps = new SimplePositionSetter();
|
final PositionSetter ps = new SimplePositionSetter();
|
||||||
@ -27,7 +25,6 @@ public class SimpleTranspilerConfiguration implements TranspilerConfiguration {
|
|||||||
ct.setLeftShiftFactory(lsf);
|
ct.setLeftShiftFactory(lsf);
|
||||||
ct.setBodyTranspiler(bt);
|
ct.setBodyTranspiler(bt);
|
||||||
ct.setValueNodeTranspiler(vnt);
|
ct.setValueNodeTranspiler(vnt);
|
||||||
ct.setComponentClassNodeResolver(componentClassNodeResolver);
|
|
||||||
|
|
||||||
c.setComponentTranspiler(ct);
|
c.setComponentTranspiler(ct);
|
||||||
c.setPositionSetter(ps);
|
c.setPositionSetter(ps);
|
||||||
@ -40,7 +37,6 @@ public class SimpleTranspilerConfiguration implements TranspilerConfiguration {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ComponentClassNodeResolver componentClassNodeResolver;
|
|
||||||
private ComponentTranspiler componentTranspiler;
|
private ComponentTranspiler componentTranspiler;
|
||||||
private PositionSetter positionSetter;
|
private PositionSetter positionSetter;
|
||||||
private LeftShiftFactory leftShiftFactory;
|
private LeftShiftFactory leftShiftFactory;
|
||||||
@ -49,14 +45,6 @@ public class SimpleTranspilerConfiguration implements TranspilerConfiguration {
|
|||||||
private BodyTranspiler bodyTranspiler;
|
private BodyTranspiler bodyTranspiler;
|
||||||
private ValueNodeTranspiler valueNodeTranspiler;
|
private ValueNodeTranspiler valueNodeTranspiler;
|
||||||
|
|
||||||
public ComponentClassNodeResolver getComponentClassNodeResolver() {
|
|
||||||
return Objects.requireNonNull(this.componentClassNodeResolver);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setComponentClassNodeResolver(ComponentClassNodeResolver componentClassNodeResolver) {
|
|
||||||
this.componentClassNodeResolver = componentClassNodeResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComponentTranspiler getComponentTranspiler() {
|
public ComponentTranspiler getComponentTranspiler() {
|
||||||
return Objects.requireNonNull(this.componentTranspiler);
|
return Objects.requireNonNull(this.componentTranspiler);
|
||||||
}
|
}
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
package groowt.view.component.web.transpile.resolve;
|
|
||||||
|
|
||||||
import groowt.util.fp.either.Either;
|
|
||||||
import groowt.view.component.web.WebViewComponent;
|
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
|
||||||
import org.codehaus.groovy.ast.ClassHelper;
|
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class CachingComponentClassNodeResolver implements ComponentClassNodeResolver {
|
|
||||||
|
|
||||||
private final List<ClassNode> classNodes = new ArrayList<>();
|
|
||||||
|
|
||||||
protected final WebViewComponentTemplateCompileUnit compileUnit;
|
|
||||||
|
|
||||||
public CachingComponentClassNodeResolver(WebViewComponentTemplateCompileUnit compileUnit) {
|
|
||||||
this.compileUnit = compileUnit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addClass(Class<? extends WebViewComponent> clazz) {
|
|
||||||
this.classNodes.add(ClassHelper.make(clazz));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addClassNode(ClassNode classNode) {
|
|
||||||
this.classNodes.add(classNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Either<ClassNodeResolveException, ClassNode> getClassForFqn(String fqn) {
|
|
||||||
for (final var classNode : this.classNodes) {
|
|
||||||
if (classNode.getName().equals(fqn)) {
|
|
||||||
return Either.right(classNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Either.left(new ClassNodeResolveException(
|
|
||||||
this.compileUnit,
|
|
||||||
fqn,
|
|
||||||
"Could not resolve ClassNode for fqn: " + fqn,
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Either<ClassNodeResolveException, ClassNode> getClassForNameWithoutPackage(String nameWithoutPackage) {
|
|
||||||
for (final var classNode : this.classNodes) {
|
|
||||||
if (classNode.getNameWithoutPackage().equals(nameWithoutPackage)) {
|
|
||||||
return Either.right(classNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Either.left(new ClassNodeResolveException(
|
|
||||||
this.compileUnit,
|
|
||||||
nameWithoutPackage,
|
|
||||||
"Could not resolve ClassNode for nameWithoutPackage: " + nameWithoutPackage,
|
|
||||||
null
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package groowt.view.component.web.transpile.resolve;
|
|
||||||
|
|
||||||
import groowt.util.fp.either.Either;
|
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class ClassLoaderComponentClassNodeResolver extends ModuleNodeComponentClassNodeResolver {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ModuleNodeComponentClassNodeResolver.class);
|
|
||||||
|
|
||||||
protected final ClassLoader classLoader;
|
|
||||||
|
|
||||||
public ClassLoaderComponentClassNodeResolver(
|
|
||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
|
||||||
ClassLoader classLoader
|
|
||||||
) {
|
|
||||||
super(compileUnit);
|
|
||||||
this.classLoader = classLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final Either<ClassNodeResolveException, ClassNode> resolveWithClassLoader(String fqn) {
|
|
||||||
logger.debug("Trying to resolve {}", fqn);
|
|
||||||
try {
|
|
||||||
Class<?> clazz = this.classLoader.loadClass(ResolveUtil.convertCanonicalNameToBinaryName(fqn));
|
|
||||||
final var classNode = ResolveUtil.getClassNode(clazz);
|
|
||||||
return Either.right(classNode);
|
|
||||||
} catch (ClassNotFoundException classNotFoundException) {
|
|
||||||
return Either.left(
|
|
||||||
new ClassNodeResolveException(
|
|
||||||
this.compileUnit,
|
|
||||||
fqn,
|
|
||||||
"Could not find class " + fqn + " with classLoader " +
|
|
||||||
this.classLoader,
|
|
||||||
classNotFoundException
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Either<ClassNodeResolveException, ClassNode> getClassForFqn(String fqn) {
|
|
||||||
return super.getClassForFqn(fqn).flatMapLeft(ignored -> {
|
|
||||||
final var classLoaderResult = this.resolveWithClassLoader(fqn);
|
|
||||||
if (classLoaderResult.isRight()) {
|
|
||||||
this.addClassNode(classLoaderResult.getRight());
|
|
||||||
}
|
|
||||||
return classLoaderResult;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package groowt.view.component.web.transpile.resolve;
|
|
||||||
|
|
||||||
import groowt.util.fp.either.Either;
|
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileException;
|
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
|
||||||
|
|
||||||
public interface ComponentClassNodeResolver {
|
|
||||||
|
|
||||||
final class ClassNodeResolveException extends WebViewComponentTemplateCompileException {
|
|
||||||
|
|
||||||
private final String identifier;
|
|
||||||
|
|
||||||
public ClassNodeResolveException(
|
|
||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
|
||||||
String identifier,
|
|
||||||
String message
|
|
||||||
) {
|
|
||||||
super(compileUnit, message);
|
|
||||||
this.identifier = identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ClassNodeResolveException(
|
|
||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
|
||||||
String identifier,
|
|
||||||
String message,
|
|
||||||
Throwable cause
|
|
||||||
) {
|
|
||||||
super(compileUnit, message, cause);
|
|
||||||
this.identifier = identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getIdentifier() {
|
|
||||||
return this.identifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Either<ClassNodeResolveException, ClassNode> getClassForFqn(String fqn);
|
|
||||||
Either<ClassNodeResolveException, ClassNode> getClassForNameWithoutPackage(String nameWithoutPackage);
|
|
||||||
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package groowt.view.component.web.transpile.resolve;
|
|
||||||
|
|
||||||
import groowt.util.fp.either.Either;
|
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
|
||||||
import org.codehaus.groovy.ast.ModuleNode;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class ModuleNodeComponentClassNodeResolver extends CachingComponentClassNodeResolver {
|
|
||||||
|
|
||||||
private ModuleNode moduleNode;
|
|
||||||
|
|
||||||
public ModuleNodeComponentClassNodeResolver(WebViewComponentTemplateCompileUnit compileUnit) {
|
|
||||||
super(compileUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ModuleNode getModuleNode() {
|
|
||||||
return Objects.requireNonNull(this.moduleNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setModuleNode(ModuleNode moduleNode) {
|
|
||||||
this.moduleNode = Objects.requireNonNull(moduleNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Either<ClassNodeResolveException, ClassNode> getClassForNameWithoutPackage(String nameWithoutPackage) {
|
|
||||||
return super.getClassForNameWithoutPackage(nameWithoutPackage).flatMapLeft(ignored -> {
|
|
||||||
// try regular imports first
|
|
||||||
final var importedClassNode = this.getModuleNode().getImportType(nameWithoutPackage);
|
|
||||||
if (importedClassNode != null) {
|
|
||||||
this.addClassNode(importedClassNode);
|
|
||||||
return Either.right(importedClassNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// try star imports
|
|
||||||
final var starImports = this.getModuleNode().getStarImports();
|
|
||||||
for (final var starImport : starImports) {
|
|
||||||
final var packageName = starImport.getPackageName();
|
|
||||||
final String fqn;
|
|
||||||
if (!packageName.equals(".") && packageName.endsWith(".")) {
|
|
||||||
fqn = packageName + nameWithoutPackage;
|
|
||||||
} else {
|
|
||||||
fqn = packageName + "." + nameWithoutPackage;
|
|
||||||
}
|
|
||||||
final var withPackage = this.getClassForFqn(fqn);
|
|
||||||
if (withPackage.isRight()) {
|
|
||||||
return withPackage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// try pre-pending package and asking for fqn
|
|
||||||
final String moduleNodePackageName = this.getModuleNode().getPackageName();
|
|
||||||
final String packageName;
|
|
||||||
if (moduleNodePackageName != null) {
|
|
||||||
packageName = moduleNodePackageName;
|
|
||||||
} else {
|
|
||||||
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);
|
|
||||||
if (withPackage.isRight()) {
|
|
||||||
return withPackage;
|
|
||||||
} else {
|
|
||||||
return Either.left(new ClassNodeResolveException(
|
|
||||||
this.compileUnit,
|
|
||||||
nameWithoutPackage,
|
|
||||||
"Cannot resolve " + nameWithoutPackage
|
|
||||||
+ " from imports, package-local classes, or pre-added classes."
|
|
||||||
));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package groowt.view.component.web.transpile.resolve;
|
|
||||||
|
|
||||||
import org.codehaus.groovy.ast.ClassHelper;
|
|
||||||
import org.codehaus.groovy.ast.ClassNode;
|
|
||||||
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public final class ResolveUtil {
|
|
||||||
|
|
||||||
private static final Pattern packageSplitter = Pattern.compile("^(?<package>(?>\\p{Ll}[^.]*\\.)*)(?<top>\\p{Lu}[^.]*)(?<members>(?>\\.\\p{Lu}[^.]*)*)$");
|
|
||||||
|
|
||||||
public static ClassNode getClassNode(Class<?> clazz) {
|
|
||||||
return ClassHelper.makeCached(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String convertCanonicalNameToBinaryName(String canonicalName) {
|
|
||||||
final var matcher = packageSplitter.matcher(canonicalName);
|
|
||||||
if (matcher.matches()) {
|
|
||||||
return new StringBuilder()
|
|
||||||
.append(matcher.group("package"))
|
|
||||||
.append(matcher.group("top"))
|
|
||||||
.append(matcher.group("members").replaceAll("\\.", "\\$"))
|
|
||||||
.toString();
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Cannot split apart " + canonicalName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResolveUtil() {}
|
|
||||||
|
|
||||||
}
|
|
@ -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()
|
|
||||||
|
@ -3,7 +3,6 @@ package groowt.view.component.web.transpiler;
|
|||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
||||||
import groowt.view.component.web.transpile.SimpleTranspilerConfiguration;
|
import groowt.view.component.web.transpile.SimpleTranspilerConfiguration;
|
||||||
import groowt.view.component.web.transpile.TranspilerConfiguration;
|
import groowt.view.component.web.transpile.TranspilerConfiguration;
|
||||||
import groowt.view.component.web.transpile.resolve.CachingComponentClassNodeResolver;
|
|
||||||
import org.codehaus.groovy.ast.ModuleNode;
|
import org.codehaus.groovy.ast.ModuleNode;
|
||||||
|
|
||||||
public class DefaultBodyTranspilerTests extends BodyTranspilerTests {
|
public class DefaultBodyTranspilerTests extends BodyTranspilerTests {
|
||||||
@ -13,7 +12,7 @@ public class DefaultBodyTranspilerTests extends BodyTranspilerTests {
|
|||||||
WebViewComponentTemplateCompileUnit compileUnit,
|
WebViewComponentTemplateCompileUnit compileUnit,
|
||||||
ModuleNode moduleNode
|
ModuleNode moduleNode
|
||||||
) {
|
) {
|
||||||
return SimpleTranspilerConfiguration.withDefaults(new CachingComponentClassNodeResolver(compileUnit));
|
return SimpleTranspilerConfiguration.withDefaults();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package groowt.view.component.web.transpiler;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static groowt.view.component.web.transpile.resolve.ResolveUtil.convertCanonicalNameToBinaryName;
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
public class ResolveUtilTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void abcABC() {
|
|
||||||
assertEquals("a.b.c.A$B$C", convertCanonicalNameToBinaryName("a.b.c.A.B.C"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void ABC() {
|
|
||||||
assertEquals("A$B$C", convertCanonicalNameToBinaryName("A.B.C"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void abcA() {
|
|
||||||
assertEquals("a.b.c.A", convertCanonicalNameToBinaryName("a.b.c.A"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1 @@
|
|||||||
|
<test test-attr />
|
@ -0,0 +1 @@
|
|||||||
|
<test-type />
|
@ -0,0 +1,7 @@
|
|||||||
|
0: ComponentOpen[1,1](<)
|
||||||
|
1: StringIdentifier[1,2](test)
|
||||||
|
2: Nlws[1,6]( )
|
||||||
|
3: AttributeIdentifier[1,7](test-attr)
|
||||||
|
4: Nlws[1,16]( )
|
||||||
|
5: ComponentSelfClose[1,17](/>)
|
||||||
|
6: RawText[1,19](\n)
|
@ -0,0 +1,5 @@
|
|||||||
|
0: ComponentOpen[1,1](<)
|
||||||
|
1: StringIdentifier[1,2](test-type)
|
||||||
|
2: Nlws[1,11]( )
|
||||||
|
3: ComponentSelfClose[1,12](/>)
|
||||||
|
4: RawText[1,14](\n)
|
@ -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,
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#/usr/bin/env bash
|
#/usr/bin/env bash
|
||||||
|
|
||||||
|
VERSION="0.1.2"
|
||||||
|
|
||||||
if [ "\$1" == "--debug" ]; then
|
if [ "\$1" == "--debug" ]; then
|
||||||
shift
|
shift
|
||||||
gradle -q toolsJar && java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:8192 -cp build/libs/web-view-components-compiler-tools-0.1.0.jar $mainClassName "\$@"
|
gradle -q toolsJar && java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:8192 -cp build/libs/web-view-components-compiler-tools-\$VERSION.jar $mainClassName "\$@"
|
||||||
else
|
else
|
||||||
gradle -q toolsJar && java -cp build/libs/web-view-components-compiler-tools-0.1.0.jar $mainClassName "\$@"
|
gradle -q toolsJar && java -cp build/libs/web-view-components-compiler-tools-\$VERSION.jar $mainClassName "\$@"
|
||||||
fi
|
fi
|
||||||
|
@ -9,6 +9,7 @@ import org.apache.logging.log4j.core.LoggerContext;
|
|||||||
import org.codehaus.groovy.control.CompilationFailedException;
|
import org.codehaus.groovy.control.CompilationFailedException;
|
||||||
import org.codehaus.groovy.control.CompilationUnit;
|
import org.codehaus.groovy.control.CompilationUnit;
|
||||||
import org.codehaus.groovy.control.CompilerConfiguration;
|
import org.codehaus.groovy.control.CompilerConfiguration;
|
||||||
|
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||||
import picocli.CommandLine;
|
import picocli.CommandLine;
|
||||||
import picocli.CommandLine.Command;
|
import picocli.CommandLine.Command;
|
||||||
|
|
||||||
@ -71,6 +72,15 @@ public final class GroovyWvcCompiler implements Callable<Integer> {
|
|||||||
|
|
||||||
public Integer doCompile() {
|
public Integer doCompile() {
|
||||||
final CompilerConfiguration configuration = new CompilerConfiguration();
|
final CompilerConfiguration configuration = new CompilerConfiguration();
|
||||||
|
|
||||||
|
final var addGroowtImports = new ImportCustomizer();
|
||||||
|
addGroowtImports.addStarImports(
|
||||||
|
"groowt.view.component.web.lib",
|
||||||
|
"groowt.view.component.web.runtime",
|
||||||
|
"groowt.view.component.runtime"
|
||||||
|
);
|
||||||
|
configuration.addCompilationCustomizers(addGroowtImports);
|
||||||
|
|
||||||
configuration.setPluginFactory(new WebViewComponentParserPluginFactory());
|
configuration.setPluginFactory(new WebViewComponentParserPluginFactory());
|
||||||
final CompilationUnit compilationUnit = new CompilationUnit(configuration);
|
final CompilationUnit compilationUnit = new CompilationUnit(configuration);
|
||||||
|
|
||||||
|
@ -133,6 +133,10 @@ java {
|
|||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
archiveBaseName = 'groowt-web-view-components'
|
||||||
|
}
|
||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
create('webViewComponents', MavenPublication) {
|
create('webViewComponents', MavenPublication) {
|
||||||
|
@ -14,6 +14,8 @@ class DefaultWebViewComponentScope extends DefaultComponentScope implements WebV
|
|||||||
addWithAttr(DefaultCase)
|
addWithAttr(DefaultCase)
|
||||||
addWithAttr(Each)
|
addWithAttr(Each)
|
||||||
addWithAttr(Echo)
|
addWithAttr(Echo)
|
||||||
|
addWithAttr(Outlet)
|
||||||
|
addWithAttr(Render)
|
||||||
addWithAttr(Switch)
|
addWithAttr(Switch)
|
||||||
addWithAttr(WhenNotEmpty)
|
addWithAttr(WhenNotEmpty)
|
||||||
addWithAttr(WhenNotNull)
|
addWithAttr(WhenNotNull)
|
||||||
|
@ -5,7 +5,6 @@ import groowt.view.component.ComponentRenderException
|
|||||||
import groowt.view.component.context.ComponentContext
|
import groowt.view.component.context.ComponentContext
|
||||||
import groowt.view.component.context.ComponentScope.TypeAndFactory
|
import groowt.view.component.context.ComponentScope.TypeAndFactory
|
||||||
import groowt.view.component.factory.ComponentFactory
|
import groowt.view.component.factory.ComponentFactory
|
||||||
import groowt.view.component.web.WithHtml
|
|
||||||
|
|
||||||
class IntrinsicHtml extends DelegatingWebViewComponent implements WithHtml {
|
class IntrinsicHtml extends DelegatingWebViewComponent implements WithHtml {
|
||||||
|
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
package groowt.view.component.web.lib
|
||||||
|
|
||||||
|
import groowt.view.View
|
||||||
|
import groowt.view.component.ComponentRenderException
|
||||||
|
import groowt.view.component.runtime.DefaultComponentWriter
|
||||||
|
|
||||||
|
class Outlet extends DelegatingWebViewComponent {
|
||||||
|
|
||||||
|
private final List givenChildren
|
||||||
|
|
||||||
|
Outlet(Map attr) {
|
||||||
|
givenChildren = attr.children ?: []
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View getDelegate() {
|
||||||
|
return { Writer w ->
|
||||||
|
if (!context.hasAncestor(OutletContainer)) {
|
||||||
|
throw new ComponentRenderException(
|
||||||
|
"<Outlet> is being used outside of a component implementing OutletContainer."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
def cw = new DefaultComponentWriter(w, context.renderContext, context)
|
||||||
|
givenChildren.each { cw << it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package groowt.view.component.web.lib
|
||||||
|
|
||||||
|
import groowt.view.component.web.WebViewComponent
|
||||||
|
|
||||||
|
interface OutletContainer extends WebViewComponent {}
|
@ -0,0 +1,28 @@
|
|||||||
|
package groowt.view.component.web.lib
|
||||||
|
|
||||||
|
import groowt.view.View
|
||||||
|
|
||||||
|
class Render extends DelegatingWebViewComponent {
|
||||||
|
|
||||||
|
private final Object item
|
||||||
|
|
||||||
|
Render(Map attr) {
|
||||||
|
item = Objects.requireNonNull(attr.item, "<Render> attribute 'item' must not be null.")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View getDelegate() {
|
||||||
|
return { Writer w ->
|
||||||
|
if (item.respondsTo('renderTo', [Writer] as Class[])) {
|
||||||
|
item.renderTo(w)
|
||||||
|
} else if (item.respondsTo('render')) {
|
||||||
|
w << item.render()
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
'<Render> must use an item which responds to either renderTo(Writer) or render().'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package groowt.view.component.web
|
package groowt.view.component.web.lib
|
||||||
|
|
||||||
trait WithHtml {
|
trait WithHtml {
|
||||||
|
|
@ -4,13 +4,14 @@ 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;
|
||||||
import groowt.view.component.compiler.source.URLSource;
|
import groowt.view.component.compiler.source.URLSource;
|
||||||
import org.codehaus.groovy.control.CompilationUnit;
|
import org.codehaus.groovy.control.CompilationUnit;
|
||||||
|
import org.codehaus.groovy.control.CompilerConfiguration;
|
||||||
import org.codehaus.groovy.control.Janitor;
|
import org.codehaus.groovy.control.Janitor;
|
||||||
|
import org.codehaus.groovy.control.customizers.ImportCustomizer;
|
||||||
import org.codehaus.groovy.control.io.ReaderSource;
|
import org.codehaus.groovy.control.io.ReaderSource;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
@ -20,8 +21,20 @@ import java.net.URI;
|
|||||||
public class DefaultWebViewComponentTemplateCompileUnit extends AbstractComponentTemplateCompileUnit
|
public class DefaultWebViewComponentTemplateCompileUnit extends AbstractComponentTemplateCompileUnit
|
||||||
implements ReaderSource, WebViewComponentTemplateCompileUnit {
|
implements ReaderSource, WebViewComponentTemplateCompileUnit {
|
||||||
|
|
||||||
|
private static CompilationUnit getCompilationUnit() {
|
||||||
|
final var configuration = new CompilerConfiguration();
|
||||||
|
final var addGroowtImports = new ImportCustomizer();
|
||||||
|
addGroowtImports.addStarImports(
|
||||||
|
"groowt.view.component.web.lib",
|
||||||
|
"groowt.view.component.web.runtime",
|
||||||
|
"groowt.view.component.runtime"
|
||||||
|
);
|
||||||
|
configuration.addCompilationCustomizers(addGroowtImports);
|
||||||
|
return new CompilationUnit(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
private final String defaultPackageName;
|
private final String defaultPackageName;
|
||||||
private final CompilationUnit groovyCompilationUnit = new CompilationUnit();
|
private final CompilationUnit groovyCompilationUnit;
|
||||||
|
|
||||||
public DefaultWebViewComponentTemplateCompileUnit(
|
public DefaultWebViewComponentTemplateCompileUnit(
|
||||||
String descriptiveName,
|
String descriptiveName,
|
||||||
@ -35,6 +48,7 @@ public class DefaultWebViewComponentTemplateCompileUnit extends AbstractComponen
|
|||||||
} else {
|
} else {
|
||||||
this.defaultPackageName = defaultPackageName;
|
this.defaultPackageName = defaultPackageName;
|
||||||
}
|
}
|
||||||
|
this.groovyCompilationUnit = getCompilationUnit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package groowt.view.component.web.lib
|
||||||
|
|
||||||
|
|
||||||
|
import groowt.view.component.web.WebViewComponentContext
|
||||||
|
import groowt.view.component.web.WebViewComponentScope
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class OutletTests extends AbstractWebViewComponentTests {
|
||||||
|
|
||||||
|
static final class DummyOutletContainer extends Echo implements OutletContainer {
|
||||||
|
|
||||||
|
DummyOutletContainer() {
|
||||||
|
super([:])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void configureContext(WebViewComponentContext context) {
|
||||||
|
context.configureRootScope(WebViewComponentScope) {
|
||||||
|
addWithNoArgConstructor(DummyOutletContainer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void smokeScreen() {
|
||||||
|
doTest('<OutletTests.DummyOutletContainer><Outlet /></OutletTests.DummyOutletContainer>', '')
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withChildren() {
|
||||||
|
doTest('<OutletTests.DummyOutletContainer><Echo items={[0, 1, 2]}><Outlet children={items} /></Echo></OutletTests.DummyOutletContainer>', '012')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package groowt.view.component.web.lib
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class RenderTests extends AbstractWebViewComponentTests {
|
||||||
|
|
||||||
|
static final class RenderToExample {
|
||||||
|
|
||||||
|
void renderTo(Writer w) {
|
||||||
|
w << 'Hello, World!'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class RenderExample {
|
||||||
|
|
||||||
|
String render() {
|
||||||
|
'Hello, World!'
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void renderToExample() {
|
||||||
|
doTest('''
|
||||||
|
---
|
||||||
|
package groowt.view.component.web.lib
|
||||||
|
---
|
||||||
|
<Render item={new RenderTests.RenderToExample()} />
|
||||||
|
'''.stripIndent().trim(),
|
||||||
|
'Hello, World!'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void renderExample() {
|
||||||
|
doTest('''
|
||||||
|
---
|
||||||
|
package groowt.view.component.web.lib
|
||||||
|
---
|
||||||
|
<Render item={new RenderTests.RenderExample()} />
|
||||||
|
'''.stripIndent().trim(),
|
||||||
|
'Hello, World!'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user