diff --git a/license-report.md b/license-report.md index 1e5d2392a5..74193d05bb 100644 --- a/license-report.md +++ b/license-report.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine:spine-base:1.5.4` +# Dependencies of `io.spine:spine-base:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -330,12 +330,12 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:12 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:53 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-errorprone-checks:1.5.4` +# Dependencies of `io.spine.tools:spine-errorprone-checks:1.5.5` ## Runtime 1. **Group:** com.github.ben-manes.caffeine **Name:** caffeine **Version:** 2.7.0 @@ -777,12 +777,12 @@ This report was generated on **Mon Apr 06 12:01:12 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:13 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:54 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-javadoc-filter:1.5.4` +# Dependencies of `io.spine.tools:spine-javadoc-filter:1.5.5` ## Runtime 1. **Group:** com.google.android **Name:** annotations **Version:** 4.1.1.4 @@ -1170,12 +1170,12 @@ This report was generated on **Mon Apr 06 12:01:13 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:14 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:55 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-javadoc-prettifier:1.5.4` +# Dependencies of `io.spine.tools:spine-javadoc-prettifier:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -1537,12 +1537,12 @@ This report was generated on **Mon Apr 06 12:01:14 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:14 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:55 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-model-compiler:1.5.4` +# Dependencies of `io.spine.tools:spine-model-compiler:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -1920,12 +1920,12 @@ This report was generated on **Mon Apr 06 12:01:14 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:15 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:56 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-mute-logging:1.5.4` +# Dependencies of `io.spine.tools:spine-mute-logging:1.5.5` ## Runtime 1. **Group:** com.google.auto.value **Name:** auto-value-annotations **Version:** 1.6.3 @@ -2305,12 +2305,12 @@ This report was generated on **Mon Apr 06 12:01:15 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:15 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:57 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-plugin-base:1.5.4` +# Dependencies of `io.spine.tools:spine-plugin-base:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -2672,12 +2672,12 @@ This report was generated on **Mon Apr 06 12:01:15 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:16 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:58 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-plugin-testlib:1.5.4` +# Dependencies of `io.spine.tools:spine-plugin-testlib:1.5.5` ## Runtime 1. **Group:** com.google.auto.value **Name:** auto-value-annotations **Version:** 1.6.3 @@ -3097,12 +3097,12 @@ This report was generated on **Mon Apr 06 12:01:16 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:16 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:58 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-proto-dart-plugin:1.5.4` +# Dependencies of `io.spine.tools:spine-proto-dart-plugin:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -3464,12 +3464,12 @@ This report was generated on **Mon Apr 06 12:01:16 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:17 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:20:59 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-proto-js-plugin:1.5.4` +# Dependencies of `io.spine.tools:spine-proto-js-plugin:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -3831,12 +3831,12 @@ This report was generated on **Mon Apr 06 12:01:17 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:17 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:21:00 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-protoc-api:1.5.4` +# Dependencies of `io.spine.tools:spine-protoc-api:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -4158,12 +4158,12 @@ This report was generated on **Mon Apr 06 12:01:17 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:18 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:21:00 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-protoc-plugin:1.5.4` +# Dependencies of `io.spine.tools:spine-protoc-plugin:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -4493,12 +4493,12 @@ This report was generated on **Mon Apr 06 12:01:18 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:18 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:21:01 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:spine-testlib:1.5.4` +# Dependencies of `io.spine:spine-testlib:1.5.5` ## Runtime 1. **Group:** com.google.auto.value **Name:** auto-value-annotations **Version:** 1.6.3 @@ -4878,12 +4878,12 @@ This report was generated on **Mon Apr 06 12:01:18 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:18 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:21:01 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-tool-base:1.5.4` +# Dependencies of `io.spine.tools:spine-tool-base:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -5213,12 +5213,12 @@ This report was generated on **Mon Apr 06 12:01:18 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:19 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). +This report was generated on **Wed Apr 08 17:21:02 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:spine-validation-generator:1.5.4` +# Dependencies of `io.spine.tools:spine-validation-generator:1.5.5` ## Runtime 1. **Group:** com.google.code.findbugs **Name:** jsr305 **Version:** 3.0.2 @@ -5548,4 +5548,4 @@ This report was generated on **Mon Apr 06 12:01:19 EEST 2020** using [Gradle-Lic The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Mon Apr 06 12:01:19 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file +This report was generated on **Wed Apr 08 17:21:02 EEST 2020** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file diff --git a/pom.xml b/pom.xml index a53084ee50..506ec3a047 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ all modules and does not describe the project structure per-subproject. io.spine spine-base -1.5.4 +1.5.5 2015 @@ -154,7 +154,7 @@ all modules and does not describe the project structure per-subproject. io.spine.tools spine-protoc-plugin - 1.5.4 + 1.5.5 test diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/DirectoryPattern.java b/tools/plugin-base/src/main/java/io/spine/tools/code/structure/DirectoryPattern.java similarity index 96% rename from tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/DirectoryPattern.java rename to tools/plugin-base/src/main/java/io/spine/tools/code/structure/DirectoryPattern.java index cbd124ae28..7843c56ce7 100644 --- a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/DirectoryPattern.java +++ b/tools/plugin-base/src/main/java/io/spine/tools/code/structure/DirectoryPattern.java @@ -18,12 +18,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package io.spine.js.generate.resolve; +package io.spine.tools.code.structure; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; -import io.spine.code.fs.js.DirectoryReference; -import io.spine.code.fs.js.FileReference; +import io.spine.code.fs.DirectoryReference; +import io.spine.code.fs.FileReference; import java.util.List; import java.util.Objects; @@ -62,7 +62,6 @@ private DirectoryPattern(DirectoryReference directory, boolean includeNested) { * the value of the pattern * @return a new instance */ - @SuppressWarnings("ResultOfMethodCallIgnored" /* The result can be ignored. */) public static DirectoryPattern of(String value) { checkNotEmptyOrBlank(value); boolean includeNested = value.endsWith(INCLUDE_NESTED_PATTERN_ENDING); diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ExternalModule.java b/tools/plugin-base/src/main/java/io/spine/tools/code/structure/ExternalModule.java similarity index 87% rename from tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ExternalModule.java rename to tools/plugin-base/src/main/java/io/spine/tools/code/structure/ExternalModule.java index 40e1e94535..2ff2325d03 100644 --- a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ExternalModule.java +++ b/tools/plugin-base/src/main/java/io/spine/tools/code/structure/ExternalModule.java @@ -18,12 +18,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package io.spine.js.generate.resolve; +package io.spine.tools.code.structure; import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import io.spine.code.fs.js.DirectoryReference; -import io.spine.code.fs.js.FileReference; +import io.spine.code.fs.DirectoryReference; +import io.spine.code.fs.FileReference; import java.util.Collection; import java.util.Objects; @@ -34,9 +35,9 @@ import static io.spine.util.Preconditions2.checkNotEmptyOrBlank; /** - * An external JavaScript module used in a project. + * An external library module used in a project. * - *

External means that it is provided by an artifact repository like NPM. + *

An external module is typically provided by a package manager, such as NPM or Pub. */ public final class ExternalModule { @@ -65,7 +66,7 @@ public ExternalModule(String name, Collection directories) { * @throws IllegalStateException * if the file is not provided by the module */ - FileReference fileInModule(FileReference fileReference) { + public FileReference fileInModule(FileReference fileReference) { Optional matchingDirectory = matchingDirectory(fileReference); checkState(matchingDirectory.isPresent()); DirectoryReference directory = matchingDirectory.get() @@ -83,11 +84,18 @@ FileReference fileInModule(FileReference fileReference) { * the file to check * @return {@code true} if the module provides the file */ - boolean provides(FileReference fileReference) { + public boolean provides(FileReference fileReference) { boolean result = matchingDirectory(fileReference).isPresent(); return result; } + /** + * Obtains the name of the module. + */ + public String name() { + return name; + } + private Optional matchingDirectory(FileReference fileReference) { DirectoryReference directory = fileReference.directory(); for (DirectoryPattern pattern : directories) { @@ -133,6 +141,13 @@ public static ExternalModule spineUsers() { return new ExternalModule("spine-users", directories); } + /** + * All the modules in {@link #spineWeb()} and {@link #spineUsers()}. + */ + public static ImmutableList predefinedModules() { + return ImmutableList.of(spineWeb(), spineUsers()); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/package-info.java b/tools/plugin-base/src/main/java/io/spine/tools/code/structure/package-info.java similarity index 92% rename from tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/package-info.java rename to tools/plugin-base/src/main/java/io/spine/tools/code/structure/package-info.java index 5810177a3d..e54cbf6162 100644 --- a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/package-info.java +++ b/tools/plugin-base/src/main/java/io/spine/tools/code/structure/package-info.java @@ -19,11 +19,11 @@ */ /** - * The classes which resolve imports in generated code. + * Classes which work with source code directory structure. */ @CheckReturnValue @ParametersAreNonnullByDefault -package io.spine.js.generate.resolve; +package io.spine.tools.code.structure; import javax.annotation.CheckReturnValue; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/tools/plugin-base/src/main/java/io/spine/tools/gradle/GradleTask.java b/tools/plugin-base/src/main/java/io/spine/tools/gradle/GradleTask.java index 077f525b82..8c9a48da9a 100644 --- a/tools/plugin-base/src/main/java/io/spine/tools/gradle/GradleTask.java +++ b/tools/plugin-base/src/main/java/io/spine/tools/gradle/GradleTask.java @@ -296,7 +296,7 @@ private void dependTask(Task task, Project project) { } if (followingTask != null) { TaskContainer existingTasks = project.getTasks(); - existingTasks.getByPath(followingTask.name()) + existingTasks.getByName(followingTask.name()) .dependsOn(task); } if (previousTaskOfAllProjects != null) { diff --git a/tools/plugin-base/src/main/java/io/spine/tools/gradle/ProtoDartTaskName.java b/tools/plugin-base/src/main/java/io/spine/tools/gradle/ProtoDartTaskName.java index 4a70a34aa4..c63d29f5d3 100644 --- a/tools/plugin-base/src/main/java/io/spine/tools/gradle/ProtoDartTaskName.java +++ b/tools/plugin-base/src/main/java/io/spine/tools/gradle/ProtoDartTaskName.java @@ -58,5 +58,10 @@ public enum ProtoDartTaskName implements TaskName { * *

Works only with the {@code test} scope files. */ - copyTestGeneratedDart + copyTestGeneratedDart, + + /** + * Rewrites the Dart source files generated from Protobuf with the resolved absolute imports. + */ + resolveImports } diff --git a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/DirectoryPatternTest.java b/tools/plugin-base/src/test/java/io/spine/tools/code/structure/DirectoryPatternTest.java similarity index 98% rename from tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/DirectoryPatternTest.java rename to tools/plugin-base/src/test/java/io/spine/tools/code/structure/DirectoryPatternTest.java index e2ce73c3f5..32ac8328b0 100644 --- a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/DirectoryPatternTest.java +++ b/tools/plugin-base/src/test/java/io/spine/tools/code/structure/DirectoryPatternTest.java @@ -18,11 +18,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package io.spine.js.generate.resolve; +package io.spine.tools.code.structure; import com.google.common.testing.EqualsTester; import com.google.common.testing.NullPointerTester; -import io.spine.code.fs.js.DirectoryReference; +import io.spine.code.fs.DirectoryReference; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ExternalModuleTest.java b/tools/plugin-base/src/test/java/io/spine/tools/code/structure/ExternalModuleTest.java similarity index 90% rename from tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ExternalModuleTest.java rename to tools/plugin-base/src/test/java/io/spine/tools/code/structure/ExternalModuleTest.java index ccacea3996..8320a32329 100644 --- a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ExternalModuleTest.java +++ b/tools/plugin-base/src/test/java/io/spine/tools/code/structure/ExternalModuleTest.java @@ -18,15 +18,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package io.spine.js.generate.resolve; +package io.spine.tools.code.structure; import com.google.common.testing.EqualsTester; -import io.spine.code.fs.js.FileReference; +import io.spine.code.fs.FileReference; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import static io.spine.js.generate.resolve.given.Given.newModule; +import java.util.List; + import static java.util.Collections.emptySet; +import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -104,4 +106,10 @@ void acceptOnlyProvidedProto() { () -> module.fileInModule(reference) ); } + + private static ExternalModule newModule(String moduleName, String directoryPattern) { + DirectoryPattern pattern = DirectoryPattern.of(directoryPattern); + List patterns = singletonList(pattern); + return new ExternalModule(moduleName, patterns); + } } diff --git a/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/Extension.java b/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/Extension.java index 146695c1ca..74d8cf818f 100644 --- a/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/Extension.java +++ b/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/Extension.java @@ -20,7 +20,10 @@ package io.spine.generate.dart; +import com.google.common.collect.ImmutableList; import io.spine.code.fs.dart.DefaultDartProject; +import io.spine.tools.code.structure.DirectoryPattern; +import io.spine.tools.code.structure.ExternalModule; import io.spine.tools.gradle.GradleExtension; import org.gradle.api.Project; import org.gradle.api.file.DirectoryProperty; @@ -29,6 +32,12 @@ import java.io.File; import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static com.google.common.collect.Maps.newHashMap; +import static java.util.stream.Collectors.toList; /** * DSL extension for configuring Protobuf-to-Dart compilation. @@ -50,6 +59,39 @@ public final class Extension extends GradleExtension { private final DirectoryProperty testDir; private final DirectoryProperty mainGeneratedDir; private final DirectoryProperty testGeneratedDir; + + /** + * Names of Dart modules and directories they provide. + * + *

Information about modules is used to resolve imports in generated Protobuf files. + * + *

Import resolution only applies to Dart files generated from Protobuf. Such files must + * have one of extensions: {@code .pb.dart}, {@code .pbenum.dart}, {@code .pbserver.dart}, or + * {@code .pbjson.dart}. All other files are ignored. + * + *

An example of the definition: + *

{@code
+     * modules = [
+     *      // The module provides `company/client` directory (not including subdirectories).
+     *      // So, an import path like {@code ../company/client/file.pb.dart}
+     *      // becomes {@code package:client/company/client/file.pb.dart}.
+     *      'client' : ['company/client'],
+     *
+     *      // The module provides `company/server` directory (including subdirectories).
+     *      // So, an import path like {@code ../company/server/nested/file.pb.dart}
+     *      // becomes {@code package:server/company/server/nested/file.pb.dart}.
+     *      'server' : ['company/server/*'],
+     *
+     *      // The module provides 'proto/company` directory.
+     *      // So, an import pah like {@code ../company/file.pbenum.dart}
+     *      // becomes {@code package:common_types/proto/company/file.pbenum.dart}.
+     *      'common_types' : ['proto/company']
+     * ]
+     * }
+ */ + @SuppressWarnings("PublicField" /* Expose fields as a Gradle extension */) + public Map> modules = newHashMap(); + private final Project project; Extension(Project project) { @@ -225,6 +267,16 @@ Path testGeneratedDir() { .toPath(); } + ImmutableList modules() { + ImmutableList.Builder modules = ImmutableList.builder(); + for (String moduleName : this.modules.keySet()) { + List patterns = patterns(this.modules.get(moduleName)); + ExternalModule module = new ExternalModule(moduleName, patterns); + modules.add(module); + } + return modules.build(); + } + /** * Finalizes all configurable values. * @@ -245,6 +297,12 @@ private File file(Property property) { return project.file(property.get()); } + private static List patterns(Collection rawPatterns) { + return rawPatterns.stream() + .map(DirectoryPattern::of) + .collect(toList()); + } + @Override protected DefaultDartProject defaultProject(Project project) { return DefaultDartProject.at(project.getProjectDir().toPath()); diff --git a/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/ProtoDartPlugin.java b/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/ProtoDartPlugin.java index 39e6f6d85f..31441f9884 100644 --- a/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/ProtoDartPlugin.java +++ b/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/ProtoDartPlugin.java @@ -28,13 +28,17 @@ import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.file.DirectoryProperty; +import org.gradle.api.file.FileTree; import org.gradle.api.tasks.Copy; import java.io.File; +import java.nio.file.Path; +import static io.spine.generate.dart.SourceFile.isGeneratedDart; import static io.spine.tools.gradle.BaseTaskName.assemble; import static io.spine.tools.gradle.ProtoDartTaskName.copyGeneratedDart; import static io.spine.tools.gradle.ProtoDartTaskName.copyTestGeneratedDart; +import static io.spine.tools.gradle.ProtoDartTaskName.resolveImports; import static io.spine.tools.gradle.ProtobufTaskName.generateProto; import static io.spine.tools.gradle.ProtobufTaskName.generateTestProto; import static io.spine.tools.gradle.ProtocPluginName.dart; @@ -62,6 +66,7 @@ public void apply(Project project) { createMainCopyTask(project, extension); createTestCopyTask(project, extension); + createResolveImportTask(project, extension); } private static void createMainCopyTask(Project project, Extension extension) { @@ -94,4 +99,30 @@ private static void createCopyTask(Project project, Extension extension, SourceS .getByName(assemble.name()) .dependsOn(taskName.name()); } + + private void createResolveImportTask(Project project, Extension extension) { + newTask(resolveImports, task -> { + FileTree generatedDir = extension.getMainGeneratedDir() + .getAsFileTree(); + generatedDir.forEach(file -> resolveImports(file, extension)); + }) + .insertAfterTask(copyGeneratedDart) + .insertBeforeTask(assemble) + .applyNowTo(project); + } + + private void resolveImports(File sourceFile, Extension extension) { + Path asPath = sourceFile.toPath(); + if (!isGeneratedDart(asPath)) { + return; + } + _debug().log("Resolving imports in file %s", sourceFile); + SourceFile file = SourceFile.read(sourceFile.toPath()); + Path libPath = extension.getLibDir() + .getAsFile() + .map(File::toPath) + .get(); + file.resolveImports(extension.modules(), libPath); + file.store(); + } } diff --git a/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/SourceFile.java b/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/SourceFile.java new file mode 100644 index 0000000000..5480fc3281 --- /dev/null +++ b/tools/proto-dart-plugin/src/main/java/io/spine/generate/dart/SourceFile.java @@ -0,0 +1,134 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package io.spine.generate.dart; + +import com.google.common.collect.ImmutableList; +import io.spine.code.AbstractSourceFile; +import io.spine.code.fs.FileReference; +import io.spine.logging.Logging; +import io.spine.tools.code.structure.ExternalModule; +import org.checkerframework.checker.regex.qual.Regex; +import org.gradle.api.GradleException; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static com.google.common.base.Preconditions.checkNotNull; +import static java.lang.String.format; +import static java.nio.file.Files.isRegularFile; +import static java.nio.file.Files.readAllLines; +import static java.nio.file.Files.write; +import static java.util.regex.Pattern.compile; + +/** + * A Dart source file. + */ +final class SourceFile extends AbstractSourceFile implements Logging { + + @Regex(2) + private static final Pattern IMPORT_PATTERN = compile("import [\"']([^:]+)[\"'] as (.+);"); + + private List lines; + + private SourceFile(Path path, List lines) { + super(path); + this.lines = lines; + } + + /** + * Reads the file from the local file system. + */ + static SourceFile read(Path path) { + checkNotNull(path); + try { + List lines = readAllLines(path); + return new SourceFile(path, lines); + } catch (IOException e) { + throw new GradleException(format("Unable to read file `%s`.", path), e); + } + } + + static boolean isGeneratedDart(Path file) { + if (!isRegularFile(file)) { + return false; + } + return file.endsWith(".pb.dart") + || file.endsWith(".pbenum.dart") + || file.endsWith(".pbserver.dart") + || file.endsWith(".pbjson.dart"); + } + + /** + * Resolves the relative imports in the file into absolute ones with the given modules. + */ + void resolveImports(ImmutableList modules, Path libPath) { + List processedLines = new ArrayList<>(); + for (String line : lines) { + String processedLine = resolveImportInLine(line, modules, libPath); + processedLines.add(processedLine); + } + lines = processedLines; + } + + private String resolveImportInLine(String line, + ImmutableList modules, + Path libPath) { + Matcher matcher = IMPORT_PATTERN.matcher(line); + if (matcher.matches()) { + _debug().log("Import found: `%s`", line); + String path = matcher.group(1); + Path absolutePath = path().getParent() + .resolve(path) + .normalize(); + _debug().log("Resolved against this file: `%s`", absolutePath); + Path relativeImport = libPath.relativize(absolutePath); + _debug().log("Relative: `%s`", relativeImport); + FileReference reference = FileReference.of(relativeImport.toString()); + for (ExternalModule module : modules) { + if (module.provides(reference)) { + String importStatement = format("import 'package:%s/%s' as %s;", + module.name(), + relativeImport, + matcher.group(2)); + _debug().log("Replacing with %s", importStatement); + return importStatement; + } + } + } + return line; + } + + /** + * Rewrites this file. + */ + void store() { + Path path = path(); + try { + write(path, lines); + } catch (IOException e) { + throw new GradleException(format("Unable to write file `%s`.", path), e); + } + } +} diff --git a/tools/proto-dart-plugin/src/test/java/io/spine/generate/dart/ProtoDartPluginTest.java b/tools/proto-dart-plugin/src/test/java/io/spine/generate/dart/ProtoDartPluginTest.java index cb1828358d..ce2a7c2e9e 100644 --- a/tools/proto-dart-plugin/src/test/java/io/spine/generate/dart/ProtoDartPluginTest.java +++ b/tools/proto-dart-plugin/src/test/java/io/spine/generate/dart/ProtoDartPluginTest.java @@ -20,6 +20,7 @@ package io.spine.generate.dart; +import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.spine.tools.gradle.TaskName; import org.gradle.api.Project; import org.gradle.api.Task; @@ -35,6 +36,7 @@ import static io.spine.tools.gradle.BaseTaskName.assemble; import static io.spine.tools.gradle.ProtoDartTaskName.copyGeneratedDart; import static io.spine.tools.gradle.ProtoDartTaskName.copyTestGeneratedDart; +import static io.spine.tools.gradle.ProtoDartTaskName.resolveImports; @DisplayName("`ProtoDartPlugin` should") class ProtoDartPluginTest { @@ -57,10 +59,10 @@ void createMainTask() { ProtoDartPlugin plugin = new ProtoDartPlugin(); plugin.apply(project); - Task task = task(copyGeneratedDart); + Task task = findTask(copyGeneratedDart); assertThat(task.getDependsOn()).isNotEmpty(); - Task assembleTask = task(assemble); + Task assembleTask = findTask(assemble); assertThat(assembleTask.getDependsOn()).contains(task.getName()); } @@ -70,14 +72,24 @@ void createTestTask() { ProtoDartPlugin plugin = new ProtoDartPlugin(); plugin.apply(project); - Task task = task(copyTestGeneratedDart); + Task task = findTask(copyTestGeneratedDart); assertThat(task.getDependsOn()).isNotEmpty(); - Task assembleTask = task(assemble); + Task assembleTask = findTask(assemble); assertThat(assembleTask.getDependsOn()).contains(task.getName()); } - private Task task(TaskName name) { + @Test + @DisplayName("create `resolveImports` task") + void createResolveTask() { + ProtoDartPlugin plugin = new ProtoDartPlugin(); + plugin.apply(project); + + findTask(resolveImports); + } + + @CanIgnoreReturnValue + private Task findTask(TaskName name) { Task task = project.getTasks() .findByName(name.name()); assertThat(task).isNotNull(); diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ImportStatement.java b/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/ImportStatement.java similarity index 92% rename from tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ImportStatement.java rename to tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/ImportStatement.java index 45026415db..a1e21d768a 100644 --- a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ImportStatement.java +++ b/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/ImportStatement.java @@ -18,9 +18,9 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package io.spine.js.generate.resolve; +package io.spine.js.generate.imports; -import io.spine.code.fs.js.FileReference; +import io.spine.code.fs.FileReference; import io.spine.logging.Logging; import java.io.File; @@ -66,7 +66,7 @@ static boolean hasImport(String line) { /** * Obtains the file reference used in this import. */ - FileReference path() { + public FileReference path() { int beginIndex = text.indexOf(IMPORT_BEGIN_SIGN) + IMPORT_BEGIN_SIGN.length(); int endIndex = text.indexOf(IMPORT_END_SIGN, beginIndex); String importPath = text.substring(beginIndex, endIndex); @@ -76,7 +76,7 @@ FileReference path() { /** * Obtains a new instance with the updated path in the import statement. */ - ImportStatement replacePath(CharSequence newPath) { + public ImportStatement replacePath(CharSequence newPath) { String updatedText = text.replace(path().value(), newPath); return new ImportStatement(updatedText, originFile); } @@ -91,7 +91,7 @@ String text() { /** * Tells whether the imported file is present on a file system. */ - boolean importedFileExists() { + public boolean importedFileExists() { Path filePath = importedFilePath(); boolean exists = filePath.toFile() .exists(); @@ -102,7 +102,7 @@ boolean importedFileExists() { /** * Obtains the absolute path to the imported file. */ - Path importedFilePath() { + public Path importedFilePath() { FileReference fileReference = path(); Path filePath = sourceDirectory().resolve(fileReference.value()); return filePath.normalize(); @@ -111,7 +111,7 @@ Path importedFilePath() { /** * Obtains the path of the directory with the file containing this import. */ - Path sourceDirectory() { + public Path sourceDirectory() { return originFile.getParentFile() .toPath(); } diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/JsFile.java b/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/JsFile.java similarity index 93% rename from tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/JsFile.java rename to tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/JsFile.java index ca1490c877..20b7fb5f8c 100644 --- a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/JsFile.java +++ b/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/JsFile.java @@ -18,7 +18,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package io.spine.js.generate.resolve; +package io.spine.js.generate.imports; import com.google.common.base.Charsets; @@ -39,13 +39,13 @@ /** * A JavaScript file present on a file system. */ -final class JsFile { +public final class JsFile { private static final String EXTENSION = ".js"; private final Path path; - JsFile(Path path) { + public JsFile(Path path) { checkArgument(path.toString() .endsWith(EXTENSION), "A JavaScript file is expected."); checkArgument(path.toFile() @@ -63,7 +63,7 @@ final class JsFile { * @param processFunction * the function processing an import */ - void processImports(Predicate importFilter, + public void processImports(Predicate importFilter, ProcessImport processFunction) { try (Stream lines = Files.lines(path)) { List updatedLines = lines @@ -101,6 +101,6 @@ private void rewriteFile(Iterable lines) { /** * A function processing an import statement. */ - interface ProcessImport extends UnaryOperator { + public interface ProcessImport extends UnaryOperator { } } diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ResolveImports.java b/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/ResolveImports.java similarity index 98% rename from tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ResolveImports.java rename to tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/ResolveImports.java index 182e20838e..456a654d9d 100644 --- a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/resolve/ResolveImports.java +++ b/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/ResolveImports.java @@ -18,19 +18,20 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package io.spine.js.generate.resolve; +package io.spine.js.generate.imports; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableSet; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.protobuf.Descriptors.FileDescriptor; +import io.spine.code.fs.FileReference; import io.spine.code.fs.js.Directory; import io.spine.code.fs.js.FileName; -import io.spine.code.fs.js.FileReference; import io.spine.code.proto.FileSet; import io.spine.js.generate.GenerationTask; import io.spine.logging.Logging; +import io.spine.tools.code.structure.ExternalModule; import org.checkerframework.checker.nullness.qual.Nullable; import java.nio.file.Path; diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/package-info.java b/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/package-info.java new file mode 100644 index 0000000000..839661a05f --- /dev/null +++ b/tools/proto-js-plugin/src/main/java/io/spine/js/generate/imports/package-info.java @@ -0,0 +1,31 @@ +/* + * Copyright 2020, TeamDev. All rights reserved. + * + * Redistribution and use in source and/or binary forms, with or without + * modification, must retain the above copyright notice and the following + * disclaimer. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Classes for resolving JS imports. + */ + +@CheckReturnValue +@ParametersAreNonnullByDefault +package io.spine.js.generate.imports; + +import com.google.errorprone.annotations.CheckReturnValue; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/gradle/Extension.java b/tools/proto-js-plugin/src/main/java/io/spine/js/gradle/Extension.java index aaccfd2ff8..6faf287a3f 100644 --- a/tools/proto-js-plugin/src/main/java/io/spine/js/gradle/Extension.java +++ b/tools/proto-js-plugin/src/main/java/io/spine/js/gradle/Extension.java @@ -21,12 +21,11 @@ package io.spine.js.gradle; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; import io.spine.code.fs.DefaultProject; import io.spine.code.fs.js.DefaultJsProject; import io.spine.code.fs.js.Directory; -import io.spine.js.generate.resolve.DirectoryPattern; -import io.spine.js.generate.resolve.ExternalModule; +import io.spine.tools.code.structure.DirectoryPattern; +import io.spine.tools.code.structure.ExternalModule; import io.spine.tools.gradle.GradleExtension; import org.gradle.api.Project; import org.gradle.api.Task; @@ -43,6 +42,7 @@ import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; import static io.spine.js.gradle.ProtoJsPlugin.extensionName; +import static io.spine.tools.code.structure.ExternalModule.predefinedModules; import static java.util.stream.Collectors.toList; /** @@ -78,7 +78,7 @@ public class Extension extends GradleExtension { *

Information about modules is used to resolve imports in generated Protobuf files. * *

Additionally to modules specified via the property, - * the {@linkplain #predefinedModules() predefined Spine} modules are used. + * the {@linkplain ExternalModule#predefinedModules() predefined Spine} modules are used. * *

An example of the definition: *

{@code
@@ -172,17 +172,6 @@ static Extension extension(Project project) {
                        .getByName(extensionName());
     }
 
-    /**
-     * Obtains the external modules published by Spine.
-     */
-    @VisibleForTesting
-    static List predefinedModules() {
-        return ImmutableList.of(
-                ExternalModule.spineWeb(),
-                ExternalModule.spineUsers()
-        );
-    }
-
     private static List patterns(Collection rawPatterns) {
         return rawPatterns.stream()
                           .map(DirectoryPattern::of)
diff --git a/tools/proto-js-plugin/src/main/java/io/spine/js/gradle/ProtoJsPlugin.java b/tools/proto-js-plugin/src/main/java/io/spine/js/gradle/ProtoJsPlugin.java
index 87b75ce3ef..e2f769b688 100644
--- a/tools/proto-js-plugin/src/main/java/io/spine/js/gradle/ProtoJsPlugin.java
+++ b/tools/proto-js-plugin/src/main/java/io/spine/js/gradle/ProtoJsPlugin.java
@@ -26,10 +26,10 @@
 import io.spine.code.proto.FileSet;
 import io.spine.js.generate.AppendTypeUrlGetter;
 import io.spine.js.generate.GenerationTask;
+import io.spine.js.generate.imports.ResolveImports;
 import io.spine.js.generate.index.GenerateIndexFile;
 import io.spine.js.generate.parse.GenerateKnownTypeParsers;
-import io.spine.js.generate.resolve.ExternalModule;
-import io.spine.js.generate.resolve.ResolveImports;
+import io.spine.tools.code.structure.ExternalModule;
 import io.spine.tools.gradle.BaseTaskName;
 import io.spine.tools.gradle.GradleTask;
 import io.spine.tools.gradle.ProtoPlugin;
diff --git a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ImportStatementTest.java b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/ImportStatementTest.java
similarity index 92%
rename from tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ImportStatementTest.java
rename to tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/ImportStatementTest.java
index 08146d49c7..1c3ec044d9 100644
--- a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ImportStatementTest.java
+++ b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/ImportStatementTest.java
@@ -18,9 +18,9 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.spine.js.generate.resolve;
+package io.spine.js.generate.imports;
 
-import io.spine.code.fs.js.FileReference;
+import io.spine.code.fs.FileReference;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 
@@ -29,8 +29,8 @@
 import java.nio.file.Paths;
 
 import static com.google.common.truth.Truth.assertThat;
-import static io.spine.js.generate.resolve.given.Given.importWithPath;
-import static io.spine.js.generate.resolve.given.Given.relativeImportPath;
+import static io.spine.js.generate.imports.given.Given.importWithPath;
+import static io.spine.js.generate.imports.given.Given.relativeImportPath;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 @DisplayName("ImportStatement should")
diff --git a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/JsFileTest.java b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/JsFileTest.java
similarity index 97%
rename from tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/JsFileTest.java
rename to tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/JsFileTest.java
index a2fab1eb48..738cc77346 100644
--- a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/JsFileTest.java
+++ b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/JsFileTest.java
@@ -18,7 +18,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.spine.js.generate.resolve;
+package io.spine.js.generate.imports;
 
 import com.google.common.collect.ImmutableList;
 import org.junit.jupiter.api.BeforeEach;
@@ -35,7 +35,7 @@
 import java.util.List;
 
 import static com.google.common.truth.Truth.assertThat;
-import static io.spine.js.generate.resolve.given.Given.importWithPath;
+import static io.spine.js.generate.imports.given.Given.importWithPath;
 
 @ExtendWith(TempDirectory.class)
 @DisplayName("JavaScript file should")
diff --git a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ResolveImportsTest.java b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/ResolveImportsTest.java
similarity index 95%
rename from tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ResolveImportsTest.java
rename to tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/ResolveImportsTest.java
index 87f5435e99..92d2696a54 100644
--- a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/ResolveImportsTest.java
+++ b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/ResolveImportsTest.java
@@ -18,12 +18,14 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.spine.js.generate.resolve;
+package io.spine.js.generate.imports;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.truth.IterableSubject;
 import io.spine.code.fs.js.Directory;
 import io.spine.js.generate.given.GivenProject;
+import io.spine.tools.code.structure.DirectoryPattern;
+import io.spine.tools.code.structure.ExternalModule;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 
@@ -33,14 +35,15 @@
 import java.util.List;
 
 import static com.google.common.truth.Truth.assertThat;
-import static io.spine.js.generate.resolve.given.Given.newModule;
 import static java.util.Arrays.asList;
 
 @DisplayName("ResolveImports task should")
 class ResolveImportsTest {
 
     private final Directory generatedProtoDir = GivenProject.mainProtoSources();
-    private final ExternalModule module = newModule("test-module", "root-dir");
+    private final ExternalModule module = new ExternalModule(
+            "test-module", ImmutableList.of(DirectoryPattern.of("root-dir"))
+    );
     private final Path tempDirectory = generatedProtoDir.path();
     private final Path testFile = tempDirectory.resolve("js/with-imports.js");
 
diff --git a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/given/Given.java b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/given/Given.java
similarity index 58%
rename from tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/given/Given.java
rename to tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/given/Given.java
index 7da7c8021c..6441e6337e 100644
--- a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/resolve/given/Given.java
+++ b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/given/Given.java
@@ -18,20 +18,13 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.spine.js.generate.resolve.given;
+package io.spine.js.generate.imports.given;
 
-import io.spine.code.fs.js.Directory;
-import io.spine.js.generate.resolve.DirectoryPattern;
-import io.spine.js.generate.resolve.ExternalModule;
-import io.spine.js.generate.resolve.ImportStatement;
+import io.spine.js.generate.imports.ImportStatement;
 
 import java.io.File;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
 
 import static java.lang.String.format;
-import static java.util.Collections.singletonList;
 
 public class Given {
 
@@ -44,28 +37,7 @@ public static ImportStatement importWithPath(String path, File importOrigin) {
         return new ImportStatement(importText, importOrigin);
     }
 
-    public static Directory mainProtoRoot() {
-        return protoRoot("main");
-    }
-
-    public static Directory testProtoRoot() {
-        return protoRoot("test");
-    }
-
     public static String relativeImportPath() {
         return "../path-relative-to-parent.js";
     }
-
-    private static Directory protoRoot(String sourceSetName) {
-        Path path = Paths.get("src")
-                         .resolve(sourceSetName)
-                         .resolve("proto");
-        return Directory.at(path.toAbsolutePath());
-    }
-
-    public static ExternalModule newModule(String moduleName, String directoryPattern) {
-        DirectoryPattern pattern = DirectoryPattern.of(directoryPattern);
-        List patterns = singletonList(pattern);
-        return new ExternalModule(moduleName, patterns);
-    }
 }
diff --git a/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/given/package-info.java b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/given/package-info.java
new file mode 100644
index 0000000000..c412a6f783
--- /dev/null
+++ b/tools/proto-js-plugin/src/test/java/io/spine/js/generate/imports/given/package-info.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2020, TeamDev. All rights reserved.
+ *
+ * Redistribution and use in source and/or binary forms, with or without
+ * modification, must retain the above copyright notice and the following
+ * disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Contains test environment for components resolving script language imports.
+ */
+
+@CheckReturnValue
+@ParametersAreNonnullByDefault
+package io.spine.js.generate.imports.given;
+
+import com.google.errorprone.annotations.CheckReturnValue;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/tools/proto-js-plugin/src/test/java/io/spine/js/gradle/ExtensionTest.java b/tools/proto-js-plugin/src/test/java/io/spine/js/gradle/ExtensionTest.java
index f4bab09a43..25a5c01b55 100644
--- a/tools/proto-js-plugin/src/test/java/io/spine/js/gradle/ExtensionTest.java
+++ b/tools/proto-js-plugin/src/test/java/io/spine/js/gradle/ExtensionTest.java
@@ -22,7 +22,7 @@
 
 import io.spine.code.fs.js.DefaultJsProject;
 import io.spine.code.fs.js.Directory;
-import io.spine.js.generate.resolve.ExternalModule;
+import io.spine.tools.code.structure.ExternalModule;
 import org.gradle.api.Project;
 import org.gradle.api.plugins.PluginManager;
 import org.gradle.testfixtures.ProjectBuilder;
@@ -75,7 +75,8 @@ void defaultMainGenProto() {
         Directory directory = Extension.getMainGenProto(project);
         Directory expected = defaultProject.proto()
                                            .mainJs();
-        assertEquals(expected, directory);
+        assertThat(directory)
+                .isEqualTo(expected);
     }
 
     @Test
@@ -94,7 +95,8 @@ void defaultTestGenProto() {
         Directory directory = Extension.getTestGenProtoDir(project);
         Directory expected = defaultProject.proto()
                                            .testJs();
-        assertEquals(expected, directory);
+        assertThat(directory)
+                .isEqualTo(expected);
     }
 
     @Test
@@ -104,7 +106,8 @@ void customTestGenProto() {
         pluginExtension().testGenProtoDir = customPath;
         Directory directory = Extension.getTestGenProtoDir(project);
         Directory expected = Directory.at(Paths.get(customPath));
-        assertEquals(expected, directory);
+        assertThat(directory)
+                .isEqualTo(expected);
     }
 
     @Test
@@ -117,7 +120,8 @@ void defaultMainDescriptorSet() {
         File expected = mainDescriptors
                 .resolve(GROUP_ID + '_' + project.getName() + '_' + VERSION + ".desc")
                 .toFile();
-        assertEquals(expected, file);
+        assertThat(file)
+                .isEqualTo(expected);
     }
 
     @Test
@@ -127,7 +131,8 @@ void customMainDescriptorSet() {
         pluginExtension().mainDescriptorSetPath = customPath;
         File file = Extension.getMainDescriptorSet(project);
         File expected = new File(customPath);
-        assertEquals(expected, file);
+        assertThat(file)
+                .isEqualTo(expected);
     }
 
     @Test
@@ -140,7 +145,8 @@ void defaultTestDescriptorSet() {
         File expected = testDescriptors
                 .resolve(GROUP_ID + '_' + project.getName() + '_' + VERSION + "_test.desc")
                 .toFile();
-        assertEquals(expected, file);
+        assertThat(file)
+                .isEqualTo(expected);
     }
 
     @Test
@@ -150,14 +156,8 @@ void customTestDescriptorSet() {
         pluginExtension().testDescriptorSetPath = customPath;
         File file = Extension.getTestDescriptorSet(project);
         File expected = new File(customPath);
-        assertEquals(expected, file);
-    }
-
-    @Test
-    @DisplayName("include predefined Spine modules")
-    void includePredefinedModules() {
-        List modules = Extension.modules(project);
-        assertThat(modules).containsAtLeastElementsIn(Extension.predefinedModules());
+        assertThat(file)
+                .isEqualTo(expected);
     }
 
     @Test
@@ -167,8 +167,8 @@ void setModulesToResolve() {
         Map> modulesExt = pluginExtension().modules;
         modulesExt.put(moduleName, emptyList());
         List modules = Extension.modules(project);
-        assertThat(modules).containsAtLeastElementsIn(Extension.predefinedModules());
-        assertThat(modules).contains(new ExternalModule(moduleName, emptyList()));
+        assertThat(modules)
+                .contains(new ExternalModule(moduleName, emptyList()));
     }
 
     private Extension pluginExtension() {
diff --git a/tools/tool-base/src/main/java/io/spine/code/fs/js/DirectoryReference.java b/tools/tool-base/src/main/java/io/spine/code/fs/DirectoryReference.java
similarity index 98%
rename from tools/tool-base/src/main/java/io/spine/code/fs/js/DirectoryReference.java
rename to tools/tool-base/src/main/java/io/spine/code/fs/DirectoryReference.java
index 9c37638dae..bc0b795169 100644
--- a/tools/tool-base/src/main/java/io/spine/code/fs/js/DirectoryReference.java
+++ b/tools/tool-base/src/main/java/io/spine/code/fs/DirectoryReference.java
@@ -18,7 +18,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.spine.code.fs.js;
+package io.spine.code.fs;
 
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
diff --git a/tools/tool-base/src/main/java/io/spine/code/fs/js/FileReference.java b/tools/tool-base/src/main/java/io/spine/code/fs/FileReference.java
similarity index 97%
rename from tools/tool-base/src/main/java/io/spine/code/fs/js/FileReference.java
rename to tools/tool-base/src/main/java/io/spine/code/fs/FileReference.java
index fc36a37d5f..017059f8c1 100644
--- a/tools/tool-base/src/main/java/io/spine/code/fs/js/FileReference.java
+++ b/tools/tool-base/src/main/java/io/spine/code/fs/FileReference.java
@@ -18,7 +18,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.spine.code.fs.js;
+package io.spine.code.fs;
 
 import com.google.common.base.Splitter;
 import com.google.common.collect.ImmutableList;
@@ -29,7 +29,7 @@
 import static io.spine.util.Preconditions2.checkNotEmptyOrBlank;
 
 /**
- * A path to a file used in a JavaScript import statement.
+ * A path to a file used in an import statement.
  */
 public final class FileReference extends StringTypeValue {
 
diff --git a/tools/tool-base/src/main/java/io/spine/code/fs/js/FileName.java b/tools/tool-base/src/main/java/io/spine/code/fs/js/FileName.java
index 0268883f85..012bafc69f 100644
--- a/tools/tool-base/src/main/java/io/spine/code/fs/js/FileName.java
+++ b/tools/tool-base/src/main/java/io/spine/code/fs/js/FileName.java
@@ -26,6 +26,7 @@
 import com.google.common.collect.ImmutableList;
 import com.google.protobuf.Descriptors.FileDescriptor;
 import io.spine.code.AbstractFileName;
+import io.spine.code.fs.FileReference;
 
 import java.util.List;
 
diff --git a/tools/tool-base/src/test/java/io/spine/code/fs/js/DirectoryReferenceTest.java b/tools/tool-base/src/test/java/io/spine/code/fs/js/DirectoryReferenceTest.java
index a30e846e37..f51e562f74 100644
--- a/tools/tool-base/src/test/java/io/spine/code/fs/js/DirectoryReferenceTest.java
+++ b/tools/tool-base/src/test/java/io/spine/code/fs/js/DirectoryReferenceTest.java
@@ -20,6 +20,7 @@
 
 package io.spine.code.fs.js;
 
+import io.spine.code.fs.DirectoryReference;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 
diff --git a/tools/tool-base/src/test/java/io/spine/code/fs/js/FileReferenceTest.java b/tools/tool-base/src/test/java/io/spine/code/fs/js/FileReferenceTest.java
index 2b67d7ca6b..18ff66c56f 100644
--- a/tools/tool-base/src/test/java/io/spine/code/fs/js/FileReferenceTest.java
+++ b/tools/tool-base/src/test/java/io/spine/code/fs/js/FileReferenceTest.java
@@ -21,6 +21,7 @@
 package io.spine.code.fs.js;
 
 import com.google.common.testing.NullPointerTester;
+import io.spine.code.fs.FileReference;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 
diff --git a/version.gradle b/version.gradle
index 8d3d59d0b5..7add5bdb18 100644
--- a/version.gradle
+++ b/version.gradle
@@ -25,7 +25,7 @@
  * as we want to manage the versions in a single source.
  */
 
-final def SPINE_VERSION = '1.5.4'
+final def SPINE_VERSION = '1.5.5'
 
 ext {
     spineVersion = SPINE_VERSION