Browse Source

Port javadoc configuration logic into a binary plugin (#86471)

Also adding test coverage and fixing certain issues we stumbled into

when resolving project dependencies of compileClasspath we need to use allDependencies instead of dependencies as usually no dependencies are added directly to compileClasspath but via implementation, compileonly and api and friends
Fixed javadoc setup for projects using shadowed dependencies via shadow plugin
Fixed dealing with skipped javadoc tasks in referenced dependent projects.
In general this PR only fixes expected javadoc generation as it was intended before this PR.

This also contains some tweaks to our gradle integration test fixtures for setting up and debugging test projects
Rene Groeschke 3 years ago
parent
commit
8bbc7c2e0b

+ 1 - 1
build-conventions/build.gradle

@@ -66,7 +66,7 @@ dependencies {
     api 'gradle.plugin.com.github.johnrengelman:shadow:7.1.2'
     api 'org.apache.rat:apache-rat:0.11'
     compileOnly "com.puppycrawl.tools:checkstyle:9.3"
-    api('com.diffplug.spotless:spotless-plugin-gradle:6.4.0') {
+    api('com.diffplug.spotless:spotless-plugin-gradle:6.5.2') {
       exclude module: "groovy-xml"
     }
 }

+ 4 - 0
build-tools-internal/build.gradle

@@ -103,6 +103,10 @@ gradlePlugin {
       id = 'elasticsearch.internal-test-rerun'
       implementationClass = 'org.elasticsearch.gradle.internal.test.rerun.TestRerunPlugin'
     }
+    javaDoc {
+      id = 'elasticsearch.java-doc'
+      implementationClass = 'org.elasticsearch.gradle.internal.ElasticsearchJavadocPlugin'
+    }
     java {
       id = 'elasticsearch.java'
       implementationClass = 'org.elasticsearch.gradle.internal.ElasticsearchJavaPlugin'

+ 5 - 5
build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/fixtures/AbstractRestResourcesFuncTest.groovy

@@ -12,10 +12,10 @@ package org.elasticsearch.gradle.fixtures;
 abstract class AbstractRestResourcesFuncTest extends AbstractGradleFuncTest {
 
     def setup() {
-        addSubProject(":test:framework") << "apply plugin: 'elasticsearch.java'"
-        addSubProject(":test:yaml-rest-runner") << "apply plugin: 'elasticsearch.java'"
+        subProject(":test:framework") << "apply plugin: 'elasticsearch.java'"
+        subProject(":test:yaml-rest-runner") << "apply plugin: 'elasticsearch.java'"
 
-        addSubProject(":rest-api-spec") << """
+        subProject(":rest-api-spec") << """
         configurations { restSpecs\nrestTests }
         artifacts {
           restSpecs(new File(projectDir, "src/main/resources/rest-api-spec/api"))
@@ -23,14 +23,14 @@ abstract class AbstractRestResourcesFuncTest extends AbstractGradleFuncTest {
         }
         """
 
-        addSubProject(":x-pack:plugin") << """
+        subProject(":x-pack:plugin") << """
         configurations { restXpackSpecs\nrestXpackTests }
         artifacts {
           restXpackTests(new File(projectDir, "src/yamlRestTest/resources/rest-api-spec/test"))
         }
         """
 
-        addSubProject(":distribution:archives:integ-test-zip") << "configurations { extracted }"
+        subProject(":distribution:archives:integ-test-zip") << "configurations { extracted }"
     }
 
     void setupRestResources(List<String> apis, List<String> tests = [], List<String> xpackTests = []) {

+ 203 - 0
build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/ElasticsearchJavadocPluginFuncTest.groovy

@@ -0,0 +1,203 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal
+
+import org.elasticsearch.gradle.fixtures.AbstractGradleFuncTest
+import org.gradle.testkit.runner.TaskOutcome
+import spock.lang.Unroll
+
+class ElasticsearchJavadocPluginFuncTest extends AbstractGradleFuncTest {
+
+    @Unroll
+    def "#versionType created javadoc with inter project linking"() {
+        given:
+        someLibProject()
+        subProject("some-depending-lib") {
+            buildFile << """               
+                plugins {
+                    id 'elasticsearch.java-doc'
+                    id 'java'
+                }
+                group = 'org.acme.depending'
+                
+                dependencies {
+                    implementation project(':some-lib')
+                }
+            """
+            classFile('org.acme.depending.SomeDepending') << """
+                package org.acme.depending;
+                
+                import org.acme.Something;
+                
+                public class SomeDepending {
+                    public Something createSomething() {
+                        return new Something();
+                    }
+                }
+            """
+        }
+        buildFile << """
+            allprojects {
+                version = '$version'
+            }
+        """
+        when:
+        def result = gradleRunner(':some-depending-lib:javadoc').build()
+        then:
+        result.task(":some-lib:javadoc").outcome == TaskOutcome.SUCCESS
+        result.task(":some-depending-lib:javadoc").outcome == TaskOutcome.SUCCESS
+
+        def options = file('some-depending-lib/build/tmp/javadoc/javadoc.options').text
+        options.contains('-notimestamp')
+        options.contains('-quiet')
+        options.contains("-linkoffline '$expectedLink' '${file('some-lib/build/docs/javadoc/').canonicalPath}/'")
+
+        where:
+        version        | versionType | expectedLink
+        '1.0'          | 'release'   | "https://artifacts.elastic.co/javadoc/org/acme/some-lib/$version"
+        '1.0-SNAPSHOT' | 'snapshot'  | "https://snapshots.elastic.co/javadoc/org/acme/some-lib/$version"
+    }
+
+    def "sources of shadowed dependencies are added to projects javadoc"() {
+        given:
+        someLibProject() << """version = 1.0"""
+        subProject("some-depending-lib") {
+            buildFile << """               
+                plugins {
+                    id 'elasticsearch.java-doc'
+                    id 'com.github.johnrengelman.shadow' version '7.1.2'
+                    id 'java'
+                }
+                group = 'org.acme.depending'
+                
+                dependencies {
+                    implementation project(':some-lib')
+                    shadow project(':some-shadowed-lib')
+                }
+            """
+            classFile('org.acme.depending.SomeDepending') << """
+                package org.acme.depending;
+                
+                import org.acme.Something;
+                
+                public class SomeDepending {
+                    public Something createSomething() {
+                        return new Something();
+                    }
+                }
+            """
+            classFile('org.acme.depending.SomeShadowedDepending') << """
+                package org.acme.depending;
+                
+                import org.acme.shadowed.Shadowed;
+                
+                public class SomeShadowedDepending {
+                    public Shadowed createShadowed() {
+                        return new Shadowed();
+                    }
+                }
+            """
+        }
+        subProject("some-shadowed-lib") {
+            buildFile << """
+                plugins {
+                    id 'elasticsearch.java-doc'
+                    id 'java'
+                }
+                group = 'org.acme.shadowed'
+            """
+            classFile('org.acme.shadowed.Shadowed') << """
+                package org.acme.shadowed;
+                
+                public class Shadowed {
+                }
+            """
+        }
+        when:
+        def result = gradleRunner(':some-depending-lib:javadoc').build()
+
+        then:
+
+        def options = file('some-depending-lib/build/tmp/javadoc/javadoc.options').text
+        options.contains('-notimestamp')
+        options.contains('-quiet')
+
+        // normal dependencies handles as usual
+        result.task(":some-lib:javadoc").outcome == TaskOutcome.SUCCESS
+        options.contains("-linkoffline 'https://artifacts.elastic.co/javadoc/org/acme/some-lib/1.0' '${file('some-lib/build/docs/javadoc/').canonicalPath}/'")
+        file('some-depending-lib/build/docs/javadoc/org/acme/Something.html').exists() == false
+
+        // source of shadowed dependencies are inlined
+        result.task(":some-shadowed-lib:javadoc") == null
+        file('some-depending-lib/build/docs/javadoc/org/acme/shadowed/Shadowed.html').exists()
+        normalized(file('some-depending-lib/build/docs/javadoc/element-list').text) == 'org.acme.depending\norg.acme.shadowed'
+    }
+
+    def "ignores skipped javadocs of dependent projects"() {
+        given:
+        someLibProject() << """
+            version = '1.0'
+            tasks.named("javadoc").configure { enabled = false }
+        """
+        subProject("some-depending-lib") {
+            buildFile << """               
+                plugins {
+                    id 'elasticsearch.java-doc'
+                    id 'java'
+                }
+                group = 'org.acme.depending'
+                
+                dependencies {
+                    implementation project(':some-lib')
+                }
+            """
+            classFile('org.acme.depending.SomeDepending') << """
+                package org.acme.depending;
+                
+                import org.acme.Something;
+                
+                public class SomeDepending {
+                    public Something createSomething() {
+                        return new Something();
+                    }
+                }
+            """
+        }
+        when:
+        def result = gradleRunner(':some-depending-lib:javadoc').build()
+        then:
+        result.task(":some-lib:javadoc").outcome == TaskOutcome.SKIPPED
+        result.task(":some-depending-lib:javadoc").outcome == TaskOutcome.SUCCESS
+
+        def options = file('some-depending-lib/build/tmp/javadoc/javadoc.options').text
+        options.contains('-notimestamp')
+        options.contains('-quiet')
+        options.contains("-linkoffline 'https://artifacts.elastic.co/javadoc/org/acme/some-lib/1.0' '${file('some-lib/build/docs/javadoc/').canonicalPath}/'") == false
+    }
+
+
+    private File someLibProject() {
+        subProject("some-lib") {
+            buildFile << """
+                plugins {
+                    id 'elasticsearch.java-doc'
+                    id 'java'
+                }
+                group = 'org.acme'
+                """
+
+            classFile('org.acme.Something') << """
+                package org.acme;
+                
+                public class Something {
+                }
+            """
+        }
+    }
+}

+ 1 - 3
build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/PublishPluginFuncTest.groovy

@@ -10,16 +10,14 @@ package org.elasticsearch.gradle.internal
 
 import org.elasticsearch.gradle.fixtures.AbstractGradleFuncTest
 import org.gradle.testkit.runner.TaskOutcome
-import org.junit.Ignore
 import org.xmlunit.builder.DiffBuilder
 import org.xmlunit.builder.Input
-import spock.lang.IgnoreRest
 
 class PublishPluginFuncTest extends AbstractGradleFuncTest {
 
     def setup() {
         // required for JarHell to work
-        addSubProject(":libs:elasticsearch-core") << "apply plugin:'java'"
+        subProject(":libs:elasticsearch-core") << "apply plugin:'java'"
     }
     def "artifacts and tweaked pom is published"() {
         given:

+ 1 - 1
build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/test/rest/InternalYamlRestTestPluginFuncTest.groovy

@@ -89,7 +89,7 @@ class InternalYamlRestTestPluginFuncTest extends AbstractRestResourcesFuncTest {
         localDistroSetup()
         def distroVersion = VersionProperties.getElasticsearch()
 
-        def subProjectBuildFile = addSubProject(pluginProjectPath)
+        def subProjectBuildFile = subProject(pluginProjectPath)
         subProjectBuildFile << """
             apply plugin: 'elasticsearch.esplugin'
             apply plugin: 'elasticsearch.internal-yaml-rest-test'

+ 4 - 4
build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/test/rest/YamlRestCompatTestPluginFuncTest.groovy

@@ -30,7 +30,7 @@ class YamlRestCompatTestPluginFuncTest extends AbstractRestResourcesFuncTest {
 
     def "yamlRestTestVxCompatTest does nothing when there are no tests"() {
         given:
-        addSubProject(":distribution:bwc:maintenance") << """
+        subProject(":distribution:bwc:maintenance") << """
         configurations { checkout }
         artifacts {
             checkout(new File(projectDir, "checkoutDir"))
@@ -57,7 +57,7 @@ class YamlRestCompatTestPluginFuncTest extends AbstractRestResourcesFuncTest {
         given:
         internalBuild()
 
-        addSubProject(":distribution:bwc:maintenance") << """
+        subProject(":distribution:bwc:maintenance") << """
         configurations { checkout }
         artifacts {
             checkout(new File(projectDir, "checkoutDir"))
@@ -136,7 +136,7 @@ class YamlRestCompatTestPluginFuncTest extends AbstractRestResourcesFuncTest {
     def "yamlRestTestVxCompatTest is wired into check and checkRestCompat"() {
         given:
 
-        addSubProject(":distribution:bwc:maintenance") << """
+        subProject(":distribution:bwc:maintenance") << """
         configurations { checkout }
         artifacts {
             checkout(new File(projectDir, "checkoutDir"))
@@ -180,7 +180,7 @@ class YamlRestCompatTestPluginFuncTest extends AbstractRestResourcesFuncTest {
         given:
         internalBuild()
 
-        addSubProject(":distribution:bwc:maintenance") << """
+        subProject(":distribution:bwc:maintenance") << """
         configurations { checkout }
         artifacts {
             checkout(new File(projectDir, "checkoutDir"))

+ 1 - 0
build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BuildPlugin.java

@@ -57,6 +57,7 @@ public class BuildPlugin implements Plugin<Project> {
 
         project.getPluginManager().apply("elasticsearch.java");
         project.getPluginManager().apply("elasticsearch.publish");
+        project.getPluginManager().apply(ElasticsearchJavadocPlugin.class);
         project.getPluginManager().apply(DependenciesInfoPlugin.class);
         project.getPluginManager().apply(DependenciesGraphPlugin.class);
         InternalPrecommitTasks.create(project, true);

+ 134 - 0
build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/ElasticsearchJavadocPlugin.java

@@ -0,0 +1,134 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+package org.elasticsearch.gradle.internal;
+
+import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin;
+
+import org.gradle.api.Action;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.Dependency;
+import org.gradle.api.artifacts.ProjectDependency;
+import org.gradle.api.plugins.BasePluginExtension;
+import org.gradle.api.plugins.JavaPlugin;
+import org.gradle.api.tasks.javadoc.Javadoc;
+import org.gradle.external.javadoc.JavadocOfflineLink;
+import org.gradle.external.javadoc.StandardJavadocDocletOptions;
+
+import java.io.File;
+import java.util.Comparator;
+import java.util.List;
+
+// Handle javadoc dependencies across projects. Order matters: the linksOffline for
+// org.elasticsearch:elasticsearch must be the last one or all the links for the
+// other packages (e.g org.elasticsearch.client) will point to server rather than
+// their own artifacts.
+public class ElasticsearchJavadocPlugin implements Plugin<Project> {
+    private Project project;
+
+    @Override
+    public void apply(Project project) {
+        this.project = project;
+        // ignore missing javadocs
+        project.getTasks().withType(Javadoc.class).configureEach(javadoc -> {
+            // the -quiet here is because of a bug in gradle, in that adding a string option
+            // by itself is not added to the options. By adding quiet, both this option and
+            // the "value" -quiet is added, separated by a space. This is ok since the javadoc
+            // command already adds -quiet, so we are just duplicating it
+            // see https://discuss.gradle.org/t/add-custom-javadoc-option-that-does-not-take-an-argument/5959
+            javadoc.getOptions().setEncoding("UTF8");
+            ((StandardJavadocDocletOptions) javadoc.getOptions()).addStringOption("Xdoclint:all,-missing", "-quiet");
+        });
+
+        // Relying on configurations introduced by the java plugin
+        this.project.getPlugins().withType(JavaPlugin.class, javaPlugin -> project.afterEvaluate(project1 -> {
+            var withShadowPlugin = project1.getPlugins().hasPlugin(ShadowPlugin.class);
+            var compileClasspath = project.getConfigurations().getByName("compileClasspath");
+
+            if (withShadowPlugin) {
+                var shadowConfiguration = project.getConfigurations().getByName("shadow");
+                var shadowedDependencies = shadowConfiguration.getAllDependencies();
+                var nonShadowedCompileClasspath = compileClasspath.copyRecursive(
+                    dependency -> shadowedDependencies.contains(dependency) == false
+                );
+                configureJavadocForConfiguration(false, nonShadowedCompileClasspath);
+                configureJavadocForConfiguration(true, shadowConfiguration);
+            } else {
+                configureJavadocForConfiguration(false, compileClasspath);
+            }
+        }));
+    }
+
+    private void configureJavadocForConfiguration(boolean shadow, Configuration configuration) {
+        configuration.getAllDependencies()
+            .stream()
+            .sorted(Comparator.comparing(Dependency::getGroup))
+            .filter(d -> d instanceof ProjectDependency)
+            .map(d -> (ProjectDependency) d)
+            .filter(p -> p.getDependencyProject() != null)
+            .forEach(projectDependency -> configureDependency(shadow, projectDependency));
+    }
+
+    private void configureDependency(boolean shadowed, ProjectDependency dep) {
+        var upstreamProject = dep.getDependencyProject();
+        if (shadowed) {
+            /*
+             * Include the source of shadowed upstream projects so we don't
+             * have to publish their javadoc.
+             */
+            project.evaluationDependsOn(upstreamProject.getPath());
+            project.getTasks().named("javadoc", Javadoc.class).configure(javadoc -> {
+                Javadoc upstreamJavadoc = upstreamProject.getTasks().named("javadoc", Javadoc.class).get();
+                javadoc.setSource(javadoc.getSource().plus(upstreamJavadoc.getSource()));
+                javadoc.setClasspath(javadoc.getClasspath().plus(upstreamJavadoc.getClasspath()));
+            });
+            /*
+             * Instead we need the upstream project's javadoc classpath so
+             * we don't barf on the classes that it references.
+             */
+        } else {
+            project.getTasks().named("javadoc", Javadoc.class).configure(javadoc -> {
+                // Link to non-shadowed dependant projects
+                javadoc.dependsOn(upstreamProject.getPath() + ":javadoc");
+                String externalLinkName = upstreamProject.getExtensions().getByType(BasePluginExtension.class).getArchivesName().get();
+                String artifactPath = dep.getGroup().replaceAll("\\.", "/") + '/' + externalLinkName.replaceAll("\\.", "/") + '/' + dep
+                    .getVersion();
+                var options = (StandardJavadocDocletOptions) javadoc.getOptions();
+                options.linksOffline(
+                    artifactHost(project) + "/javadoc/" + artifactPath,
+                    upstreamProject.getBuildDir().getPath() + "/docs/javadoc/"
+                );
+                /*
+                 *some dependent javadoc tasks are explicitly skipped. We need to ignore those external links as
+                 * javadoc would fail otherwise.
+                 * Using Action here instead of lambda to keep gradle happy and don't trigger deprecation
+                 */
+                javadoc.doFirst(new Action<Task>() {
+                    @Override
+                    public void execute(Task task) {
+                        List<JavadocOfflineLink> existingJavadocOfflineLinks = ((StandardJavadocDocletOptions) javadoc.getOptions())
+                            .getLinksOffline()
+                            .stream()
+                            .filter(javadocOfflineLink -> new File(javadocOfflineLink.getPackagelistLoc()).exists())
+                            .toList();
+                        ((StandardJavadocDocletOptions) javadoc.getOptions()).setLinksOffline(existingJavadocOfflineLinks);
+
+                    }
+                });
+
+            });
+        }
+    }
+
+    private String artifactHost(Project project) {
+        return project.getVersion().toString().endsWith("-SNAPSHOT") ? "https://snapshots.elastic.co" : "https://artifacts.elastic.co";
+    }
+}

+ 1 - 1
build-tools/src/integTest/groovy/org/elasticsearch/gradle/TestClustersPluginFuncTest.groovy

@@ -122,7 +122,7 @@ class TestClustersPluginFuncTest extends AbstractGradleFuncTest {
     @Unroll
     def "test cluster #pluginType #propertyName change is detected"() {
         given:
-        addSubProject("test-$pluginType") << """
+        subProject("test-$pluginType") << """
             plugins {
                 id 'elasticsearch.esplugin'
             }

+ 39 - 3
build-tools/src/testFixtures/groovy/org/elasticsearch/gradle/fixtures/AbstractGradleFuncTest.groovy

@@ -8,6 +8,7 @@
 
 package org.elasticsearch.gradle.fixtures
 
+import org.apache.commons.io.FileUtils
 import org.elasticsearch.gradle.internal.test.InternalAwareGradleRunner
 import org.elasticsearch.gradle.internal.test.NormalizeOutputGradleRunner
 import org.gradle.testkit.runner.GradleRunner
@@ -39,9 +40,19 @@ abstract class AbstractGradleFuncTest extends Specification {
             "org.gradle.java.installations.fromEnv=JAVA_HOME,RUNTIME_JAVA_HOME,JAVA15_HOME,JAVA14_HOME,JAVA13_HOME,JAVA12_HOME,JAVA11_HOME,JAVA8_HOME"
     }
 
-    File addSubProject(String subProjectPath) {
+    File subProject(String subProjectPath) {
         def subProjectBuild = file(subProjectPath.replace(":", "/") + "/build.gradle")
-        settingsFile << "include \"${subProjectPath}\"\n"
+        if (subProjectBuild.exists() == false) {
+            settingsFile << "include \"${subProjectPath}\"\n"
+        }
+        subProjectBuild
+    }
+
+    File subProject(String subProjectPath, Closure configAction) {
+        def subProjectBuild = subProject(subProjectPath)
+        configAction.setDelegate(new ProjectConfigurer(subProjectBuild.parentFile))
+        configAction.setResolveStrategy(Closure.DELEGATE_ONLY)
+        configAction.call()
         subProjectBuild
     }
 
@@ -113,7 +124,7 @@ abstract class AbstractGradleFuncTest extends Specification {
     ) {
         buildFile << """plugins {
           id 'elasticsearch.global-build-info'
-          ${extraPlugins.collect {p -> "id '$p'" }.join('\n')}
+          ${extraPlugins.collect { p -> "id '$p'" }.join('\n')}
         }
         import org.elasticsearch.gradle.Architecture
         import org.elasticsearch.gradle.internal.info.BuildParams
@@ -151,4 +162,29 @@ abstract class AbstractGradleFuncTest extends Specification {
             System.err.println("Syserr: " + proc.errorStream.text)
         }
     }
+
+    def cleanup() {
+        if (Boolean.getBoolean('test.keep.samplebuild')) {
+            FileUtils.copyDirectory(testProjectDir.root, new File("build/test-debug/" + testProjectDir.root.name))
+        }
+    }
+
+    static class ProjectConfigurer {
+        private File projectDir
+
+        ProjectConfigurer(File projectDir) {
+            this.projectDir = projectDir
+        }
+
+        File classFile(String fullQualifiedName) {
+            File sourceRoot = new File(projectDir, 'src/main/java');
+            File file = new File(sourceRoot, fullQualifiedName.replace('.', '/') + '.java')
+            file.getParentFile().mkdirs()
+            file
+        }
+
+        File getBuildFile() {
+            return new File(projectDir, 'build.gradle')
+        };
+    }
 }

+ 0 - 65
build.gradle

@@ -182,17 +182,6 @@ allprojects {
 
   ext.bwc_tests_enabled = bwc_tests_enabled
 
-  // ignore missing javadocs
-  tasks.withType(Javadoc).configureEach { Javadoc javadoc ->
-    // the -quiet here is because of a bug in gradle, in that adding a string option
-    // by itself is not added to the options. By adding quiet, both this option and
-    // the "value" -quiet is added, separated by a space. This is ok since the javadoc
-    // command already adds -quiet, so we are just duplicating it
-    // see https://discuss.gradle.org/t/add-custom-javadoc-option-that-does-not-take-an-argument/5959
-    javadoc.options.encoding = 'UTF8'
-    javadoc.options.addStringOption('Xdoclint:all,-missing', '-quiet')
-  }
-
   // eclipse configuration
   apply plugin: 'elasticsearch.eclipse'
 
@@ -270,60 +259,6 @@ allprojects {
         }
       }
     }
-
-
-    // Handle javadoc dependencies across projects. Order matters: the linksOffline for
-    // org.elasticsearch:elasticsearch must be the last one or all the links for the
-    // other packages (e.g org.elasticsearch.client) will point to server rather than
-    // their own artifacts.
-    if (project.plugins.hasPlugin(BuildPlugin) || project.plugins.hasPlugin(PluginBuildPlugin)) {
-      String artifactsHost = VersionProperties.elasticsearch.endsWith("-SNAPSHOT") ? "https://snapshots.elastic.co" : "https://artifacts.elastic.co"
-      Closure sortClosure = { a, b -> b.group <=> a.group }
-      Closure depJavadocClosure = { shadowed, dep ->
-        if ((dep instanceof ProjectDependency) == false) {
-          return
-        }
-        Project upstreamProject = dep.dependencyProject
-        if (upstreamProject == null) {
-          return
-        }
-        if (shadowed) {
-          /*
-           * Include the source of shadowed upstream projects so we don't
-           * have to publish their javadoc.
-           */
-          project.evaluationDependsOn(upstreamProject.path)
-          project.javadoc.source += upstreamProject.javadoc.source
-          /*
-           * Instead we need the upstream project's javadoc classpath so
-           * we don't barf on the classes that it references.
-           */
-          project.javadoc.classpath += upstreamProject.javadoc.classpath
-        } else {
-          // Link to non-shadowed dependant projects
-          project.javadoc.dependsOn "${upstreamProject.path}:javadoc"
-          String externalLinkName = upstreamProject.archivesBaseName
-          String artifactPath = dep.group.replaceAll('\\.', '/') + '/' + externalLinkName.replaceAll('\\.', '/') + '/' + dep.version
-          project.javadoc.options.linksOffline artifactsHost + "/javadoc/" + artifactPath, "${upstreamProject.buildDir}/docs/javadoc/"
-        }
-      }
-      boolean hasShadow = project.plugins.hasPlugin(ShadowPlugin)
-      project.configurations.compileClasspath.dependencies
-              .findAll()
-              .toSorted(sortClosure)
-              .each({ c -> depJavadocClosure(hasShadow, c) })
-      project.configurations.compileOnly.dependencies
-              .findAll()
-              .toSorted(sortClosure)
-              .each({ c -> depJavadocClosure(false, c) })
-      if (hasShadow) {
-        // include any dependencies for shadow JAR projects that are *not* bundled in the shadow JAR
-        project.configurations.shadow.dependencies
-                .findAll()
-                .toSorted(sortClosure)
-                .each({ c -> depJavadocClosure(false, c) })
-      }
-    }
   }
 
   apply plugin: 'elasticsearch.formatting'