From 8375185ee11d573562f98de14bed79a77fcfd728 Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 19 May 2016 17:55:20 +0000 Subject: Consider /src/ in the path when locating the java root directory, to support cases like src/com/google/java, where the root is just src. Also check for nested /src/ directories. This allows "blaze analyze" to understand the classes provided by such "double src" rules and match them up to java imports. -- MOS_MIGRATED_REVID=122748028 --- .../devtools/build/lib/rules/java/JavaUtil.java | 42 +++++++- .../build/lib/rules/java/JavaUtilTest.java | 118 +++++++++++++++++++++ 2 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/google/devtools/build/lib/rules/java/JavaUtilTest.java (limited to 'src') diff --git a/src/main/java/com/google/devtools/build/lib/rules/java/JavaUtil.java b/src/main/java/com/google/devtools/build/lib/rules/java/JavaUtil.java index c4f95fe22c..60647c2f98 100644 --- a/src/main/java/com/google/devtools/build/lib/rules/java/JavaUtil.java +++ b/src/main/java/com/google/devtools/build/lib/rules/java/JavaUtil.java @@ -61,8 +61,11 @@ public final class JavaUtil { } /** - * Find the index of the "java" or "javatests" segment in a Java path fragment - * that precedes the source root. + * Finds the index of the segment in a Java path fragment that precedes the source root. + * Starts from the first "java" or "javatests" or "src" segment. + * If the found item was "src", check if this is followed by "main" or "test" and then "java". + * If the found item was at the first segment, check for a nested "src" directory, followed by + * either (main|test)/java or (com|org|net), to avoid false positives. * * @param path a Java source dir or file path * @return the index of the java segment or -1 iff no java segment was found. @@ -71,7 +74,40 @@ public final class JavaUtil { if (path.isAbsolute()) { throw new IllegalArgumentException("path must not be absolute: '" + path + "'"); } - return path.getFirstSegment(ImmutableSet.of("java", "javatests")); + int rootIndex = path.getFirstSegment(ImmutableSet.of("java", "javatests", "src")); + if (rootIndex < 0) { + return rootIndex; + } + final boolean isSrc = "src".equals(path.getSegment(rootIndex)); + int checkMavenIndex = isSrc ? rootIndex : -1; + if (rootIndex == 0) { + // Check for a nested "src" directory. + // Also, to support an existing case, "javatests" within "src". + for (int i = 1, max = path.segmentCount() - 2; i <= max; i++) { + String segment = path.getSegment(i); + if ("src".equals(segment) || (isSrc && "javatests".equals(segment))) { + String next = path.getSegment(i + 1); + if ("com".equals(next) || "org".equals(next) || "net".equals(next)) { + // Check for common first element of java package, to avoid false positives. + rootIndex = i; + } else if ("src".equals(segment)) { + // Also accept maven style src/(main|test)/java. + checkMavenIndex = i; + } + break; + } + } + } + // Check for (main|test)/java after /src/. + if (checkMavenIndex >= 0 && checkMavenIndex + 2 < path.segmentCount()) { + if ("java".equals(path.getSegment(checkMavenIndex + 2))) { + String next = path.getSegment(checkMavenIndex + 1); + if ("main".equals(next) || "test".equals(next)) { + rootIndex = checkMavenIndex + 2; + } + } + } + return rootIndex; } /** diff --git a/src/test/java/com/google/devtools/build/lib/rules/java/JavaUtilTest.java b/src/test/java/com/google/devtools/build/lib/rules/java/JavaUtilTest.java new file mode 100644 index 0000000000..353b3072bc --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/rules/java/JavaUtilTest.java @@ -0,0 +1,118 @@ +// Copyright 2015 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.devtools.build.lib.rules.java; + +import static com.google.common.truth.Truth.assertThat; + +import com.google.devtools.build.lib.vfs.PathFragment; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** + * Tests for {@link JavaUtil} methods. + */ +@RunWith(JUnit4.class) +public class JavaUtilTest { + + private String getRootPath(String path) { + return JavaUtil.getJavaRoot(new PathFragment(path)).getPathString(); + } + + @Test + public void testGetJavaRoot() { + assertThat( + JavaUtil.getJavaRoot(new PathFragment("path/without/Java/or/Javatests/or/Src/lowercase"))) + .isNull(); + assertThat(getRootPath("java/com/google/common/case")).isEqualTo("java"); + assertThat(getRootPath("javatests/com/google/common/case")).isEqualTo("javatests"); + assertThat(getRootPath("src/com/myproject/util")).isEqualTo("src"); + assertThat(getRootPath("project/java")).isEqualTo("project/java"); + assertThat(getRootPath("project/java/anything")).isEqualTo("project/java"); + assertThat(getRootPath("project/javatests")).isEqualTo("project/javatests"); + assertThat(getRootPath("project/javatests/anything")).isEqualTo("project/javatests"); + assertThat(getRootPath("project/src")).isEqualTo("project/src"); + assertThat(getRootPath("project/src/anything")).isEqualTo("project/src"); + assertThat(getRootPath("third_party/java_src/project/src/main/java/foo")) + .isEqualTo("third_party/java_src/project/src/main/java"); + assertThat(getRootPath("third_party/java_src/project/src/test/java/foo")) + .isEqualTo("third_party/java_src/project/src/test/java"); + assertThat(getRootPath("third_party/java_src/project/javatests/foo")) + .isEqualTo("third_party/java_src/project/javatests"); + + // Cases covering nested /src/ directories. + assertThat(getRootPath("java/com/google/project/module/src/com")) + .isEqualTo("java/com/google/project/module/src"); + assertThat(getRootPath("java/com/google/project/module/src/org")) + .isEqualTo("java/com/google/project/module/src"); + assertThat(getRootPath("java/com/google/project/module/src/net")) + .isEqualTo("java/com/google/project/module/src"); + assertThat(getRootPath("java/com/google/project/module/src/main/java")) + .isEqualTo("java/com/google/project/module/src/main/java"); + assertThat(getRootPath("java/com/google/project/module/src/test/java")) + .isEqualTo("java/com/google/project/module/src/test/java"); + assertThat(getRootPath("javatests/com/google/project/src/com")) + .isEqualTo("javatests/com/google/project/src"); + assertThat(getRootPath("src/com/google/project/src/main/java")) + .isEqualTo("src/com/google/project/src/main/java"); + assertThat(getRootPath("java/com/google/project/module/src/somethingelse")) + .isEqualTo("java"); + assertThat(getRootPath("java/com/google/project/module/src/foo/java")) + .isEqualTo("java"); + assertThat(getRootPath("java/com/google/project/module/src/main/com")) + .isEqualTo("java"); + assertThat(getRootPath("java/com/google/project/module/src/test/org")) + .isEqualTo("java"); + assertThat(getRootPath("java/com/google/project/module/src/java/com")) + .isEqualTo("java"); + assertThat(getRootPath("foo/java/com/google/project/src/com")) + .isEqualTo("foo/java"); + assertThat(getRootPath("src/com/google/java/javac")) + .isEqualTo("src"); + + assertThat(getRootPath("src/java_tools/buildjar/javatests/com")) + .isEqualTo("src/java_tools/buildjar/javatests"); + assertThat(getRootPath("src/java_tools/buildjar/javatests/foo")) + .isEqualTo("src"); + assertThat(getRootPath("src/tools/workspace/src/test/java/foo")) + .isEqualTo("src/tools/workspace/src/test/java"); + } + + @Test + public void testGetJavaPackageName() { + assertThat(JavaUtil.getJavaPackageName(new PathFragment("java/com/google/foo/FooModule.java"))) + .isEqualTo("com.google.foo"); + assertThat(JavaUtil.getJavaPackageName(new PathFragment("org/foo/FooUtil.java"))) + .isEqualTo("org.foo"); + } + + @Test + public void testGetJavaFullClassname() { + assertThat( + JavaUtil.getJavaFullClassname(new PathFragment("java/com/google/foo/FooModule.java"))) + .isEqualTo("com.google.foo.FooModule.java"); + assertThat(JavaUtil.getJavaFullClassname(new PathFragment("org/foo/FooUtil.java"))).isNull(); + } + + @Test + public void testGetJavaPath() { + assertThat( + JavaUtil.getJavaPath( + new PathFragment("java/com/google/foo/FooModule.java")).getPathString()) + .isEqualTo("com/google/foo/FooModule.java"); + assertThat(JavaUtil.getJavaPath(new PathFragment("org/foo/FooUtil.java"))).isNull(); + } +} -- cgit v1.2.3