Skip to content

Commit

Permalink
Remove addSourcesToIde, believe in sourceSet.source(generateProto) magic
Browse files Browse the repository at this point in the history
  • Loading branch information
rougsig committed Aug 21, 2022
1 parent c5ea9da commit 416f13f
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 157 deletions.
48 changes: 0 additions & 48 deletions src/main/groovy/com/google/protobuf/gradle/ProtobufPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ import org.gradle.api.file.CopySpec
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.plugins.AppliedPlugin
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.SourceSet
import org.gradle.language.jvm.tasks.ProcessResources
Expand Down Expand Up @@ -158,9 +157,6 @@ class ProtobufPlugin implements Plugin<Project> {
// protoc and codegen plugin configuration may change through the protobuf{}
// block. Only at this point the configuration has been finalized.
project.protobuf.tools.resolve(project)

// Register proto and generated sources with IDE
addSourcesToIde(isAndroid)
}
}

Expand Down Expand Up @@ -437,48 +433,4 @@ class ProtobufPlugin implements Plugin<Project> {
private String getExtractedProtosDir(String sourceSetName) {
return "${project.buildDir}/extracted-protos/${sourceSetName}"
}

/**
* Adds proto sources and generated sources to supported IDE plugins.
*/
private void addSourcesToIde(boolean isAndroid) {
// The generated javalite sources have lint issues. This is fixed upstream but
// there is still no release with the fix yet.
// https://github.com/google/protobuf/pull/2823

// TODO(zpencer): add gen sources from cross project GenerateProtoTasks
// This is an uncommon project set up but it is possible.
// We must avoid using private android APIs to find subprojects that the variant depends
// on, such as by walking through
// variant.variantData.variantDependency.compileConfiguration.allDependencies
// Gradle.getTaskGraph().getDependencies() should allow us to walk the task graph,
// but unfortunately that API is @Incubating. We can revisit it when it becomes stable.
// https://docs.gradle.org/4.8/javadoc/org/gradle/api/execution/
// TaskExecutionGraph.html#getDependencies-org.gradle.api.Task-

// TODO(zpencer): find a way to make android studio aware of the .proto files
// Simply adding the .proto dirs via addJavaSourceFoldersToModel does not seem to work.

if (!isAndroid) {
// Make the proto source dirs known to IDEs
project.convention.getPlugin(JavaPluginConvention).sourceSets.each { sourceSet ->
SourceDirectorySet protoSrcDirSet = sourceSet.extensions.getByName('proto') as SourceDirectorySet
protoSrcDirSet.srcDirs.each { File protoDir ->
Utils.addToIdeSources(project, Utils.isTest(sourceSet.name), protoDir, false)
}
}
// Make the extracted proto dirs known to IDEs
project.tasks.withType(ProtobufExtract).each { ProtobufExtract extractProtoTask ->
Utils.addToIdeSources(project, extractProtoTask.isTest.get(), extractProtoTask.destDir.get().asFile, true)
}
// Make the generated code dirs known to IDEs
project.tasks.withType(GenerateProtoTask).each { GenerateProtoTask generateProtoTask ->
generateProtoTask.getOutputSourceDirectories().each { File outputDir ->
Utils.addToIdeSources(project, generateProtoTask.isTest, outputDir, true)
Utils.addToEclipseSources(project, generateProtoTask.isTest,
generateProtoTask.sourceSet.name, outputDir)
}
}
}
}
}
109 changes: 0 additions & 109 deletions src/main/groovy/com/google/protobuf/gradle/Utils.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@ import groovy.transform.CompileStatic
import org.apache.commons.lang.StringUtils
import org.gradle.api.Project
import org.gradle.api.tasks.SourceSet
import org.gradle.plugins.ide.eclipse.model.Classpath
import org.gradle.plugins.ide.eclipse.model.ClasspathEntry
import org.gradle.plugins.ide.eclipse.model.EclipseModel
import org.gradle.plugins.ide.eclipse.model.SourceFolder
import org.gradle.plugins.ide.idea.GenerateIdeaModule
import org.gradle.plugins.ide.idea.model.IdeaModel
import org.gradle.util.GUtil

/**
Expand Down Expand Up @@ -107,107 +101,4 @@ class Utils {
sourceSetOrVariantName.toLowerCase().contains('androidtest') ||
sourceSetOrVariantName.toLowerCase().contains('unittest')
}

/**
* Adds the file to the IDE plugin's set of sources / resources. If the directory does
* not exist, it will be created before the IDE task is run.
*/
static void addToIdeSources(Project project, boolean isTest, File f, boolean isGenerated) {
project.plugins.withId("idea") {
IdeaModel model = project.getExtensions().findByType(IdeaModel)
if (isTest) {
model.module.testSourceDirs += f
} else {
model.module.sourceDirs += f
}
if (isGenerated) {
model.module.generatedSourceDirs += f
}
project.tasks.withType(GenerateIdeaModule).each {
it.doFirst {
// This is required because the intellij plugin does not allow adding source directories
// that do not exist. The intellij config files should be valid from the start even if a
// user runs './gradlew idea' before running './gradlew generateProto'.
f.mkdirs()
}
}
}
}

/**
* Add the the folder of generated source to Eclipse .classpath file.
*/
static void addToEclipseSources(Project project, boolean isTest, String sourceSetName, File f) {
project.plugins.withId("eclipse") {
File projectDir = project.getProjectDir()

EclipseModel model = project.getExtensions().findByType(EclipseModel)
model.classpath.file.whenMerged { Classpath cp ->
// buildship requires the folder exists on disk, otherwise
// it will be ignored when updating classpath file, see:
// https://github.com/eclipse/buildship/issues/1196
f.mkdirs()

String relativePath = projectDir.toURI().relativize(f.toURI()).getPath()
// remove trailing slash
if (relativePath.endsWith("/")) {
relativePath = relativePath[0..(relativePath.length() - 1)]
}
SourceFolder entry = new SourceFolder(relativePath, getOutputPath(cp, sourceSetName))
entry.entryAttributes.put("optional", "true")
entry.entryAttributes.put("ignore_optional_problems", "true")

entry.entryAttributes.put("gradle_scope", isTest ? "test" : "main")
entry.entryAttributes.put("gradle_used_by_scope", isTest ? "test" : "main,test")

// this attribute is optional, but it could be useful for IDEs to recognize that it is
// generated source folder from protobuf, thus providing some support for that.
// e.g. Hint user to run generate tasks if the folder is empty or does not exist.
entry.entryAttributes.put("protobuf_generated_source", "true")

// check if output is not null here because test source folder
// must have a separate output folder in Eclipse
if (entry.output != null && isTest) {
entry.entryAttributes.put("test", "true")
}
cp.entries.add(entry)
}
}
}

/**
* Get the output path according to the source set name, if no valid path can be
* found, <code>null</code> will return.
*/
private static String getOutputPath(Classpath classpath, String sourceSetName) {
String path = "bin/" + sourceSetName
if (isValidOutput(classpath, path)) {
return path
}
// fallback to default output
return null
}

/**
* Check if the output path is valid or not.
* See: org.eclipse.jdt.internal.core.ClasspathEntry#validateClasspath()
*/
private static boolean isValidOutput(Classpath classpath, String path) {
Set<String> outputs = [] as Set<String>
for (ClasspathEntry cpe : classpath.getEntries()) {
if (cpe instanceof SourceFolder) {
outputs.add(((SourceFolder) cpe).getOutput())
}
}
for (String output : outputs) {
if (Objects.equals(output, path)) {
continue
}
// Eclipse does not allow nested output path
if (output.startsWith(path) || path.startsWith(output)) {
return false
}
}
return true
}
}

0 comments on commit 416f13f

Please sign in to comment.