diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index e3d86f3c..0dbf571f 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -42,15 +42,26 @@ jobs:
java-version: ${{env.JAVA_VERSION}}
- uses: actions/cache@v4
with:
- path: ~/.m2/repository
- key: build_maven
+ path: |
+ ~/.m2/repository
+ ~/.gradle
+ key: manual_build_cache_key
- name: Build And Test
run: ./mvnw install -e --ntp -B
- name: Test JPMS
run: ./mvnw clean verify -pl it/java8 -P it-jpms -e --ntp -B
- name: Test Maven 3.2.5 compatibility
- working-directory: maven-plugin/it
+ working-directory: build-tool-plugins/maven-plugin/it
run: ./mvnw stype:gen -e -B
+ - name: Build and Test Gradle plugin
+ working-directory: build-tool-plugins/gradle-plugin
+ run: ./gradlew --no-daemon test publishToMavenLocal --stacktrace
+ - name: Download Gradle in Gradle Plugin IT
+ working-directory: build-tool-plugins/gradle-plugin/it
+ run: ./gradlew --no-daemon --version
+# - name: Test Gradle plugin # Gradle 7 does not support JDK21
+# working-directory: build-tool-plugins/gradle-plugin/it
+# run: ./gradlew stypeGen test --stacktrace
- name: Javadoc
run: ./mvnw -P release javadoc:javadoc --ntp -B
- name: Upload generated sources
@@ -92,13 +103,18 @@ jobs:
# run: ls -lhR ~/.m2/repository/online/sharedtype
- uses: actions/cache/restore@v4
with:
- path: ~/.m2/repository
- key: build_maven
+ path: |
+ ~/.m2/repository
+ ~/.gradle
+ key: manual_build_cache_key
- name: Test
run: ./mvnw verify -pl it/java8 -e --ntp -B
- name: Maven Plugin Test
- working-directory: maven-plugin/it
+ working-directory: build-tool-plugins/maven-plugin/it
run: ./mvnw stype:gen -e -B
+ - name: Gradle Plugin Test
+ working-directory: build-tool-plugins/gradle-plugin/it
+ run: ./gradlew stypeGen test --stacktrace
client_test:
needs: [build_and_test]
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index c8c16c85..46ab096e 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -34,6 +34,8 @@ jobs:
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
SONATYPE_CENTRAL_USER: ${{ secrets.SONATYPE_CENTRAL_USER }}
SONATYPE_CENTRAL_PASS: ${{ secrets.SONATYPE_CENTRAL_PASS }}
+ GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PUBLISH_KEY }}
+ GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PUBLISH_SECRET }}
run: |
. ./misc/release.sh
echo "new_version=$(cat NEW_VERSION.cache)" >> "$GITHUB_OUTPUT"
diff --git a/README.md b/README.md
index 4072f4ea..12d02a35 100644
--- a/README.md
+++ b/README.md
@@ -18,22 +18,6 @@ export interface User {
email: string;
}
```
-Go:
-```golang
-type User struct {
- Name string
- Age int
- Email string
-}
-```
-Rust:
-```rust
-pub struct User {
- name: String,
- age: i32,
- email: String,
-}
-```
## Features
* Java8+ compatible.
@@ -41,6 +25,7 @@ pub struct User {
* Compile-time constant support.
* Fast. (Execution takes milliseconds with `-proc:only`.)
* Simple global + type level configurations.
+* Multiple target language options: Typescript, Go, Rust.
## Documentation
* [User Guide](doc/Usage.md)
diff --git a/annotation/pom.xml b/annotation/pom.xml
index d89ffbb0..07d4b397 100644
--- a/annotation/pom.xml
+++ b/annotation/pom.xml
@@ -4,7 +4,7 @@
online.sharedtype
sharedtype-parent
- 0.14.0-SNAPSHOT
+ 0.13.1-SNAPSHOT
../pom.xml
diff --git a/build-tool-plugins/exec/pom.xml b/build-tool-plugins/exec/pom.xml
new file mode 100644
index 00000000..49083137
--- /dev/null
+++ b/build-tool-plugins/exec/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+ online.sharedtype
+ sharedtype-parent
+ 0.13.1-SNAPSHOT
+ ../../pom.xml
+
+
+ sharedtype-ap-exec
+ 0.13.1-SNAPSHOT
+ SharedType Annotation Processor Executor
+ Call javac to execute annotation processing.
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
+ org.junit-pioneer
+ junit-pioneer
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ org.mockito
+ mockito-junit-jupiter
+ test
+
+
+
+
+
+
+ maven-surefire-plugin
+
+
+ -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
+
+
+
+
+
+
diff --git a/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/AnnotationProcessorExecutor.java b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/AnnotationProcessorExecutor.java
new file mode 100644
index 00000000..e3b3ab61
--- /dev/null
+++ b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/AnnotationProcessorExecutor.java
@@ -0,0 +1,90 @@
+package online.sharedtype.exec.common;
+
+import javax.annotation.processing.Processor;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+
+/**
+ * Generic annotation processor executor. This module does not depend on sharedtype-ap.
+ * @see SharedTypeApCompilerOptions
+ * @author Cause Chung
+ */
+public final class AnnotationProcessorExecutor {
+ private static final String JAVA8_VERSION = "1.8";
+ private final Processor processor;
+ private final Logger log;
+ private final DependencyResolver dependencyResolver;
+
+ public AnnotationProcessorExecutor(Processor processor, Logger log, DependencyResolver dependencyResolver) {
+ this.processor = processor;
+ this.log = log;
+ this.dependencyResolver = dependencyResolver;
+ }
+
+ public void execute(Path projectBaseDir,
+ Path outputDir,
+ Iterable compileSourceRoots,
+ String sourceEncoding,
+ Iterable compilerOptions) throws Exception {
+ SimpleDiagnosticListener diagnosticListener = new SimpleDiagnosticListener(log, projectBaseDir);
+ JavaCompiler compiler = getJavaCompiler();
+
+ StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, getCharset(sourceEncoding));
+ try (SimpleLoggerWriter logger = new SimpleLoggerWriter(log)) {
+ if (Files.notExists(outputDir)) {
+ Files.createDirectories(outputDir);
+ }
+ fileManager.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(outputDir.toFile()));
+ fileManager.setLocation(StandardLocation.CLASS_PATH, dependencyResolver.getClasspathDependencies());
+ Iterable extends JavaFileObject> sources = fileManager.getJavaFileObjectsFromFiles(walkAllSourceFiles(compileSourceRoots));
+
+ JavaCompiler.CompilationTask task = compiler.getTask(logger, fileManager, diagnosticListener, compilerOptions, null, sources);
+ task.setProcessors(Collections.singleton(processor));
+ task.call();
+ }
+ }
+
+ private static List walkAllSourceFiles(Iterable compileSourceRoots) throws IOException {
+ SourceFileVisitor visitor = new SourceFileVisitor();
+ for (Path compileSourceRoot : compileSourceRoots) {
+ if (Files.isDirectory(compileSourceRoot)) {
+ Files.walkFileTree(compileSourceRoot, EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, visitor);
+ }
+ }
+ return visitor.getFiles();
+ }
+
+ private static JavaCompiler getJavaCompiler() throws Exception {
+ String javaVersion = System.getProperty("java.specification.version");
+ JavaCompiler compiler;
+ if (JAVA8_VERSION.equals(javaVersion)) {
+ Class> javacToolClass = Class.forName("com.sun.tools.javac.api.JavacTool");
+ compiler = (JavaCompiler) javacToolClass.getConstructor().newInstance();
+ } else {
+ compiler = ToolProvider.getSystemJavaCompiler();
+ }
+ if (compiler != null) {
+ return compiler;
+ }
+ throw new ClassNotFoundException("Java compiler not found, currently only compiler from jdk.compiler module is supported.");
+ }
+
+ private static Charset getCharset(String encoding) {
+ if (encoding != null) {
+ return Charset.forName(encoding);
+ }
+ return null;
+ }
+}
diff --git a/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/DependencyResolver.java b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/DependencyResolver.java
new file mode 100644
index 00000000..4618e103
--- /dev/null
+++ b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/DependencyResolver.java
@@ -0,0 +1,12 @@
+package online.sharedtype.exec.common;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Adapter interface for retrieving classpath dependencies.
+ * @author Cause Chung
+ */
+public interface DependencyResolver {
+ List getClasspathDependencies() throws Exception;
+}
diff --git a/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/Logger.java b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/Logger.java
new file mode 100644
index 00000000..36a34502
--- /dev/null
+++ b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/Logger.java
@@ -0,0 +1,11 @@
+package online.sharedtype.exec.common;
+
+/**
+ * Adapter for logging.
+ * @author Cause Chung
+ */
+public interface Logger {
+ void info(String message);
+ void warn(String message);
+ void error(String message);
+}
diff --git a/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SharedTypeApCompilerOptions.java b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SharedTypeApCompilerOptions.java
new file mode 100644
index 00000000..ea93564b
--- /dev/null
+++ b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SharedTypeApCompilerOptions.java
@@ -0,0 +1,37 @@
+package online.sharedtype.exec.common;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Assumed options for sharedtype annotation processor.
+ * @author Cause Chung
+ */
+public final class SharedTypeApCompilerOptions {
+ private static final List DEFAULT_COMPILER_OPTIONS = Arrays.asList("-proc:only", "-Asharedtype.enabled=true");
+ private static final String OPTION_PROPS_FILE_KEY = "-Asharedtype.propsFile=";
+ private final String propertyFile;
+
+ public SharedTypeApCompilerOptions(String propertyFile) {
+ this.propertyFile = propertyFile;
+ }
+ public SharedTypeApCompilerOptions(File propertyFile) {
+ this(propertyFile == null ? null : propertyFile.getAbsolutePath());
+ }
+
+ public List toList() {
+ List options = new ArrayList<>(DEFAULT_COMPILER_OPTIONS.size() + 1);
+ options.addAll(DEFAULT_COMPILER_OPTIONS);
+ if (propertyFile != null) {
+ if (Files.notExists(Paths.get(propertyFile))) {
+ throw new IllegalArgumentException("Property file not found: " + propertyFile);
+ }
+ options.add(OPTION_PROPS_FILE_KEY + propertyFile);
+ }
+ return options;
+ }
+}
diff --git a/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeDiagnosticListener.java b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SimpleDiagnosticListener.java
similarity index 71%
rename from maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeDiagnosticListener.java
rename to build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SimpleDiagnosticListener.java
index 7f0c372f..c077f7cf 100644
--- a/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeDiagnosticListener.java
+++ b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SimpleDiagnosticListener.java
@@ -1,8 +1,4 @@
-package online.sharedtype.maven;
-
-import com.google.common.annotations.VisibleForTesting;
-import online.sharedtype.processor.support.annotation.SideEffect;
-import org.apache.maven.plugin.logging.Log;
+package online.sharedtype.exec.common;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticListener;
@@ -10,10 +6,13 @@
import java.nio.file.Path;
import java.nio.file.Paths;
-final class SharedTypeDiagnosticListener implements DiagnosticListener {
- private final Log log;
+/**
+ * @author Cause Chung
+ */
+final class SimpleDiagnosticListener implements DiagnosticListener {
+ private final Logger log;
private final Path projectBaseDir;
- SharedTypeDiagnosticListener(Log log, Path projectBaseDir) {
+ SimpleDiagnosticListener(Logger log, Path projectBaseDir) {
this.log = log;
this.projectBaseDir = projectBaseDir;
}
@@ -40,8 +39,7 @@ public void report(Diagnostic extends JavaFileObject> diagnostic) {
}
}
- @VisibleForTesting
- void addSourceInfo(@SideEffect StringBuilder sb, Diagnostic extends JavaFileObject> diagnostic) {
+ void addSourceInfo(StringBuilder sb, Diagnostic extends JavaFileObject> diagnostic) {
if (diagnostic.getSource() == null) {
return;
}
diff --git a/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeLogger.java b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SimpleLoggerWriter.java
similarity index 81%
rename from maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeLogger.java
rename to build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SimpleLoggerWriter.java
index 838cb9f7..2db74ba3 100644
--- a/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeLogger.java
+++ b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SimpleLoggerWriter.java
@@ -1,14 +1,15 @@
-package online.sharedtype.maven;
-
-import org.apache.maven.plugin.logging.Log;
+package online.sharedtype.exec.common;
import java.io.Writer;
-final class SharedTypeLogger extends Writer {
- private final Log log;
+/**
+ * @author Cause Chung
+ */
+final class SimpleLoggerWriter extends Writer {
+ private final Logger log;
private final StringBuffer buffer = new StringBuffer();
- SharedTypeLogger(Log log) {
+ SimpleLoggerWriter(Logger log) {
this.log = log;
}
diff --git a/maven-plugin/src/main/java/online/sharedtype/maven/SourceFileVisitor.java b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SourceFileVisitor.java
similarity index 95%
rename from maven-plugin/src/main/java/online/sharedtype/maven/SourceFileVisitor.java
rename to build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SourceFileVisitor.java
index 586e2ce6..3ad87e58 100644
--- a/maven-plugin/src/main/java/online/sharedtype/maven/SourceFileVisitor.java
+++ b/build-tool-plugins/exec/src/main/java/online/sharedtype/exec/common/SourceFileVisitor.java
@@ -1,4 +1,4 @@
-package online.sharedtype.maven;
+package online.sharedtype.exec.common;
import java.io.File;
import java.nio.file.FileVisitResult;
diff --git a/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/AnnotationProcessorExecutorTest.java b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/AnnotationProcessorExecutorTest.java
new file mode 100644
index 00000000..1a346ea2
--- /dev/null
+++ b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/AnnotationProcessorExecutorTest.java
@@ -0,0 +1,70 @@
+package online.sharedtype.exec.common;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.io.TempDir;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.SourceVersion;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+final class AnnotationProcessorExecutorTest {
+ private @Mock Processor processor;
+ private @Mock Logger log;
+ private @Mock DependencyResolver dependencyResolver;
+ private AnnotationProcessorExecutor executor;
+ @TempDir
+ private Path projectBaseDir;
+ private Path outputDir;
+ private Path sourceDir;
+
+ @BeforeEach
+ void setup() throws Exception {
+ sourceDir = projectBaseDir.resolve("src/main/java");
+ Files.createDirectories(sourceDir);
+ outputDir = projectBaseDir.resolve("generated-sources");
+ copySampleSourceToSourceDir(sourceDir);
+ Files.createDirectory(outputDir);
+ executor = new AnnotationProcessorExecutor(processor, log, dependencyResolver);
+
+ when(processor.getSupportedSourceVersion()).thenReturn(SourceVersion.RELEASE_21);
+ when(processor.getSupportedAnnotationTypes()).thenReturn(Collections.singleton("online.sharedtype.exec.common.SampleAnno"));
+ when(processor.process(any(), any())).then(invocation -> {
+ RoundEnvironment env = invocation.getArgument(1);
+ if (env.processingOver()) {
+ Files.write(outputDir.resolve("out.txt"), "OK".getBytes());
+ }
+ return true;
+ });
+ }
+
+ @Test
+ void execute() throws Exception {
+ executor.execute(projectBaseDir, outputDir, List.of(sourceDir, Paths.get("not-exist")), "UTF-8", Collections.singleton("-proc:only"));
+ verify(processor).init(any());
+ verify(processor, times(2)).process(any(), any());
+ assertThat(Files.readString(outputDir.resolve("out.txt"))).isEqualTo("OK");
+ }
+
+ private static void copySampleSourceToSourceDir(Path sourceDir) throws Exception {
+ try (var input = AnnotationProcessorExecutor.class.getClassLoader().getResourceAsStream("SampleSource.java")) {
+ assertThat(input).isNotNull();
+ Files.copy(input, sourceDir.resolve("SampleSource.java"));
+ }
+ }
+}
diff --git a/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SampleAnno.java b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SampleAnno.java
new file mode 100644
index 00000000..8a1df31c
--- /dev/null
+++ b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SampleAnno.java
@@ -0,0 +1,4 @@
+package online.sharedtype.exec.common;
+
+public @interface SampleAnno {
+}
diff --git a/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SharedTypeApCompilerOptionsTest.java b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SharedTypeApCompilerOptionsTest.java
new file mode 100644
index 00000000..e7da75ae
--- /dev/null
+++ b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SharedTypeApCompilerOptionsTest.java
@@ -0,0 +1,7 @@
+package online.sharedtype.exec.common;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+final class SharedTypeApCompilerOptionsTest {
+
+}
diff --git a/maven-plugin/src/test/java/online/sharedtype/maven/SharedTypeDiagnosticListenerTest.java b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SharedTypeDiagnosticListenerTest.java
similarity index 86%
rename from maven-plugin/src/test/java/online/sharedtype/maven/SharedTypeDiagnosticListenerTest.java
rename to build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SharedTypeDiagnosticListenerTest.java
index 2d197761..1e60a0f5 100644
--- a/maven-plugin/src/test/java/online/sharedtype/maven/SharedTypeDiagnosticListenerTest.java
+++ b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SharedTypeDiagnosticListenerTest.java
@@ -1,6 +1,5 @@
-package online.sharedtype.maven;
+package online.sharedtype.exec.common;
-import org.apache.maven.plugin.logging.Log;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -9,7 +8,6 @@
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
-
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -19,15 +17,15 @@
@ExtendWith(MockitoExtension.class)
final class SharedTypeDiagnosticListenerTest {
private @Mock Diagnostic diagnostic;
- private @Mock Log log;
+ private @Mock Logger log;
private final Path baseDir = Paths.get("/test/project/dir");
- private SharedTypeDiagnosticListener listener;
+ private SimpleDiagnosticListener listener;
private @Mock JavaFileObject source;
@BeforeEach
void setup() {
- listener = new SharedTypeDiagnosticListener(log, baseDir);
+ listener = new SimpleDiagnosticListener(log, baseDir);
}
@Test
diff --git a/maven-plugin/src/test/java/online/sharedtype/maven/SharedTypeLoggerTest.java b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SimpleLoggerWriterTest.java
similarity index 78%
rename from maven-plugin/src/test/java/online/sharedtype/maven/SharedTypeLoggerTest.java
rename to build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SimpleLoggerWriterTest.java
index d4fb1d30..5c44b78a 100644
--- a/maven-plugin/src/test/java/online/sharedtype/maven/SharedTypeLoggerTest.java
+++ b/build-tool-plugins/exec/src/test/java/online/sharedtype/exec/common/SimpleLoggerWriterTest.java
@@ -1,6 +1,5 @@
-package online.sharedtype.maven;
+package online.sharedtype.exec.common;
-import org.apache.maven.plugin.logging.Log;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -13,14 +12,14 @@
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
-final class SharedTypeLoggerTest {
- private @Mock Log log;
- private SharedTypeLogger logger;
+final class SimpleLoggerWriterTest {
+ private @Mock Logger log;
+ private SimpleLoggerWriter logger;
private @Captor ArgumentCaptor messageCaptor;
@BeforeEach
void setup() {
- logger = new SharedTypeLogger(log);
+ logger = new SimpleLoggerWriter(log);
}
@Test
diff --git a/build-tool-plugins/exec/src/test/resources/SampleSource.java b/build-tool-plugins/exec/src/test/resources/SampleSource.java
new file mode 100644
index 00000000..b16451c0
--- /dev/null
+++ b/build-tool-plugins/exec/src/test/resources/SampleSource.java
@@ -0,0 +1,4 @@
+@online.sharedtype.exec.common.SampleAnno
+class A {
+
+}
diff --git a/build-tool-plugins/gradle-plugin/.gitattributes b/build-tool-plugins/gradle-plugin/.gitattributes
new file mode 100644
index 00000000..f91f6460
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/.gitattributes
@@ -0,0 +1,12 @@
+#
+# https://help.github.com/articles/dealing-with-line-endings/
+#
+# Linux start script should use lf
+/gradlew text eol=lf
+
+# These are Windows script files and should use crlf
+*.bat text eol=crlf
+
+# Binary files should be left untouched
+*.jar binary
+
diff --git a/build-tool-plugins/gradle-plugin/.gitignore b/build-tool-plugins/gradle-plugin/.gitignore
new file mode 100644
index 00000000..1b6985c0
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/.gitignore
@@ -0,0 +1,5 @@
+# Ignore Gradle project-specific cache directory
+.gradle
+
+# Ignore Gradle build output directory
+build
diff --git a/build-tool-plugins/gradle-plugin/build.gradle.kts b/build-tool-plugins/gradle-plugin/build.gradle.kts
new file mode 100644
index 00000000..63b1594f
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/build.gradle.kts
@@ -0,0 +1,70 @@
+plugins {
+ `java-gradle-plugin`
+ id("com.gradle.plugin-publish") version "1.2.1"
+ id("com.vanniktech.maven.publish") version "0.34.0" //currently only used for local publish, plugin is published bto Gradle Plugin Portal
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+group = "online.sharedtype"
+
+repositories {
+ mavenCentral()
+ mavenLocal()
+}
+
+dependencies {
+ implementation("online.sharedtype:sharedtype-ap:${project.version}")
+ implementation("online.sharedtype:sharedtype-ap-exec:${project.version}")
+ testImplementation("org.junit.jupiter:junit-jupiter:5.10.2")
+ testImplementation("org.assertj:assertj-core:3.25.3")
+ testRuntimeOnly("org.junit.platform:junit-platform-launcher")
+}
+
+gradlePlugin {
+ website = "https://github.com/SharedType/sharedtype"
+ vcsUrl = "https://github.com/SharedType/sharedtype.git"
+ plugins {
+ create("sharedtype") {
+ id = "online.sharedtype.sharedtype-gradle-plugin"
+ displayName = "SharedType Gradle Plugin"
+ description = "SharedType Gradle Plugin, SharedType is the tool to generate types from Java to target languages."
+ tags = listOf("sharedtype", "java", "annotation processing", "type generation")
+ implementationClass = "online.sharedtype.gradle.SharedtypeGradlePlugin"
+ }
+ }
+}
+
+tasks.named("test") {
+ useJUnitPlatform()
+}
+
+mavenPublishing {
+ pom {
+ name.set("SharedType Gradle Plugin")
+ description.set("SharedType Gradle Plugin, SharedType is the tool to generate types from Java to target languages.")
+ inceptionYear.set("2024")
+ url.set("https://github.com/SharedType/sharedtype")
+ licenses {
+ license {
+ name.set("CC BY 4.0")
+ url.set("https://creativecommons.org/licenses/by/4.0/deed.en")
+ distribution.set("https://creativecommons.org/licenses/by/4.0/deed.en")
+ }
+ }
+ developers {
+ developer {
+ id.set("cuzfrog")
+ name.set("Cause Chung")
+ url.set("https://github.com/cuzfrog")
+ }
+ }
+ scm {
+ url.set("https://github.com/SharedType/sharedtype")
+ connection.set("scm:git@github.com:SharedType/sharedtype.git")
+ }
+ }
+}
diff --git a/build-tool-plugins/gradle-plugin/gradle.properties b/build-tool-plugins/gradle-plugin/gradle.properties
new file mode 100644
index 00000000..feeb330f
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/gradle.properties
@@ -0,0 +1,3 @@
+version=0.13.1-SNAPSHOT
+mavenCentralPublishing=true
+signAllPublications=true
diff --git a/build-tool-plugins/gradle-plugin/gradle/wrapper/gradle-wrapper.jar b/build-tool-plugins/gradle-plugin/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..1b33c55b
Binary files /dev/null and b/build-tool-plugins/gradle-plugin/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/build-tool-plugins/gradle-plugin/gradle/wrapper/gradle-wrapper.properties b/build-tool-plugins/gradle-plugin/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..d4081da4
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/build-tool-plugins/gradle-plugin/gradlew b/build-tool-plugins/gradle-plugin/gradlew
new file mode 100755
index 00000000..23d15a93
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/gradlew
@@ -0,0 +1,251 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# 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.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+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.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH="\\\"\\\""
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/build-tool-plugins/gradle-plugin/it/build.gradle b/build-tool-plugins/gradle-plugin/it/build.gradle
new file mode 100644
index 00000000..3f853ae5
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/build.gradle
@@ -0,0 +1,24 @@
+plugins {
+ id "java"
+ id "online.sharedtype.sharedtype-gradle-plugin" version "${projectVersion}"
+}
+
+java {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+dependencies {
+ compileOnly "online.sharedtype:sharedtype:${projectVersion}"
+}
+
+repositories {
+ mavenLocal()
+}
+
+sharedtype {
+ propertyFile = project.file("sharedtype-test.properties")
+ properties = [
+ "sharedtype.typescript.custom-code-path": project.file("custom-code.ts").absolutePath
+ ]
+}
diff --git a/build-tool-plugins/gradle-plugin/it/custom-code.ts b/build-tool-plugins/gradle-plugin/it/custom-code.ts
new file mode 100644
index 00000000..79a2f9a9
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/custom-code.ts
@@ -0,0 +1 @@
+// test gradle plugin custom code
diff --git a/build-tool-plugins/gradle-plugin/it/degradlew b/build-tool-plugins/gradle-plugin/it/degradlew
new file mode 100755
index 00000000..0d28dee1
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/degradlew
@@ -0,0 +1,3 @@
+#!/bin/sh
+# port is 5005, can be seen from --info
+./gradlew -Dorg.gradle.debug=true --no-daemon "$@"
diff --git a/build-tool-plugins/gradle-plugin/it/gradle.properties b/build-tool-plugins/gradle-plugin/it/gradle.properties
new file mode 100644
index 00000000..e6e1a1cf
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/gradle.properties
@@ -0,0 +1 @@
+projectVersion=0.13.1-SNAPSHOT
diff --git a/build-tool-plugins/gradle-plugin/it/gradle/wrapper/gradle-wrapper.jar b/build-tool-plugins/gradle-plugin/it/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..033e24c4
Binary files /dev/null and b/build-tool-plugins/gradle-plugin/it/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/build-tool-plugins/gradle-plugin/it/gradle/wrapper/gradle-wrapper.properties b/build-tool-plugins/gradle-plugin/it/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..b36ccea5
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.6-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/build-tool-plugins/gradle-plugin/it/gradlew b/build-tool-plugins/gradle-plugin/it/gradlew
new file mode 100755
index 00000000..fcb6fca1
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/gradlew
@@ -0,0 +1,248 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (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
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/build-tool-plugins/gradle-plugin/it/settings.gradle b/build-tool-plugins/gradle-plugin/it/settings.gradle
new file mode 100644
index 00000000..05d25a1b
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/settings.gradle
@@ -0,0 +1,7 @@
+pluginManagement {
+ repositories {
+ mavenLocal()
+ }
+}
+
+rootProject.name="sharedtype-gradle-plugin-it"
diff --git a/build-tool-plugins/gradle-plugin/it/sharedtype-test.properties b/build-tool-plugins/gradle-plugin/it/sharedtype-test.properties
new file mode 100644
index 00000000..8d2dd8ab
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/sharedtype-test.properties
@@ -0,0 +1 @@
+rootProject.name = 'sharedtype-gradle-plugin-it'
diff --git a/build-tool-plugins/gradle-plugin/it/src/main/java/online/sharedtype/gradle/it/MyGradleClass.java b/build-tool-plugins/gradle-plugin/it/src/main/java/online/sharedtype/gradle/it/MyGradleClass.java
new file mode 100644
index 00000000..e4f9aa7a
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/it/src/main/java/online/sharedtype/gradle/it/MyGradleClass.java
@@ -0,0 +1,8 @@
+package online.sharedtype.gradle.it;
+
+import online.sharedtype.SharedType;
+
+@SharedType
+final class MyGradleClass {
+ private int value;
+}
diff --git a/build-tool-plugins/gradle-plugin/settings.gradle.kts b/build-tool-plugins/gradle-plugin/settings.gradle.kts
new file mode 100644
index 00000000..e2da201c
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/settings.gradle.kts
@@ -0,0 +1,8 @@
+/*
+ * This file was generated by the Gradle 'init' task.
+ *
+ * The settings file is used to specify which projects to include in your build.
+ * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.14.3/userguide/multi_project_builds.html in the Gradle documentation.
+ */
+
+rootProject.name = "sharedtype-gradle-plugin"
diff --git a/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/GradleLoggerAdaptor.java b/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/GradleLoggerAdaptor.java
new file mode 100644
index 00000000..b6d85fc4
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/GradleLoggerAdaptor.java
@@ -0,0 +1,22 @@
+package online.sharedtype.gradle;
+
+import org.slf4j.Logger;
+
+final class GradleLoggerAdaptor implements online.sharedtype.exec.common.Logger {
+ private final Logger delegate;
+ GradleLoggerAdaptor(Logger delegate) {
+ this.delegate = delegate;
+ }
+ @Override
+ public void info(String s) {
+ delegate.info(s);
+ }
+ @Override
+ public void warn(String s) {
+ delegate.warn(s);
+ }
+ @Override
+ public void error(String s) {
+ delegate.error(s);
+ }
+}
diff --git a/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeConfigExtension.java b/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeConfigExtension.java
new file mode 100644
index 00000000..9fdabdab
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeConfigExtension.java
@@ -0,0 +1,54 @@
+package online.sharedtype.gradle;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * This will enable lazy configuration so that the actual values will only be resolved when they are needed
+ * and can be reconfigured at any time during build configuration. See Gradle extension doc.
+ *
+ * @author Cause Chung
+ */
+public final class SharedtypeConfigExtension {
+ private static final Set DEFAULT_SRC_SET_NAME = Collections.singleton("main");
+
+ private File outputDirectory;
+ private File propertyFile;
+ private Map properties;
+ private String sourceEncoding;
+ private Set sourceSets = DEFAULT_SRC_SET_NAME;
+
+ public File getOutputDirectory() {
+ return outputDirectory;
+ }
+ public void setOutputDirectory(File outputDirectory) {
+ this.outputDirectory = outputDirectory;
+ }
+ public File getPropertyFile() {
+ return propertyFile;
+ }
+ public void setPropertyFile(File propertyFile) {
+ this.propertyFile = propertyFile;
+ }
+ public Map getProperties() {
+ return properties;
+ }
+ public void setProperties(Map properties) {
+ this.properties = properties;
+ }
+ public String getSourceEncoding() {
+ return sourceEncoding;
+ }
+ public void setSourceEncoding(String sourceEncoding) {
+ this.sourceEncoding = sourceEncoding;
+ }
+ public Set getSourceSets() {
+ return sourceSets;
+ }
+ public void setSourceSets(Set sourceSets) {
+ this.sourceSets = sourceSets;
+ }
+}
diff --git a/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeGenTask.java b/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeGenTask.java
new file mode 100644
index 00000000..cf8cb552
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeGenTask.java
@@ -0,0 +1,84 @@
+package online.sharedtype.gradle;
+
+import online.sharedtype.exec.common.AnnotationProcessorExecutor;
+import online.sharedtype.exec.common.SharedTypeApCompilerOptions;
+import online.sharedtype.processor.SharedTypeAnnotationProcessor;
+import online.sharedtype.processor.support.exception.SharedTypeException;
+import org.gradle.api.DefaultTask;
+import org.gradle.api.Project;
+import org.gradle.api.plugins.JavaPluginExtension;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.TaskAction;
+
+import javax.inject.Inject;
+import java.io.File;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author Cause Chung
+ */
+class SharedtypeGenTask extends DefaultTask {
+ static final String TASK_NAME = "stypeGen";
+ private static final String DEFAULT_OUTPUT_DIRECTORY = "generated";
+ private final Project project;
+ private SharedtypeConfigExtension extension;
+
+ @Inject
+ public SharedtypeGenTask(Project project) {
+ super();
+ this.project = project;
+ }
+ void setExtension(SharedtypeConfigExtension extension) {
+ this.extension = extension;
+ }
+
+ @TaskAction
+ void action() {
+ try {
+ execute();
+ } catch (Exception e) {
+ throw new SharedTypeException(String.format("Failed to execute task '%s'", TASK_NAME), e);
+ }
+ }
+
+ private void execute() throws Exception {
+ JavaPluginExtension javaPluginExtension = project.getExtensions().findByType(JavaPluginExtension.class);
+ if (javaPluginExtension == null) {
+ throw new UnsupportedOperationException("Could not find JavaPluginExtension, only Java projects are supported.");
+ }
+ List sourceSets = javaPluginExtension.getSourceSets().stream()
+ .filter(srcSet -> extension.getSourceSets().contains(srcSet.getName()))
+ .collect(Collectors.toList());
+ List sourceDirs = sourceSets.stream()
+ .flatMap(srcSet -> srcSet.getAllJava().getSrcDirs().stream())
+ .map(File::toPath)
+ .collect(Collectors.toList());
+ List classpathDependencies = sourceSets.stream()
+ .flatMap(srcSet -> srcSet.getCompileClasspath().getFiles().stream())
+ .collect(Collectors.toList());
+
+ SharedTypeAnnotationProcessor processor = new SharedTypeAnnotationProcessor();
+ processor.setUserProps(extension.getProperties());
+ AnnotationProcessorExecutor executor = new AnnotationProcessorExecutor(
+ processor,
+ new GradleLoggerAdaptor(project.getLogger()),
+ () -> classpathDependencies
+ );
+
+ executor.execute(
+ project.getProjectDir().toPath(),
+ resolveOutputDirectory().toPath(),
+ sourceDirs,
+ extension.getSourceEncoding(),
+ new SharedTypeApCompilerOptions(extension.getPropertyFile()).toList()
+ );
+ }
+
+ private File resolveOutputDirectory() {
+ return extension.getOutputDirectory() != null
+ ? extension.getOutputDirectory()
+ : project.getLayout().getBuildDirectory().dir(DEFAULT_OUTPUT_DIRECTORY).get().getAsFile();
+ }
+}
diff --git a/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeGradlePlugin.java b/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeGradlePlugin.java
new file mode 100644
index 00000000..c6debf44
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/src/main/java/online/sharedtype/gradle/SharedtypeGradlePlugin.java
@@ -0,0 +1,21 @@
+package online.sharedtype.gradle;
+
+import org.gradle.api.Project;
+import org.gradle.api.Plugin;
+
+/**
+ * @author Cause Chung
+ */
+final class SharedtypeGradlePlugin implements Plugin {
+ private static final String EXTENSION_METHOD_NAME = "sharedtype";
+
+ public void apply(Project project) {
+ SharedtypeConfigExtension extension = new SharedtypeConfigExtension();
+ project.getExtensions().add(EXTENSION_METHOD_NAME, extension);
+ project.getTasks().register(SharedtypeGenTask.TASK_NAME, SharedtypeGenTask.class, task -> {
+ task.setExtension(extension);
+ task.setDescription("Generate shared types in target languages. See https://github.com/SharedType/sharedtype");
+ task.setGroup("SharedType");
+ });
+ }
+}
diff --git a/build-tool-plugins/gradle-plugin/src/test/java/online/sharedtype/gradle/SharedtypeGradlePluginTest.java b/build-tool-plugins/gradle-plugin/src/test/java/online/sharedtype/gradle/SharedtypeGradlePluginTest.java
new file mode 100644
index 00000000..70439831
--- /dev/null
+++ b/build-tool-plugins/gradle-plugin/src/test/java/online/sharedtype/gradle/SharedtypeGradlePluginTest.java
@@ -0,0 +1,17 @@
+package online.sharedtype.gradle;
+
+import org.gradle.testfixtures.ProjectBuilder;
+import org.gradle.api.Project;
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+final class SharedtypeGradlePluginTest {
+ @Test
+ void pluginRegistersATask() {
+ Project project = ProjectBuilder.builder().build();
+ project.getPlugins().apply("online.sharedtype.sharedtype-gradle-plugin");
+
+ // Verify the result
+ assertNotNull(project.getTasks().findByName("stypeGen"));
+ }
+}
diff --git a/maven-plugin/it/.mvn/wrapper/maven-wrapper.properties b/build-tool-plugins/maven-plugin/it/.mvn/wrapper/maven-wrapper.properties
similarity index 100%
rename from maven-plugin/it/.mvn/wrapper/maven-wrapper.properties
rename to build-tool-plugins/maven-plugin/it/.mvn/wrapper/maven-wrapper.properties
diff --git a/maven-plugin/it/mvne b/build-tool-plugins/maven-plugin/it/demvnw
similarity index 100%
rename from maven-plugin/it/mvne
rename to build-tool-plugins/maven-plugin/it/demvnw
diff --git a/maven-plugin/it/mvnw b/build-tool-plugins/maven-plugin/it/mvnw
similarity index 100%
rename from maven-plugin/it/mvnw
rename to build-tool-plugins/maven-plugin/it/mvnw
diff --git a/maven-plugin/it/pom.xml b/build-tool-plugins/maven-plugin/it/pom.xml
similarity index 96%
rename from maven-plugin/it/pom.xml
rename to build-tool-plugins/maven-plugin/it/pom.xml
index 10c471ac..c577fe46 100644
--- a/maven-plugin/it/pom.xml
+++ b/build-tool-plugins/maven-plugin/it/pom.xml
@@ -5,8 +5,8 @@
online.sharedtype
sharedtype-parent
- 0.14.0-SNAPSHOT
- ../../pom.xml
+ 0.13.1-SNAPSHOT
+ ../../../pom.xml
sharedtype-maven-plugin-it
diff --git a/maven-plugin/it/sharedtype.properties b/build-tool-plugins/maven-plugin/it/sharedtype.properties
similarity index 100%
rename from maven-plugin/it/sharedtype.properties
rename to build-tool-plugins/maven-plugin/it/sharedtype.properties
diff --git a/maven-plugin/it/src/main/java/online/sharedtype/maven/it/MyClass.java b/build-tool-plugins/maven-plugin/it/src/main/java/online/sharedtype/maven/it/MyClass.java
similarity index 100%
rename from maven-plugin/it/src/main/java/online/sharedtype/maven/it/MyClass.java
rename to build-tool-plugins/maven-plugin/it/src/main/java/online/sharedtype/maven/it/MyClass.java
diff --git a/maven-plugin/it/src/test/java/online/sharedtype/maven/it/MavenPluginIntegrationTest.java b/build-tool-plugins/maven-plugin/it/src/test/java/online/sharedtype/maven/it/MavenPluginIntegrationTest.java
similarity index 100%
rename from maven-plugin/it/src/test/java/online/sharedtype/maven/it/MavenPluginIntegrationTest.java
rename to build-tool-plugins/maven-plugin/it/src/test/java/online/sharedtype/maven/it/MavenPluginIntegrationTest.java
diff --git a/maven-plugin/it/src/test/resources/expected-types.ts b/build-tool-plugins/maven-plugin/it/src/test/resources/expected-types.ts
similarity index 100%
rename from maven-plugin/it/src/test/resources/expected-types.ts
rename to build-tool-plugins/maven-plugin/it/src/test/resources/expected-types.ts
diff --git a/maven-plugin/pom.xml b/build-tool-plugins/maven-plugin/pom.xml
similarity index 87%
rename from maven-plugin/pom.xml
rename to build-tool-plugins/maven-plugin/pom.xml
index 8ae89b4f..e2cb8fa9 100644
--- a/maven-plugin/pom.xml
+++ b/build-tool-plugins/maven-plugin/pom.xml
@@ -5,12 +5,12 @@
online.sharedtype
sharedtype-parent
- 0.14.0-SNAPSHOT
- ../pom.xml
+ 0.13.1-SNAPSHOT
+ ../../pom.xml
sharedtype-maven-plugin
- 0.14.0-SNAPSHOT
+ 0.13.1-SNAPSHOT
maven-plugin
SharedType Maven Plugin
@@ -25,6 +25,11 @@
sharedtype-ap
${project.version}
+
+ ${project.groupId}
+ sharedtype-ap-exec
+ ${project.version}
+
org.apache.maven
maven-plugin-api
@@ -84,6 +89,14 @@
+
+ maven-surefire-plugin
+
+
+ -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
+
+
+
maven-clean-plugin
@@ -124,15 +137,6 @@
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
-
-
-
diff --git a/maven-plugin/src/main/java/online/sharedtype/maven/DependencyResolver.java b/build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/MavenDependencyResolver.java
similarity index 86%
rename from maven-plugin/src/main/java/online/sharedtype/maven/DependencyResolver.java
rename to build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/MavenDependencyResolver.java
index 67e3038f..e0f79c1d 100644
--- a/maven-plugin/src/main/java/online/sharedtype/maven/DependencyResolver.java
+++ b/build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/MavenDependencyResolver.java
@@ -1,5 +1,6 @@
package online.sharedtype.maven;
+import online.sharedtype.exec.common.DependencyResolver;
import org.apache.maven.RepositoryUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
@@ -17,18 +18,19 @@
/**
* @author Cause Chung
*/
-final class DependencyResolver {
+final class MavenDependencyResolver implements DependencyResolver {
private final RepositorySystem repositorySystem;
private final MavenSession session;
private final MavenProject project;
- DependencyResolver(RepositorySystem repositorySystem, MavenSession session, MavenProject project) {
+ MavenDependencyResolver(RepositorySystem repositorySystem, MavenSession session, MavenProject project) {
this.repositorySystem = repositorySystem;
this.session = session;
this.project = project;
}
- List getClasspathDependencies() throws MojoExecutionException {
+ @Override
+ public List getClasspathDependencies() throws Exception {
try {
ArtifactTypeRegistry artifactTypeRegistry =
session.getRepositorySession().getArtifactTypeRegistry();
diff --git a/build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/MavenLoggerAdaptor.java b/build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/MavenLoggerAdaptor.java
new file mode 100644
index 00000000..ba200956
--- /dev/null
+++ b/build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/MavenLoggerAdaptor.java
@@ -0,0 +1,24 @@
+package online.sharedtype.maven;
+
+import online.sharedtype.exec.common.Logger;
+import org.apache.maven.plugin.logging.Log;
+
+final class MavenLoggerAdaptor implements Logger {
+ private final Log log;
+ MavenLoggerAdaptor(Log log) {
+ this.log = log;
+ }
+
+ @Override
+ public void info(String message) {
+ log.info(message);
+ }
+ @Override
+ public void warn(String message) {
+ log.warn(message);
+ }
+ @Override
+ public void error(String message) {
+ log.error(message);
+ }
+}
diff --git a/build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeGenMojo.java b/build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeGenMojo.java
new file mode 100644
index 00000000..f64bc323
--- /dev/null
+++ b/build-tool-plugins/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeGenMojo.java
@@ -0,0 +1,78 @@
+package online.sharedtype.maven;
+
+import online.sharedtype.SharedType;
+import online.sharedtype.exec.common.AnnotationProcessorExecutor;
+import online.sharedtype.exec.common.SharedTypeApCompilerOptions;
+import online.sharedtype.processor.SharedTypeAnnotationProcessor;
+import online.sharedtype.processor.support.annotation.Nullable;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.eclipse.aether.RepositorySystem;
+
+import javax.inject.Inject;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Generate types from {@link SharedType} annotated classes.
+ * See SharedType for details.
+ *
+ * @author Cause Chung
+ */
+@Mojo(name = "gen")
+public final class SharedTypeGenMojo extends AbstractMojo {
+ private static final String PROP_PROJECT_SOURCE_ENCODING = "project.build.sourceEncoding";
+ private @Inject RepositorySystem repositorySystem;
+ private @Inject MavenSession session;
+ private @Inject MavenProject project;
+
+ /**
+ * Output directory for generated types. Defaults to '${project.build.directory}/generated-sources'.
+ */
+ @Parameter(defaultValue = "${project.build.directory}/generated-sources")
+ private String outputDirectory;
+
+ /**
+ * The path of file 'sharedtype.properties'. If not provided, default values will be used. If provided, the file must exist.
+ * User-provided properties will be checked in below order:
+ * 1. 'sharedtype.properties' file set by this config, 2. individual properties set by this plugin's 'properties' config, 3. System properties.
+ */
+ @Nullable
+ @Parameter
+ private String propertyFile;
+
+ /**
+ * Sharedtype properties. See doc for all the property entries. User-provided properties will be checked in below order:
+ * 1. 'sharedtype.properties' file, 2. this config, 3. System properties.
+ */
+ @Nullable
+ @Parameter
+ private Map properties;
+
+ @Override
+ public void execute() throws MojoExecutionException {
+ SharedTypeAnnotationProcessor processor = new SharedTypeAnnotationProcessor();
+ processor.setUserProps(properties);
+ AnnotationProcessorExecutor apExecutor = new AnnotationProcessorExecutor(
+ processor,
+ new MavenLoggerAdaptor(getLog()),
+ new MavenDependencyResolver(repositorySystem, session, project)
+ );
+ try {
+ apExecutor.execute(
+ project.getBasedir().toPath(),
+ Paths.get(outputDirectory),
+ project.getCompileSourceRoots().stream().map(Paths::get).collect(Collectors.toList()),
+ project.getProperties().getProperty(PROP_PROJECT_SOURCE_ENCODING),
+ new SharedTypeApCompilerOptions(propertyFile).toList()
+ );
+ } catch (Exception e) {
+ throw new MojoExecutionException(e);
+ }
+ }
+}
diff --git a/mvne b/demvnw
similarity index 100%
rename from mvne
rename to demvnw
diff --git a/doc/Development.md b/doc/Development.md
index 39cef68e..a62c2c67 100644
--- a/doc/Development.md
+++ b/doc/Development.md
@@ -14,14 +14,17 @@ Internal types also have javadoc for more information.
* `java17` uses symlink to reuse types in `java8` then does more type checks, e.g. for Java `record`.
* `client-test` contains target languages' tests respectively against generated code.
* `e2e` contains e2e json 2-way serialization and deserialization tests against target languages' http servers.
-* `maven-plugin` contains maven plugin for SharedType annotation, and `maven-plugin/it` contains integration tests for maven plugin.
+* `build-tool-plugins` contains Maven and Gradle plugin for SharedType annotation.
+ * `exec` contains generic annotation processor executor.
+ * `maven-plugin` and `maven-plugin/it` contains Maven plugin and integration tests.
+ * `gradle-plugin` and `gradle-plugin/it` contains Gradle plugin and integration tests.
Domain types are shared among processor and integration tests to reduce maven module count.
## Setup
-**Linux is assumed**. If you use Windows, you can use WSL with a remotely connected IDE. Windows 11 supports GUI app inside WSL.
+**Linux/macOS is assumed**. If you use Windows, you can use WSL with a remotely connected IDE. Windows 11 supports GUI app inside WSL.
-Setup Java env vars (>= Java17 for development), configure `JAVA17_HOME` to point to your Java installation:
+Setup Java env vars (>= Java21 for development), configure `JAVA21_HOME` to point to your Java installation:
```bash
. setenv
```
@@ -31,7 +34,7 @@ Optionally mount tmpfs to save your disk by:
```
Optionally setup `MVND_HOME` to use [maven daemon](https://github.com/apache/maven-mvnd) by `mvnd`
-Choose maven profiles in IDE accordingly as below.
+**Choose maven profiles in IDE accordingly as below.**
### Maven profiles
* `dev` and `release` - control whether to include test maven modules during build.
@@ -39,6 +42,8 @@ Choose maven profiles in IDE accordingly as below.
IDE may not able to properly resolve classes in `internal` folder for both modules.
Enable this profile to enable `it` modules in IDE, and disable it when developing against `processor` module.
* `it-no-jpms` and `it-jpms` - control whether to enable Java 9 Jigsaw module test in `it`. `it/java8` sources are reused to test on jdk9. Turn on `it-jpms` for IDE to correctly resolve `it/java8` classes.
+* `java8-jdk-tools-jar` - auto managed for adding `tools.jar` dependency for annotation processor.
+* `dev-build-tool` - controls build tool plugin modules.
## Development
### Run test
@@ -74,7 +79,7 @@ Style check:
```
Debug annotation processor by run maven build:
```bash
-./mvne
+./demvnw
```
Then attach your debugger on it. E.g. [IDEA run config](../.run/mvnDebug.run.xml).
@@ -87,7 +92,7 @@ Compile specific classes, **along with debug, this is useful for developing a sp
### Maven Plugin Development
Debug Maven plugin IT:
```bash
-mvnd -pl maven-plugin clean install && ./mvne -pl maven-plugin/it sharedtype:gen
+mvnd -pl maven-plugin clean install && ./demvnw -pl maven-plugin/it sharedtype:gen
```
## Coding Style Guide / Keep it simple
diff --git a/doc/Usage.md b/doc/Usage.md
index 9d9830b4..dca513ef 100644
--- a/doc/Usage.md
+++ b/doc/Usage.md
@@ -1,6 +1,7 @@
# User Guide
Menu:
* [Setup Maven](#Maven)
+* [Setup Gradle](#Gradle)
* [A simple example](#A-simple-example)
* [Configurations](#Configurations)
@@ -37,6 +38,26 @@ Add sharedtype dependency:
`sharedtype-maven-plugin` requires Maven 3.2.5+.
Annotation processing can also be setup and configured via `maven-compiler-plugin`, see [example](../it/pom.xml).
The advantage of using `sharedtype-maven-plugin` is that no need to execute other annotation processors if there are multiple.
+
+### Gradle
+Add sharedtype plugin and annotation dependency:
+```properties
+# gradle.properties
+sharedtypeVersion=
+```
+
+```groovy
+// build.gradle
+plugins {
+ id "online.sharedtype.sharedtype-gradle-plugin" version "${sharedtypeVersion}"
+}
+
+dependencies {
+ compileOnly "online.sharedtype:sharedtype:${sharedtypeVersion}"
+}
+```
+
+`sharedtype-gradle-plugin` requires Gradle 7.6+. For old gradle versions, can setup annotation processing.
## Usage
### A simple example
@@ -47,7 +68,9 @@ record User(String name, int age, String email) {}
```
Execute:
-* maven: `./mvnw stype:gen` (Why `stype`? Because it's easy to type while explicitly enough to remember.)
+* maven: `./mvnw stype:gen`
+* gradle: `./gradlew stypeGen`
+(Why `stype`? Because it's easy to type while explicitly enough to remember.)
By default, below code will be generated:
```typescript
@@ -63,6 +86,8 @@ export interface User {
#### Global options
By default, the file `sharedtype.properties` on current cmd path will be picked up.
You can customize the path:
+
+Maven:
```xml
@@ -71,7 +96,16 @@ You can customize the path:
```
+Gradle:
+```groovy
+sharedtype {
+ propertyFile = project.file("sharedtype.properties")
+}
+```
+
You can also specify individual properties:
+
+Maven:
```xml
@@ -82,6 +116,15 @@ You can also specify individual properties:
```
+Gradle:
+```groovy
+sharedtype {
+ properties = [
+ "sharedtype.typescript.custom-code-path": project.file("custom-code.ts").absolutePath
+ ]
+}
+```
+
See [Default Properties](../processor/src/main/resources/sharedtype-default.properties) for all property entries.
Execution goal `gen` can be bound to a Maven lifecycle phase.
diff --git a/e2e/pom.xml b/e2e/pom.xml
index 2b267e02..325ea010 100644
--- a/e2e/pom.xml
+++ b/e2e/pom.xml
@@ -4,7 +4,7 @@
online.sharedtype
sharedtype-parent
- 0.14.0-SNAPSHOT
+ 0.13.1-SNAPSHOT
../pom.xml
diff --git a/e2e/src/test/java/online/sharedtype/e2e/ObjectRemoteClientCaller.java b/e2e/src/test/java/online/sharedtype/e2e/ObjectRemoteClientCaller.java
index 4740278c..f20753b5 100644
--- a/e2e/src/test/java/online/sharedtype/e2e/ObjectRemoteClientCaller.java
+++ b/e2e/src/test/java/online/sharedtype/e2e/ObjectRemoteClientCaller.java
@@ -31,6 +31,7 @@ final class ObjectRemoteClientCaller {
objectMapper.registerModule(module);
}
+ @SuppressWarnings("unchecked")
T call(T t, SharedType.TargetType targetCodeType) throws Exception {
String simpleName = t.getClass().getSimpleName();
String json = objectMapper.writeValueAsString(t);
diff --git a/it/java17/pom.xml b/it/java17/pom.xml
index 6c1740ab..8d91e812 100644
--- a/it/java17/pom.xml
+++ b/it/java17/pom.xml
@@ -4,7 +4,7 @@
online.sharedtype
sharedtype-it-parent
- 0.14.0-SNAPSHOT
+ 0.13.1-SNAPSHOT
../pom.xml
diff --git a/it/java8/pom.xml b/it/java8/pom.xml
index 8df0d803..d326be26 100644
--- a/it/java8/pom.xml
+++ b/it/java8/pom.xml
@@ -4,7 +4,7 @@
online.sharedtype
sharedtype-it-parent
- 0.14.0-SNAPSHOT
+ 0.13.1-SNAPSHOT
../pom.xml
@@ -18,12 +18,6 @@
${java.version}
-
-
-
-
-
-
it-no-jpms
diff --git a/it/pom.xml b/it/pom.xml
index e597939c..c9c98b73 100644
--- a/it/pom.xml
+++ b/it/pom.xml
@@ -5,7 +5,7 @@
online.sharedtype
sharedtype-parent
- 0.14.0-SNAPSHOT
+ 0.13.1-SNAPSHOT
../pom.xml
diff --git a/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeGenMojo.java b/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeGenMojo.java
deleted file mode 100644
index 10f1d5b5..00000000
--- a/maven-plugin/src/main/java/online/sharedtype/maven/SharedTypeGenMojo.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package online.sharedtype.maven;
-
-import online.sharedtype.SharedType;
-import online.sharedtype.processor.SharedTypeAnnotationProcessor;
-import online.sharedtype.processor.support.annotation.Nullable;
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.Mojo;
-import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.project.MavenProject;
-import org.eclipse.aether.RepositorySystem;
-
-import javax.inject.Inject;
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.StandardLocation;
-import javax.tools.ToolProvider;
-import java.io.File;
-import java.nio.charset.Charset;
-import java.nio.charset.UnsupportedCharsetException;
-import java.nio.file.FileVisitOption;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Generate types from {@link SharedType} annotated classes.
- * See SharedType for details.
- *
- * @author Cause Chung
- */
-@Mojo(name = "gen")
-public final class SharedTypeGenMojo extends AbstractMojo {
- private static final String JAVA8_VERSION = "1.8";
- private static final List DEFAULT_COMPILER_OPTIONS = Arrays.asList("-proc:only", "-Asharedtype.enabled=true");
- private @Inject RepositorySystem repositorySystem;
-
- @Inject
- private MavenSession session;
-
- @Inject
- private MavenProject project;
-
- /**
- * Output directory for generated types. Defaults to '${project.build.directory}/generated-sources'.
- */
- @Parameter(defaultValue = "${project.build.directory}/generated-sources")
- private String outputDirectory;
-
- /**
- * The path of file 'sharedtype.properties'. If not provided, default values will be used. If provided, the file must exist.
- * User-provided properties will be checked in below order:
- * 1. 'sharedtype.properties' file set by this config, 2. individual properties set by this plugin's 'properties' config, 3. System properties.
- */
- @Nullable
- @Parameter
- private String propertyFile;
-
- /**
- * Sharedtype properties. See doc for all the property entries. User-provided properties will be checked in below order:
- * 1. 'sharedtype.properties' file, 2. this config, 3. System properties.
- */
- @Nullable
- @Parameter
- private Map properties;
-
- @Override
- public void execute() throws MojoExecutionException, MojoFailureException {
- SharedTypeDiagnosticListener diagnosticListener = new SharedTypeDiagnosticListener(getLog(), project.getBasedir().toPath());
- JavaCompiler compiler = getJavaCompiler();
-
- DependencyResolver dependencyResolver = new DependencyResolver(repositorySystem, session, project);
- StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, getCharset());
- try {
- Path outputDirPath = Paths.get(outputDirectory);
- if (Files.notExists(outputDirPath)) {
- Files.createDirectories(outputDirPath);
- }
- fileManager.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(outputDirPath.toFile()));
- fileManager.setLocation(StandardLocation.CLASS_PATH, dependencyResolver.getClasspathDependencies());
- } catch (Exception e) {
- throw new MojoExecutionException(e);
- }
- Iterable extends JavaFileObject> sources = fileManager.getJavaFileObjectsFromFiles(walkAllSourceFiles());
-
- try (SharedTypeLogger logger = new SharedTypeLogger(getLog())) {
- JavaCompiler.CompilationTask task = compiler.getTask(logger, fileManager, diagnosticListener, getCompilerOptions(), null, sources);
- SharedTypeAnnotationProcessor annotationProcessor = new SharedTypeAnnotationProcessor();
- annotationProcessor.setUserProps(properties);
- task.setProcessors(Collections.singleton(annotationProcessor));
- task.call();
- }
- }
-
- private List walkAllSourceFiles() throws MojoExecutionException {
- SourceFileVisitor visitor = new SourceFileVisitor();
- try {
- for (String compileSourceRoot : project.getCompileSourceRoots()) {
- Files.walkFileTree(Paths.get(compileSourceRoot), EnumSet.of(FileVisitOption.FOLLOW_LINKS), Integer.MAX_VALUE, visitor);
- }
- } catch (Exception e) {
- throw new MojoExecutionException(e);
- }
- return visitor.getFiles();
- }
-
- private List getCompilerOptions() throws MojoFailureException {
- List options = new ArrayList<>(DEFAULT_COMPILER_OPTIONS.size() + 1);
- options.addAll(DEFAULT_COMPILER_OPTIONS);
- if (propertyFile != null) {
- if (Files.notExists(Paths.get(propertyFile))) {
- throw new MojoFailureException("Property file not found: " + propertyFile);
- }
- options.add("-Asharedtype.propsFile=" + propertyFile);
- }
- return options;
- }
-
- private static JavaCompiler getJavaCompiler() throws MojoExecutionException {
- String javaVersion = System.getProperty("java.specification.version");
- JavaCompiler compiler;
- if (JAVA8_VERSION.equals(javaVersion)) {
- try {
- Class> javacToolClass = SharedTypeAnnotationProcessor.class.getClassLoader().loadClass("com.sun.tools.javac.api.JavacTool");
- compiler = (JavaCompiler) javacToolClass.getConstructor().newInstance();
- } catch (Exception e) {
- throw new MojoExecutionException("Failed to load JavaCompiler.", e);
- }
- } else {
- compiler = ToolProvider.getSystemJavaCompiler();
- }
- if (compiler != null) {
- return compiler;
- }
- throw new MojoExecutionException("Java compiler not found, currently only compiler from jdk.compiler module is supported.");
- }
-
- private Charset getCharset() throws MojoFailureException {
- String encoding = project.getProperties().getProperty("project.build.sourceEncoding");
- if (encoding != null) {
- try {
- return Charset.forName(encoding);
- } catch (UnsupportedCharsetException e) {
- throw new MojoFailureException("Invalid 'encoding' option: " + encoding, e);
- }
- }
- return null;
- }
-}
diff --git a/misc/release.sh b/misc/release.sh
index 552c2dd6..d2d04d9e 100755
--- a/misc/release.sh
+++ b/misc/release.sh
@@ -33,3 +33,9 @@ sed -i -E "s/[0-9]+\.[0-9\.\[0-9]+\.[0-9]+<\/sharedtype\.ve
NEW_VERSION="$(increment_version "$version" 1)-SNAPSHOT"
./mvnw versions:set -DgenerateBackupPoms=false -DnewVersion="$NEW_VERSION" --ntp -B
printf '%s' "$NEW_VERSION" > NEW_VERSION.cache
+
+# gradle plugin
+cd build-tool-plugins/gradle-plugin || exit 1
+./gradlew publishPlugins -Pversion="$version" -Pgradle.publish.key="$GRADLE_PUBLISH_KEY" -Pgradle.publish.secret="$GRADLE_PUBLISH_SECRET" --no-daemon
+sed -i -E "s/^version=.*\$/version=$version/g" build-tool-plugins/gradle-plugin/gradle.properties
+sed -i -E "s/^projectVersion=.*\$/projectVersion=$version/g" build-tool-plugins/gradle-plugin/it/gradle.properties
diff --git a/misc/setversion.sh b/misc/setversion.sh
index a45b2c53..5c82fa1f 100755
--- a/misc/setversion.sh
+++ b/misc/setversion.sh
@@ -1,3 +1,5 @@
#!/bin/bash
./mvnw versions:set -DgenerateBackupPoms=false -DnewVersion="$1" --ntp
+sed -i -E "s/^version=.*\$/version=$1/g" build-tool-plugins/gradle-plugin/gradle.properties
+sed -i -E "s/^projectVersion=.*\$/projectVersion=$1/g" build-tool-plugins/gradle-plugin/it/gradle.properties
diff --git a/mount-tmpfs.sh b/mount-tmpfs.sh
index b10e5bf8..e26e2593 100755
--- a/mount-tmpfs.sh
+++ b/mount-tmpfs.sh
@@ -22,8 +22,14 @@ mountTmpfs "$DIR/processor/target" 64M
mountTmpfs "$DIR/it/java17/target" 64M
mountTmpfs "$DIR/it/java8/target" 64M
mountTmpfs "$DIR/e2e/target" 64M
-mountTmpfs "$DIR/maven-plugin/target" 32M
-mountTmpfs "$DIR/maven-plugin/it/target" 16M
+mountTmpfs "$DIR/build-tool-plugins/exec/target" 32M
+mountTmpfs "$DIR/build-tool-plugins/maven-plugin/target" 32M
+mountTmpfs "$DIR/build-tool-plugins/maven-plugin/it/target" 16M
+mountTmpfs "$DIR/build-tool-plugins/gradle-plugin/.gradle" 32M
+mountTmpfs "$DIR/build-tool-plugins/gradle-plugin/build" 32M
+mountTmpfs "$DIR/build-tool-plugins/gradle-plugin/target" 32M
+mountTmpfs "$DIR/build-tool-plugins/gradle-plugin/it/.gradle" 16M
+mountTmpfs "$DIR/build-tool-plugins/gradle-plugin/it/build" 16M
mountTmpfs "$MAVEN_REPO_DIR" 64M
mountTmpfs "$DIR/client-test/rust/target" 512M
mountTmpfs "$DIR/client-test/typescript/dist" 32M
diff --git a/pom.xml b/pom.xml
index 886633ca..417f97bb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
online.sharedtype
sharedtype-parent
- 0.14.0-SNAPSHOT
+ 0.13.1-SNAPSHOT
pom
SharedType Parent
@@ -270,8 +270,6 @@
annotation
processor
it
- maven-plugin
- maven-plugin/it
@@ -280,12 +278,24 @@
e2e
+
+ dev-build-tool
+
+ true
+
+
+ build-tool-plugins/exec
+ build-tool-plugins/maven-plugin
+ build-tool-plugins/maven-plugin/it
+
+
release
annotation
processor
- maven-plugin
+ build-tool-plugins/exec
+ build-tool-plugins/maven-plugin
diff --git a/processor/pom.xml b/processor/pom.xml
index eb3f53b2..877313e6 100644
--- a/processor/pom.xml
+++ b/processor/pom.xml
@@ -5,7 +5,7 @@
online.sharedtype
sharedtype-parent
- 0.14.0-SNAPSHOT
+ 0.13.1-SNAPSHOT
../pom.xml
@@ -110,6 +110,14 @@
+
+ maven-surefire-plugin
+
+
+ -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
+
+
+
org.codehaus.mojo
build-helper-maven-plugin
@@ -177,15 +185,6 @@
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar
-
-
-
diff --git a/setenv b/setenv
index de1330f5..eeb5700a 100755
--- a/setenv
+++ b/setenv
@@ -1,25 +1,25 @@
#!/bin/bash
-version=$1
+javaVersion=$1
-if [ -z "$version" ];then
- version="21"
- echo "No version provided, use default jdk$version"
+if [ -z "$javaVersion" ];then
+ javaVersion="21"
+ echo "No javaVersion provided, use default jdk$javaVersion"
fi
-if [[ "$version" == "17" ]];then
+if [[ "$javaVersion" == "17" ]];then
export JAVA_HOME=$JAVA17_HOME
-elif [[ "$version" == "8" ]];then
+elif [[ "$javaVersion" == "8" ]];then
export JAVA_HOME=$JAVA8_HOME
-elif [[ "$version" == "11" ]];then
+elif [[ "$javaVersion" == "11" ]];then
export JAVA_HOME=$JAVA11_HOME
-elif [[ "$version" == "21" ]];then
+elif [[ "$javaVersion" == "21" ]];then
export JAVA_HOME=$JAVA21_HOME
else
- echo "Unsupported version $version"
+ echo "Unsupported javaVersion $javaVersion"
return
fi
-export MAVEN_OPTS="-Xmx512m -Xms512m"
+export MAVEN_OPTS="-Xmx512m -Xms128m"
export PATH=$JAVA_HOME/bin:$MVND_HOME/bin:$PATH
if [ -z "$MVND_HOME" ];then