diff --git a/build.gradle b/build.gradle index 6c16702e..540f9c01 100644 --- a/build.gradle +++ b/build.gradle @@ -61,6 +61,7 @@ dependencies { implementation 'commons-lang:commons-lang:2.6' testImplementation 'junit:junit:4.12' + testImplementation "com.android.tools.build:gradle:3.5.0" testImplementation('org.spockframework:spock-core:1.0-groovy-2.4') { exclude module: 'groovy-all' } diff --git a/src/main/groovy/com/google/protobuf/gradle/ArchiveActionFacade.java b/src/main/groovy/com/google/protobuf/gradle/ArchiveActionFacade.java index 3d4f2779..f16dee37 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ArchiveActionFacade.java +++ b/src/main/groovy/com/google/protobuf/gradle/ArchiveActionFacade.java @@ -28,18 +28,21 @@ */ package com.google.protobuf.gradle; +import groovy.transform.CompileStatic; import org.gradle.api.Project; import org.gradle.api.file.FileTree; import org.gradle.api.internal.file.FileOperations; import javax.inject.Inject; +@CompileStatic public interface ArchiveActionFacade { FileTree zipTree(Object path); FileTree tarTree(Object path); + @CompileStatic class ProjectBased implements ArchiveActionFacade { private final Project project; @@ -59,6 +62,7 @@ public FileTree tarTree(Object path) { } } + @CompileStatic abstract class ServiceBased implements ArchiveActionFacade { // TODO Use public ArchiveOperations from Gradle 6.6 instead diff --git a/src/main/groovy/com/google/protobuf/gradle/CopyActionFacade.java b/src/main/groovy/com/google/protobuf/gradle/CopyActionFacade.java index 41e8e770..804f3aa7 100644 --- a/src/main/groovy/com/google/protobuf/gradle/CopyActionFacade.java +++ b/src/main/groovy/com/google/protobuf/gradle/CopyActionFacade.java @@ -29,6 +29,7 @@ */ package com.google.protobuf.gradle; +import groovy.transform.CompileStatic; import org.gradle.api.Action; import org.gradle.api.Project; import org.gradle.api.file.CopySpec; @@ -42,9 +43,11 @@ * {@link org.gradle.api.file.FileSystemOperations} if available (Gradle 6.0+) or {@link org.gradle.api.Project#copy} if * the version of Gradle is below 6.0. */ +@CompileStatic interface CopyActionFacade { WorkResult copy(Action var1); + @CompileStatic class ProjectBased implements CopyActionFacade { private final Project project; @@ -58,6 +61,7 @@ public WorkResult copy(Action action) { } } + @CompileStatic abstract class FileSystemOperationsBased implements CopyActionFacade { @Inject public abstract FileSystemOperations getFileSystemOperations(); diff --git a/src/main/groovy/com/google/protobuf/gradle/ExecutableLocator.groovy b/src/main/groovy/com/google/protobuf/gradle/ExecutableLocator.groovy index 13256367..6927ce95 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ExecutableLocator.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ExecutableLocator.groovy @@ -28,7 +28,7 @@ */ package com.google.protobuf.gradle -import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic import org.gradle.api.Named /** @@ -37,7 +37,7 @@ import org.gradle.api.Named * configured, the plugin should try to run the executable from system search * path. */ -@CompileDynamic +@CompileStatic class ExecutableLocator implements Named { private final String name diff --git a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy index cbf51b5b..940f943e 100644 --- a/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/GenerateProtoTask.groovy @@ -29,8 +29,6 @@ */ package com.google.protobuf.gradle -import static java.nio.charset.StandardCharsets.US_ASCII - import com.google.common.base.Preconditions import com.google.common.collect.ImmutableList import groovy.transform.CompileDynamic @@ -68,6 +66,8 @@ import org.gradle.util.ConfigureUtil import javax.annotation.Nullable import javax.inject.Inject +import static java.nio.charset.StandardCharsets.US_ASCII + /** * The task that compiles proto files into Java files. */ @@ -98,9 +98,11 @@ public abstract class GenerateProtoTask extends DefaultTask { // accidentally modifying them. private String outputBaseDir // Tags for selectors inside protobuf.generateProtoTasks; do not serialize with Gradle configuration caching - @SuppressWarnings("UnnecessaryTransientModifier") // It is not necessary for task to implement Serializable + @SuppressWarnings("UnnecessaryTransientModifier") + // It is not necessary for task to implement Serializable transient private SourceSet sourceSet - @SuppressWarnings("UnnecessaryTransientModifier") // It is not necessary for task to implement Serializable + @SuppressWarnings("UnnecessaryTransientModifier") + // It is not necessary for task to implement Serializable transient private Object variant private ImmutableList flavors private String buildType @@ -183,7 +185,7 @@ public abstract class GenerateProtoTask extends DefaultTask { int baseCmdLength = baseCmd.sum { it.length() + CMD_ARGUMENT_EXTRA_LENGTH } List currentArgs = [] int currentArgsLength = 0 - for (File proto: protoFiles) { + for (File proto : protoFiles) { String protoFileName = proto int currentFileLength = protoFileName.length() + CMD_ARGUMENT_EXTRA_LENGTH // Check if appending the next proto string will overflow the cmd length limit @@ -263,14 +265,14 @@ public abstract class GenerateProtoTask extends DefaultTask { void setSourceSet(SourceSet sourceSet) { checkInitializing() Preconditions.checkState(!isAndroidProject.get(), - 'sourceSet should not be set in an Android project') + 'sourceSet should not be set in an Android project') this.sourceSet = sourceSet } void setVariant(Object variant, boolean isTestVariant) { checkInitializing() Preconditions.checkState(isAndroidProject.get(), - 'variant should not be set in a Java project') + 'variant should not be set in a Java project') this.variant = variant this.isTestVariant = isTestVariant } @@ -278,14 +280,14 @@ public abstract class GenerateProtoTask extends DefaultTask { void setFlavors(ImmutableList flavors) { checkInitializing() Preconditions.checkState(isAndroidProject.get(), - 'flavors should not be set in a Java project') + 'flavors should not be set in a Java project') this.flavors = flavors } void setBuildType(String buildType) { checkInitializing() Preconditions.checkState(isAndroidProject.get(), - 'buildType should not be set in a Java project') + 'buildType should not be set in a Java project') this.buildType = buildType } @@ -297,7 +299,7 @@ public abstract class GenerateProtoTask extends DefaultTask { @Internal("Inputs tracked in getSourceFiles()") SourceSet getSourceSet() { Preconditions.checkState(!isAndroidProject.get(), - 'sourceSet should not be used in an Android project') + 'sourceSet should not be used in an Android project') Preconditions.checkNotNull(sourceSet, 'sourceSet is not set') return sourceSet } @@ -319,7 +321,7 @@ public abstract class GenerateProtoTask extends DefaultTask { @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") Object getVariant() { Preconditions.checkState(isAndroidProject.get(), - 'variant should not be used in a Java project') + 'variant should not be used in a Java project') Preconditions.checkNotNull(variant, 'variant is not set') return variant } @@ -375,7 +377,7 @@ public abstract class GenerateProtoTask extends DefaultTask { Provider> getReleaseDependenciesMapping() { providerFactory.provider { locatorToDependencyMapping.get() - .findAll { entry -> ! entry.value.endsWith ("-SNAPSHOT") } + .findAll { entry -> !entry.value.endsWith("-SNAPSHOT") } } } @@ -402,7 +404,7 @@ public abstract class GenerateProtoTask extends DefaultTask { @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") boolean getIsTestVariant() { Preconditions.checkState(isAndroidProject.get(), - 'isTestVariant should not be used in a Java project') + 'isTestVariant should not be used in a Java project') Preconditions.checkNotNull(variant, 'variant is not set') return isTestVariant } @@ -410,7 +412,7 @@ public abstract class GenerateProtoTask extends DefaultTask { @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") ImmutableList getFlavors() { Preconditions.checkState(isAndroidProject.get(), - 'flavors should not be used in a Java project') + 'flavors should not be used in a Java project') Preconditions.checkNotNull(flavors, 'flavors is not set') return flavors } @@ -418,10 +420,10 @@ public abstract class GenerateProtoTask extends DefaultTask { @Internal("Not an actual input to the task, only used to find tasks belonging to a variant") String getBuildType() { Preconditions.checkState(isAndroidProject.get(), - 'buildType should not be used in a Java project') + 'buildType should not be used in a Java project') Preconditions.checkState( - variant.name == 'test' || buildType, - 'buildType is not set and task is not for local unit test variant') + variant.name == 'test' || buildType, + 'buildType is not set and task is not for local unit test variant') return buildType } @@ -439,7 +441,7 @@ public abstract class GenerateProtoTask extends DefaultTask { String getDescriptorPath() { if (!generateDescriptorSet) { throw new IllegalStateException( - "requested descriptor path but descriptor generation is off") + "requested descriptor path but descriptor generation is off") } return descriptorSetOptions.path != null ? descriptorSetOptions.path : "${outputBaseDir}/descriptor_set.desc" } @@ -637,7 +639,7 @@ public abstract class GenerateProtoTask extends DefaultTask { logger.debug "ProtobufCompile using files ${protoFiles}" String protocPath = computeExecutablePath(protocLocator.get()) - List baseCmd = [ protocPath ] + List baseCmd = [protocPath] baseCmd.addAll(dirs) // Handle code generation built-ins @@ -720,7 +722,7 @@ public abstract class GenerateProtoTask extends DefaultTask { private void checkCanConfig() { Preconditions.checkState(state == State.CONFIG || state == State.INIT, - 'Should not be called after configuration has finished') + 'Should not be called after configuration has finished') } private void compileFiles(List cmd) { @@ -769,16 +771,16 @@ public abstract class GenerateProtoTask extends DefaultTask { throw new GradleException(".jar protoc plugin path '${jarAbsolutePath}' has no file name") } File scriptExecutableFile = new File("${projectLayout.buildDirectory.get()}/scripts/" + - jarFileName[0..(jarFileName.length() - JAR_SUFFIX.length() - 1)] + "-${getName()}-trampoline." + - (isWindows ? "bat" : "sh")) + jarFileName[0..(jarFileName.length() - JAR_SUFFIX.length() - 1)] + "-${getName()}-trampoline." + + (isWindows ? "bat" : "sh")) try { mkdirsForFile(scriptExecutableFile) String javaExe = computeJavaExePath(isWindows) // Rewrite the trampoline file unconditionally (even if it already exists) in case the dependency or versioning // changes we don't need to detect the delta (and the file content is cheap to re-generate). String trampoline = isWindows ? - "@ECHO OFF\r\n\"${escapePathWindows(javaExe)}\" -jar \"${escapePathWindows(jarAbsolutePath)}\" %*\r\n" : - "#!/bin/sh\nexec '${escapePathUnix(javaExe)}' -jar '${escapePathUnix(jarAbsolutePath)}' \"\$@\"\n" + "@ECHO OFF\r\n\"${escapePathWindows(javaExe)}\" -jar \"${escapePathWindows(jarAbsolutePath)}\" %*\r\n" : + "#!/bin/sh\nexec '${escapePathUnix(javaExe)}' -jar '${escapePathUnix(jarAbsolutePath)}' \"\$@\"\n" scriptExecutableFile.write(trampoline, US_ASCII.name()) setExecutableOrFail(scriptExecutableFile) logger.info("Resolved artifact jar: ${jarAbsolutePath}. Created trampoline file: ${scriptExecutableFile}") diff --git a/src/main/groovy/com/google/protobuf/gradle/ProtobufConvention.groovy b/src/main/groovy/com/google/protobuf/gradle/ProtobufConvention.groovy index 0a5c0397..92a0c3c9 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ProtobufConvention.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ProtobufConvention.groovy @@ -29,7 +29,7 @@ */ package com.google.protobuf.gradle -import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic import org.gradle.api.Project import org.gradle.api.internal.file.FileResolver import org.gradle.util.ConfigureUtil @@ -37,7 +37,7 @@ import org.gradle.util.ConfigureUtil /** * Adds the protobuf {} block as a property of the project. */ -@CompileDynamic +@CompileStatic class ProtobufConvention { ProtobufConvention(Project project, FileResolver fileResolver) { protobuf = new ProtobufConfigurator(project, fileResolver) diff --git a/src/main/groovy/com/google/protobuf/gradle/ToolsLocator.groovy b/src/main/groovy/com/google/protobuf/gradle/ToolsLocator.groovy index d3113ed1..ff7cf903 100644 --- a/src/main/groovy/com/google/protobuf/gradle/ToolsLocator.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/ToolsLocator.groovy @@ -28,7 +28,8 @@ */ package com.google.protobuf.gradle -import groovy.transform.CompileDynamic +import com.google.gradle.osdetector.OsDetector +import groovy.transform.CompileStatic import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project import org.gradle.api.artifacts.Configuration @@ -38,12 +39,12 @@ import org.gradle.api.file.FileCollection /** * Holds locations of all external executables, i.e., protoc and plugins. */ -@CompileDynamic +@CompileStatic class ToolsLocator { private final Project project - private final ExecutableLocator protoc - private final NamedDomainObjectContainer plugins + final ExecutableLocator protoc + final NamedDomainObjectContainer plugins static List artifactParts(String artifactCoordinate) { String artifact @@ -53,11 +54,14 @@ class ToolsLocator { String version String classifier - (artifact, extension) = artifactCoordinate.tokenize('@') + List artifactCoordinateTokenized = artifactCoordinate.tokenize('@') + (artifact, extension) = [artifactCoordinateTokenized[0], artifactCoordinateTokenized[1]] if (extension == null && artifactCoordinate.endsWith('@')) { extension = '' } - (group, name, version, classifier) = artifact.tokenize(':') + List artifactTokenized = artifact.tokenize(':') + (group, name, version, classifier) = + [artifactTokenized[0], artifactTokenized[1], artifactTokenized[2], artifactTokenized[3]] return [group, name, version, classifier, extension] } @@ -92,19 +96,20 @@ class ToolsLocator { void registerDependencyWithTasks(ExecutableLocator locator, Collection protoTasks) { // create a project configuration dependency for the artifact - Configuration config = project.configurations.create("protobufToolsLocator_${locator.name}") { - visible = false - transitive = false - extendsFrom = [] + Configuration config = project.configurations.create("protobufToolsLocator_${locator.name}") { Configuration conf -> + conf.visible = false + conf.transitive = false } String groupId, artifact, version, classifier, extension - (groupId, artifact, version, classifier, extension) = artifactParts(locator.artifact) + OsDetector osdetector = project.extensions.getByName("osdetector") as OsDetector + List parts = artifactParts(locator.artifact) + (groupId, artifact, version, classifier, extension) = [parts[0], parts[1], parts[2], parts[3], parts[4]] Map notation = [ - group:groupId, - name:artifact, - version:version, - classifier:classifier ?: project.osdetector.classifier, - ext:extension ?: 'exe', + group:groupId, + name:artifact, + version:version, + classifier:classifier ?: osdetector.classifier, + ext:extension ?: 'exe', ] Dependency dep = project.dependencies.add(config.name, notation) FileCollection artifactFiles = config.fileCollection(dep) diff --git a/src/main/groovy/com/google/protobuf/gradle/Utils.groovy b/src/main/groovy/com/google/protobuf/gradle/Utils.groovy index 80c84681..2c6e1a3f 100644 --- a/src/main/groovy/com/google/protobuf/gradle/Utils.groovy +++ b/src/main/groovy/com/google/protobuf/gradle/Utils.groovy @@ -29,7 +29,7 @@ package com.google.protobuf.gradle import com.google.common.base.Preconditions -import groovy.transform.CompileDynamic +import groovy.transform.CompileStatic import org.apache.commons.lang.StringUtils import org.gradle.api.GradleException import org.gradle.api.Project @@ -43,7 +43,7 @@ import java.util.regex.Matcher /** * Utility classes. */ -@CompileDynamic +@CompileStatic class Utils { /** * Returns the conventional name of a configuration for a sourceSet