From ac2c084290b49f434c8f4cc8318dd46ecbcd0da7 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 24 Nov 2023 21:28:37 +0100 Subject: [PATCH] js: add ability so refer to local files in source maps. Add copying of source files to Gradle plugin. --- .../information/SourceFileResolver.java | 22 +++++ .../information/SourceMapsWriter.java | 19 ++++- samples/hello/build.gradle.kts | 4 + .../teavm/tooling/TeaVMSourceFilePolicy.java | 22 +++++ .../java/org/teavm/tooling/TeaVMTool.java | 71 ++++++++++++---- .../teavm/tooling/builder/BuildStrategy.java | 4 + .../builder/InProcessBuildStrategy.java | 17 +++- .../tooling/builder/RemoteBuildStrategy.java | 10 ++- .../org/teavm/tooling/daemon/BuildDaemon.java | 5 +- .../tooling/daemon/RemoteBuildRequest.java | 3 +- .../sources/DirectorySourceFileProvider.java | 7 +- .../sources/JarSourceFileProvider.java | 5 ++ .../teavm/tooling/sources/SourceFileInfo.java | 3 + .../java/org/teavm/gradle/TeaVMPlugin.java | 84 ++++++++++++++++--- .../teavm/gradle/api/SourceFilePolicy.java | 22 +++++ .../gradle/api/TeaVMJSConfiguration.java | 2 + .../gradle/tasks/GenerateJavaScriptTask.java | 32 +++++++ .../org/teavm/maven/TeaVMCompileMojo.java | 5 +- 18 files changed, 297 insertions(+), 40 deletions(-) create mode 100644 core/src/main/java/org/teavm/debugging/information/SourceFileResolver.java create mode 100644 tools/core/src/main/java/org/teavm/tooling/TeaVMSourceFilePolicy.java create mode 100644 tools/gradle/src/main/java/org/teavm/gradle/api/SourceFilePolicy.java diff --git a/core/src/main/java/org/teavm/debugging/information/SourceFileResolver.java b/core/src/main/java/org/teavm/debugging/information/SourceFileResolver.java new file mode 100644 index 000000000..cec8d2603 --- /dev/null +++ b/core/src/main/java/org/teavm/debugging/information/SourceFileResolver.java @@ -0,0 +1,22 @@ +/* + * Copyright 2023 Alexey Andreev. + * + * 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 + * + * http://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. + */ +package org.teavm.debugging.information; + +import java.io.IOException; + +public interface SourceFileResolver { + String resolveFile(String fileName) throws IOException; +} diff --git a/core/src/main/java/org/teavm/debugging/information/SourceMapsWriter.java b/core/src/main/java/org/teavm/debugging/information/SourceMapsWriter.java index fc3ee7761..0f843a1e4 100644 --- a/core/src/main/java/org/teavm/debugging/information/SourceMapsWriter.java +++ b/core/src/main/java/org/teavm/debugging/information/SourceMapsWriter.java @@ -17,9 +17,11 @@ package org.teavm.debugging.information; import java.io.IOException; import java.io.Writer; +import java.util.ArrayList; +import java.util.List; import org.teavm.common.JsonUtil; -class SourceMapsWriter { +public class SourceMapsWriter { private static final String BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; private Writer output; private int lastLine; @@ -27,11 +29,16 @@ class SourceMapsWriter { private int lastSourceLine; private int lastSourceFile; private boolean first; + private List sourceFileResolvers = new ArrayList<>(); public SourceMapsWriter(Writer output) { this.output = output; } + public void addSourceResolver(SourceFileResolver sourceFileResolver) { + sourceFileResolvers.add(sourceFileResolver); + } + public void write(String generatedFile, String sourceRoot, DebugInformation debugInfo) throws IOException { output.write("{\"version\":3"); output.write(",\"file\":\""); @@ -46,7 +53,15 @@ class SourceMapsWriter { output.write(','); } output.write("\""); - JsonUtil.writeEscapedString(output, debugInfo.fileNames[i]); + var name = debugInfo.fileNames[i]; + for (var resolver : sourceFileResolvers) { + var resolvedName = resolver.resolveFile(name); + if (resolvedName != null) { + name = resolvedName; + break; + } + } + JsonUtil.writeEscapedString(output, name); output.write("\""); } output.write("]"); diff --git a/samples/hello/build.gradle.kts b/samples/hello/build.gradle.kts index bd02656c5..725f36003 100644 --- a/samples/hello/build.gradle.kts +++ b/samples/hello/build.gradle.kts @@ -1,3 +1,5 @@ +import org.teavm.gradle.api.SourceFilePolicy + /* * Copyright 2023 Alexey Andreev. * @@ -28,4 +30,6 @@ dependencies { teavm.js { addedToWebApp = true mainClass = "org.teavm.samples.hello.Client" + sourceMap = true + sourceFilePolicy = SourceFilePolicy.LINK_LOCAL_FILES } diff --git a/tools/core/src/main/java/org/teavm/tooling/TeaVMSourceFilePolicy.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMSourceFilePolicy.java new file mode 100644 index 000000000..b038cd593 --- /dev/null +++ b/tools/core/src/main/java/org/teavm/tooling/TeaVMSourceFilePolicy.java @@ -0,0 +1,22 @@ +/* + * Copyright 2023 Alexey Andreev. + * + * 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 + * + * http://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. + */ +package org.teavm.tooling; + +public enum TeaVMSourceFilePolicy { + DO_NOTHING, + COPY, + LINK_LOCAL_FILES +} diff --git a/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java index 7c4265883..8a764ae01 100644 --- a/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java +++ b/tools/core/src/main/java/org/teavm/tooling/TeaVMTool.java @@ -49,6 +49,7 @@ import org.teavm.cache.EmptyProgramCache; import org.teavm.cache.FileSymbolTable; import org.teavm.debugging.information.DebugInformation; import org.teavm.debugging.information.DebugInformationBuilder; +import org.teavm.debugging.information.SourceMapsWriter; import org.teavm.dependency.DependencyInfo; import org.teavm.dependency.FastDependencyAnalyzer; import org.teavm.dependency.PreciseDependencyAnalyzer; @@ -61,7 +62,6 @@ import org.teavm.model.ReferenceCache; import org.teavm.model.transformation.AssertionRemoval; import org.teavm.parsing.ClasspathClassHolderSource; import org.teavm.tooling.sources.SourceFileProvider; -import org.teavm.tooling.sources.SourceFilesCopier; import org.teavm.vm.BuildTarget; import org.teavm.vm.DirectoryBuildTarget; import org.teavm.vm.TeaVM; @@ -81,7 +81,7 @@ public class TeaVMTool { private Properties properties = new Properties(); private boolean debugInformationGenerated; private boolean sourceMapsFileGenerated; - private boolean sourceFilesCopied; + private TeaVMSourceFilePolicy sourceFilePolicy = TeaVMSourceFilePolicy.DO_NOTHING; private boolean incremental; private File cacheDirectory = new File("./teavm-cache"); private List transformers = new ArrayList<>(); @@ -177,12 +177,23 @@ public class TeaVMTool { this.sourceMapsFileGenerated = sourceMapsFileGenerated; } + @Deprecated public boolean isSourceFilesCopied() { - return sourceFilesCopied; + return sourceFilePolicy == TeaVMSourceFilePolicy.COPY; } + @Deprecated public void setSourceFilesCopied(boolean sourceFilesCopied) { - this.sourceFilesCopied = sourceFilesCopied; + if (isSourceFilesCopied() == sourceFilesCopied) { + return; + } + sourceFilePolicy = sourceFilesCopied + ? TeaVMSourceFilePolicy.COPY + : TeaVMSourceFilePolicy.DO_NOTHING; + } + + public void setSourceFilePolicy(TeaVMSourceFilePolicy sourceFilePolicy) { + this.sourceFilePolicy = sourceFilePolicy; } public Properties getProperties() { @@ -527,14 +538,48 @@ public class TeaVMTool { File sourceMapsFile = new File(targetDirectory, sourceMapsFileName); try (Writer sourceMapsOut = new OutputStreamWriter(new FileOutputStream(sourceMapsFile), StandardCharsets.UTF_8)) { - debugInfo.writeAsSourceMaps(sourceMapsOut, "src", getResolvedTargetFileName()); + writeSourceMaps(sourceMapsOut, debugInfo); } generatedFiles.add(sourceMapsFile); log.info("Source maps successfully written"); } - if (sourceFilesCopied) { - copySourceFiles(); - log.info("Source files successfully written"); + } + + private void writeSourceMaps(Writer out, DebugInformation debugInfo) throws IOException { + var sourceMapWriter = new SourceMapsWriter(out); + for (var provider : sourceFileProviders) { + provider.open(); + } + + var targetDir = new File(targetDirectory, "src"); + if (sourceFilePolicy != TeaVMSourceFilePolicy.DO_NOTHING) { + sourceMapWriter.addSourceResolver(fileName -> { + for (var provider : sourceFileProviders) { + var sourceFile = provider.getSourceFile(fileName); + if (sourceFile != null) { + if (sourceFilePolicy == TeaVMSourceFilePolicy.COPY || sourceFile.getFile() == null) { + var outputFile = new File(targetDir, fileName); + outputFile.getParentFile().mkdirs(); + try (var input = sourceFile.open(); + var output = new FileOutputStream(outputFile)) { + input.transferTo(output); + } + if (sourceFilePolicy == TeaVMSourceFilePolicy.LINK_LOCAL_FILES) { + return "file://" + outputFile.getCanonicalPath(); + } + } else { + return "file://" + sourceFile.getFile().getCanonicalPath(); + } + break; + } + } + return null; + }); + } + sourceMapWriter.write(getResolvedTargetFileName(), "src", debugInfo); + + for (var provider : sourceFileProviders) { + provider.close(); } } @@ -554,16 +599,6 @@ public class TeaVMTool { log.info("Methods compiled: " + methodCount); } - private void copySourceFiles() { - if (vm.getWrittenClasses() == null) { - return; - } - SourceFilesCopier copier = new SourceFilesCopier(sourceFileProviders, generatedFiles::add); - copier.addClasses(vm.getWrittenClasses()); - copier.setLog(log); - copier.copy(new File(targetDirectory, "src")); - } - private List resolveTransformers() { List transformerInstances = new ArrayList<>(); if (transformers == null) { diff --git a/tools/core/src/main/java/org/teavm/tooling/builder/BuildStrategy.java b/tools/core/src/main/java/org/teavm/tooling/builder/BuildStrategy.java index da529e48d..f1ade6f28 100644 --- a/tools/core/src/main/java/org/teavm/tooling/builder/BuildStrategy.java +++ b/tools/core/src/main/java/org/teavm/tooling/builder/BuildStrategy.java @@ -18,6 +18,7 @@ package org.teavm.tooling.builder; import java.util.List; import java.util.Properties; import org.teavm.backend.wasm.render.WasmBinaryVersion; +import org.teavm.tooling.TeaVMSourceFilePolicy; import org.teavm.tooling.TeaVMTargetType; import org.teavm.tooling.TeaVMToolLog; import org.teavm.vm.TeaVMOptimizationLevel; @@ -46,8 +47,11 @@ public interface BuildStrategy { void setDebugInformationGenerated(boolean debugInformationGenerated); + @Deprecated void setSourceFilesCopied(boolean sourceFilesCopied); + void setSourceFilePolicy(TeaVMSourceFilePolicy sourceFilePolicy); + void setProgressListener(TeaVMProgressListener progressListener); void setIncremental(boolean incremental); diff --git a/tools/core/src/main/java/org/teavm/tooling/builder/InProcessBuildStrategy.java b/tools/core/src/main/java/org/teavm/tooling/builder/InProcessBuildStrategy.java index f221d0ef3..adf192b81 100644 --- a/tools/core/src/main/java/org/teavm/tooling/builder/InProcessBuildStrategy.java +++ b/tools/core/src/main/java/org/teavm/tooling/builder/InProcessBuildStrategy.java @@ -30,6 +30,7 @@ import org.teavm.backend.wasm.render.WasmBinaryVersion; import org.teavm.callgraph.CallGraph; import org.teavm.diagnostics.ProblemProvider; import org.teavm.tooling.EmptyTeaVMToolLog; +import org.teavm.tooling.TeaVMSourceFilePolicy; import org.teavm.tooling.TeaVMTargetType; import org.teavm.tooling.TeaVMTool; import org.teavm.tooling.TeaVMToolException; @@ -55,7 +56,7 @@ public class InProcessBuildStrategy implements BuildStrategy { private boolean strict; private boolean sourceMapsFileGenerated; private boolean debugInformationGenerated; - private boolean sourceFilesCopied; + private TeaVMSourceFilePolicy sourceMapsSourcePolicy; private String[] transformers = new String[0]; private String[] classesToPreserve = new String[0]; private WasmBinaryVersion wasmVersion = WasmBinaryVersion.V_0x1; @@ -122,7 +123,17 @@ public class InProcessBuildStrategy implements BuildStrategy { @Override public void setSourceFilesCopied(boolean sourceFilesCopied) { - this.sourceFilesCopied = sourceFilesCopied; + if ((sourceMapsSourcePolicy == TeaVMSourceFilePolicy.COPY) == sourceFilesCopied) { + return; + } + sourceMapsSourcePolicy = sourceFilesCopied + ? TeaVMSourceFilePolicy.COPY + : TeaVMSourceFilePolicy.DO_NOTHING; + } + + @Override + public void setSourceFilePolicy(TeaVMSourceFilePolicy sourceFilePolicy) { + this.sourceMapsSourcePolicy = sourceFilePolicy; } @Override @@ -233,7 +244,7 @@ public class InProcessBuildStrategy implements BuildStrategy { tool.setSourceMapsFileGenerated(sourceMapsFileGenerated); tool.setDebugInformationGenerated(debugInformationGenerated); - tool.setSourceFilesCopied(sourceFilesCopied); + tool.setSourceFilePolicy(sourceMapsSourcePolicy); tool.setObfuscated(obfuscated); tool.setStrict(strict); diff --git a/tools/core/src/main/java/org/teavm/tooling/builder/RemoteBuildStrategy.java b/tools/core/src/main/java/org/teavm/tooling/builder/RemoteBuildStrategy.java index ffea98731..9c42307c9 100644 --- a/tools/core/src/main/java/org/teavm/tooling/builder/RemoteBuildStrategy.java +++ b/tools/core/src/main/java/org/teavm/tooling/builder/RemoteBuildStrategy.java @@ -25,6 +25,7 @@ import org.teavm.callgraph.CallGraph; import org.teavm.diagnostics.Problem; import org.teavm.diagnostics.ProblemProvider; import org.teavm.tooling.EmptyTeaVMToolLog; +import org.teavm.tooling.TeaVMSourceFilePolicy; import org.teavm.tooling.TeaVMTargetType; import org.teavm.tooling.TeaVMToolLog; import org.teavm.tooling.daemon.RemoteBuildCallback; @@ -100,7 +101,14 @@ public class RemoteBuildStrategy implements BuildStrategy { @Override public void setSourceFilesCopied(boolean sourceFilesCopied) { - request.sourceFilesCopied = sourceFilesCopied; + request.sourceFilePolicy = sourceFilesCopied + ? TeaVMSourceFilePolicy.COPY.name() + : TeaVMSourceFilePolicy.DO_NOTHING.name(); + } + + @Override + public void setSourceFilePolicy(TeaVMSourceFilePolicy sourceFilePolicy) { + request.sourceFilePolicy = sourceFilePolicy.name(); } @Override diff --git a/tools/core/src/main/java/org/teavm/tooling/daemon/BuildDaemon.java b/tools/core/src/main/java/org/teavm/tooling/daemon/BuildDaemon.java index 345fd8f98..9ce2b78f1 100644 --- a/tools/core/src/main/java/org/teavm/tooling/daemon/BuildDaemon.java +++ b/tools/core/src/main/java/org/teavm/tooling/daemon/BuildDaemon.java @@ -37,6 +37,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; +import org.teavm.tooling.TeaVMSourceFilePolicy; import org.teavm.tooling.TeaVMTool; import org.teavm.tooling.TeaVMToolException; import org.teavm.tooling.sources.DirectorySourceFileProvider; @@ -147,7 +148,9 @@ public class BuildDaemon extends UnicastRemoteObject implements RemoteBuildServi tool.setSourceMapsFileGenerated(request.sourceMapsFileGenerated); tool.setDebugInformationGenerated(request.debugInformationGenerated); - tool.setSourceFilesCopied(request.sourceFilesCopied); + if (request.sourceFilePolicy != null) { + tool.setSourceFilePolicy(TeaVMSourceFilePolicy.valueOf(request.sourceFilePolicy)); + } if (request.properties != null) { tool.getProperties().putAll(request.properties); } diff --git a/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildRequest.java b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildRequest.java index b3dac65c8..0c87169af 100644 --- a/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildRequest.java +++ b/tools/core/src/main/java/org/teavm/tooling/daemon/RemoteBuildRequest.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.teavm.backend.wasm.render.WasmBinaryVersion; +import org.teavm.tooling.TeaVMSourceFilePolicy; import org.teavm.tooling.TeaVMTargetType; import org.teavm.vm.TeaVMOptimizationLevel; @@ -36,7 +37,7 @@ public class RemoteBuildRequest implements Serializable { public String tagetFileName = ""; public boolean sourceMapsFileGenerated; public boolean debugInformationGenerated; - public boolean sourceFilesCopied; + public String sourceFilePolicy = TeaVMSourceFilePolicy.DO_NOTHING.name(); public boolean incremental; public String cacheDirectory; public boolean obfuscated; diff --git a/tools/core/src/main/java/org/teavm/tooling/sources/DirectorySourceFileProvider.java b/tools/core/src/main/java/org/teavm/tooling/sources/DirectorySourceFileProvider.java index 1d19ce942..244521536 100644 --- a/tools/core/src/main/java/org/teavm/tooling/sources/DirectorySourceFileProvider.java +++ b/tools/core/src/main/java/org/teavm/tooling/sources/DirectorySourceFileProvider.java @@ -38,7 +38,7 @@ public class DirectorySourceFileProvider implements SourceFileProvider { @Override public SourceFileInfo getSourceFile(String fullPath) throws IOException { File file = new File(baseDirectory, fullPath); - return file.exists() ? new DirectorySourceFile(file) : null; + return file.isFile() ? new DirectorySourceFile(file) : null; } static class DirectorySourceFile implements SourceFileInfo { @@ -57,5 +57,10 @@ public class DirectorySourceFileProvider implements SourceFileProvider { public InputStream open() throws IOException { return new FileInputStream(file); } + + @Override + public File getFile() { + return file; + } } } diff --git a/tools/core/src/main/java/org/teavm/tooling/sources/JarSourceFileProvider.java b/tools/core/src/main/java/org/teavm/tooling/sources/JarSourceFileProvider.java index 7d474f10e..0921f09ac 100644 --- a/tools/core/src/main/java/org/teavm/tooling/sources/JarSourceFileProvider.java +++ b/tools/core/src/main/java/org/teavm/tooling/sources/JarSourceFileProvider.java @@ -80,5 +80,10 @@ public class JarSourceFileProvider implements SourceFileProvider { public InputStream open() throws IOException { return file.getInputStream(entry); } + + @Override + public File getFile() { + return null; + } } } diff --git a/tools/core/src/main/java/org/teavm/tooling/sources/SourceFileInfo.java b/tools/core/src/main/java/org/teavm/tooling/sources/SourceFileInfo.java index e71c453b5..0ea5023f2 100644 --- a/tools/core/src/main/java/org/teavm/tooling/sources/SourceFileInfo.java +++ b/tools/core/src/main/java/org/teavm/tooling/sources/SourceFileInfo.java @@ -15,6 +15,7 @@ */ package org.teavm.tooling.sources; +import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -22,4 +23,6 @@ public interface SourceFileInfo { long lastModified(); InputStream open() throws IOException; + + File getFile(); } diff --git a/tools/gradle/src/main/java/org/teavm/gradle/TeaVMPlugin.java b/tools/gradle/src/main/java/org/teavm/gradle/TeaVMPlugin.java index d97e2440c..8169badc3 100644 --- a/tools/gradle/src/main/java/org/teavm/gradle/TeaVMPlugin.java +++ b/tools/gradle/src/main/java/org/teavm/gradle/TeaVMPlugin.java @@ -16,10 +16,16 @@ package org.teavm.gradle; import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import javax.inject.Inject; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; +import org.gradle.api.artifacts.component.ModuleComponentIdentifier; +import org.gradle.api.artifacts.component.ProjectComponentIdentifier; +import org.gradle.api.artifacts.result.ResolvedDependencyResult; import org.gradle.api.file.DuplicatesStrategy; import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.JavaPlugin; @@ -83,15 +89,17 @@ public class TeaVMPlugin implements Plugin { } private void registerSourceSet(Project project) { - var sourceSets = project.getExtensions().getByType(SourceSetContainer.class); - var sourceSet = sourceSets.create(SOURCE_SET_NAME); - var main = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput(); - sourceSet.setRuntimeClasspath(sourceSet.getRuntimeClasspath().plus(main) - .plus(project.getConfigurations().getByName(CLASSPATH_CONFIGURATION_NAME))); - sourceSet.setCompileClasspath(sourceSet.getCompileClasspath().plus(main) - .plus(project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME))); - sourceSet.java(java -> { }); - project.getDependencies().add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, sourceSet.getOutput()); + var sourceSets = project.getExtensions().findByType(SourceSetContainer.class); + if (sourceSets != null) { + var sourceSet = sourceSets.create(SOURCE_SET_NAME); + var main = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput(); + sourceSet.setRuntimeClasspath(sourceSet.getRuntimeClasspath().plus(main) + .plus(project.getConfigurations().getByName(CLASSPATH_CONFIGURATION_NAME))); + sourceSet.setCompileClasspath(sourceSet.getCompileClasspath().plus(main) + .plus(project.getConfigurations().getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME))); + sourceSet.java(java -> { }); + project.getDependencies().add(JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME, sourceSet.getOutput()); + } } private void registerTasks(Project project) { @@ -113,9 +121,59 @@ public class TeaVMPlugin implements Plugin { task.getTargetFileName().convention(js.getTargetFileName()); task.getStrict().convention(js.getStrict()); task.getEntryPointName().convention(js.getEntryPointName()); + task.getSourceFilePolicy().convention(js.getSourceFilePolicy()); + + task.getSourceFiles().from(project.provider(() -> { + var result = new ArrayList(); + addSourceDirs(project, result); + return result; + })); + task.getSourceFiles().from(project.provider(() -> { + var dependencies = project.getConfigurations() + .getByName(JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME) + .getIncoming() + .getResolutionResult() + .getAllDependencies(); + + var result = new ArrayList(); + for (var dependencyResult : dependencies) { + if (!(dependencyResult instanceof ResolvedDependencyResult)) { + continue; + } + var id = ((ResolvedDependencyResult) dependencyResult).getSelected().getId(); + if (id instanceof ProjectComponentIdentifier) { + var path = ((ProjectComponentIdentifier) id).getProjectPath(); + var refProject = project.getRootProject().findProject(path); + if (refProject != null) { + addSourceDirs(refProject, result); + } + } else if (id instanceof ModuleComponentIdentifier) { + var moduleId = (ModuleComponentIdentifier) id; + var sourcesDep = project.getDependencies().create(Map.of( + "group", moduleId.getGroup(), + "name", moduleId.getModuleIdentifier().getName(), + "version", moduleId.getVersion(), + "classifier", "sources" + )); + var tmpConfig = project.getConfigurations().detachedConfiguration(sourcesDep); + tmpConfig.setTransitive(false); + result.addAll(tmpConfig.getFiles()); + } + } + return result; + })); }); } + private void addSourceDirs(Project project, List result) { + var sourceSets = project.getExtensions().findByType(SourceSetContainer.class); + if (sourceSets != null) { + for (var sourceSet : sourceSets) { + result.addAll(sourceSet.getAllJava().getSourceDirectories().getFiles()); + } + } + } + private void registerWasmTask(Project project, Configuration configuration) { var extension = project.getExtensions().getByType(TeaVMExtension.class); project.getTasks().create(WASM_TASK_NAME, GenerateWasmTask.class, task -> { @@ -202,8 +260,10 @@ public class TeaVMPlugin implements Plugin { var project = task.getProject(); - var sourceSets = project.getExtensions().getByType(SourceSetContainer.class); - task.getClasspath().from(sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput()); - task.getClasspath().from(sourceSets.getByName(SOURCE_SET_NAME).getOutput()); + var sourceSets = project.getExtensions().findByType(SourceSetContainer.class); + if (sourceSets != null) { + task.getClasspath().from(sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput()); + task.getClasspath().from(sourceSets.getByName(SOURCE_SET_NAME).getOutput()); + } } } diff --git a/tools/gradle/src/main/java/org/teavm/gradle/api/SourceFilePolicy.java b/tools/gradle/src/main/java/org/teavm/gradle/api/SourceFilePolicy.java new file mode 100644 index 000000000..73800713f --- /dev/null +++ b/tools/gradle/src/main/java/org/teavm/gradle/api/SourceFilePolicy.java @@ -0,0 +1,22 @@ +/* + * Copyright 2023 Alexey Andreev. + * + * 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 + * + * http://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. + */ +package org.teavm.gradle.api; + +public enum SourceFilePolicy { + DO_NOTHING, + COPY, + LINK_LOCAL_FILES +} diff --git a/tools/gradle/src/main/java/org/teavm/gradle/api/TeaVMJSConfiguration.java b/tools/gradle/src/main/java/org/teavm/gradle/api/TeaVMJSConfiguration.java index b33695eab..257c8b11d 100644 --- a/tools/gradle/src/main/java/org/teavm/gradle/api/TeaVMJSConfiguration.java +++ b/tools/gradle/src/main/java/org/teavm/gradle/api/TeaVMJSConfiguration.java @@ -27,4 +27,6 @@ public interface TeaVMJSConfiguration extends TeaVMWebConfiguration { Property getEntryPointName(); Property getTargetFileName(); + + Property getSourceFilePolicy(); } diff --git a/tools/gradle/src/main/java/org/teavm/gradle/tasks/GenerateJavaScriptTask.java b/tools/gradle/src/main/java/org/teavm/gradle/tasks/GenerateJavaScriptTask.java index 2b0d005d8..e96689cf3 100644 --- a/tools/gradle/src/main/java/org/teavm/gradle/tasks/GenerateJavaScriptTask.java +++ b/tools/gradle/src/main/java/org/teavm/gradle/tasks/GenerateJavaScriptTask.java @@ -15,9 +15,13 @@ */ package org.teavm.gradle.tasks; +import org.gradle.api.file.ConfigurableFileCollection; import org.gradle.api.provider.Property; import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Optional; +import org.teavm.gradle.api.SourceFilePolicy; +import org.teavm.tooling.TeaVMSourceFilePolicy; import org.teavm.tooling.TeaVMTargetType; import org.teavm.tooling.builder.BuildStrategy; @@ -26,6 +30,7 @@ public abstract class GenerateJavaScriptTask extends TeaVMTask { getObfuscated().convention(true); getStrict().convention(false); getSourceMap().convention(false); + getSourceFilePolicy().convention(SourceFilePolicy.DO_NOTHING); getEntryPointName().convention("main"); } @@ -45,6 +50,13 @@ public abstract class GenerateJavaScriptTask extends TeaVMTask { @Optional public abstract Property getEntryPointName(); + @InputFiles + public abstract ConfigurableFileCollection getSourceFiles(); + + @Input + @Optional + public abstract Property getSourceFilePolicy(); + @Override protected void setupBuilder(BuildStrategy builder) { builder.setTargetType(TeaVMTargetType.JAVASCRIPT); @@ -52,5 +64,25 @@ public abstract class GenerateJavaScriptTask extends TeaVMTask { builder.setStrict(getStrict().get()); builder.setSourceMapsFileGenerated(getSourceMap().get()); builder.setEntryPointName(getEntryPointName().get()); + for (var file : getSourceFiles()) { + if (file.isFile()) { + if (file.getName().endsWith(".jar") || file.getName().endsWith(".zip")) { + builder.addSourcesJar(file.getAbsolutePath()); + } + } else if (file.isDirectory()) { + builder.addSourcesDirectory(file.getAbsolutePath()); + } + } + switch (getSourceFilePolicy().get()) { + case DO_NOTHING: + builder.setSourceFilePolicy(TeaVMSourceFilePolicy.DO_NOTHING); + break; + case COPY: + builder.setSourceFilePolicy(TeaVMSourceFilePolicy.COPY); + break; + case LINK_LOCAL_FILES: + builder.setSourceFilePolicy(TeaVMSourceFilePolicy.LINK_LOCAL_FILES); + break; + } } } diff --git a/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java b/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java index f263b7ee3..684b8d92b 100644 --- a/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java +++ b/tools/maven/plugin/src/main/java/org/teavm/maven/TeaVMCompileMojo.java @@ -39,6 +39,7 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.repository.RepositorySystem; import org.teavm.backend.wasm.render.WasmBinaryVersion; import org.teavm.tooling.TeaVMProblemRenderer; +import org.teavm.tooling.TeaVMSourceFilePolicy; import org.teavm.tooling.TeaVMTargetType; import org.teavm.tooling.builder.BuildException; import org.teavm.tooling.builder.BuildResult; @@ -177,7 +178,9 @@ public class TeaVMCompileMojo extends AbstractMojo { builder.setIncremental(incremental); builder.setDebugInformationGenerated(debugInformationGenerated); builder.setSourceMapsFileGenerated(sourceMapsGenerated); - builder.setSourceFilesCopied(sourceFilesCopied); + builder.setSourceFilePolicy(sourceFilesCopied + ? TeaVMSourceFilePolicy.COPY + : TeaVMSourceFilePolicy.DO_NOTHING); builder.setMinHeapSize(minHeapSize * 1024 * 1024); builder.setMaxHeapSize(maxHeapSize * 1024 * 1024); builder.setShortFileNames(shortFileNames);