srcs information in order to identify
@@ -58,6 +60,8 @@
*/
public class JavaSourceInfo {
+ private static final Logger LOG = LoggerFactory.getLogger(JavaSourceInfo.class);
+
private static final IPath NOT_FOLLOWING_JAVA_PACKAGE_STRUCTURE =
IPath.forPosix("_not_following_java_package_structure_");
private static final IPath MISSING_PACKAGE = IPath.forPosix("_missing_package_declaration_");
@@ -228,6 +232,10 @@ public void analyzeSourceDirectories(MultiStatus result,
}
}
+ // Scan BUILD directories and infer package paths for directories without direct Java files
+ // This must happen before split package checks to ensure complete index
+ scanBuildDirectoriesForPackageInfo(sourceEntriesByParentFolder, sourceEntriesBySourceRoot);
+
// rescue missing packages
if (sourceEntriesBySourceRoot.containsKey(MISSING_PACKAGE)) {
// we use the MISSING_PACKAGE when a package could not be calculated
@@ -325,7 +333,9 @@ public void analyzeSourceDirectories(MultiStatus result,
var entryParentLocation = bazelPackageLocation.append(potentialSourceRoot).toPath();
try {
// when there are declared Java files, expect them to match
- var declaredJavaFilesInFolder = entry.getValue().size();
+ // Exclude synthetic entries as they don't represent actual files on disk
+ var declaredJavaFilesInFolder =
+ (int) entry.getValue().stream().filter(e -> !(e instanceof SyntheticPackageEntry)).count();
if (declaredJavaFilesInFolder > 0) {
var foundJavaFiles = findJavaFilesNoneRecursive(entryParentLocation);
var javaFilesInParent = foundJavaFiles.size();
@@ -367,7 +377,10 @@ public void analyzeSourceDirectories(MultiStatus result,
var potentialSourceRootPath = bazelPackageLocation.append(potentialSourceRoot).toPath();
try {
- var registeredFiles = ((List>) potentialSourceRootAndSourceEntries.getValue()).size();
+ // Exclude synthetic entries when counting registered files
+ var registeredFiles = (int) ((List>) potentialSourceRootAndSourceEntries.getValue()).stream()
+ .filter(e -> !(e instanceof SyntheticPackageEntry))
+ .count();
var foundJavaFiles = findJavaFilesRecursive(potentialSourceRootPath);
var foundJavaFilesInSourceRoot = foundJavaFiles.size();
if ((registeredFiles != foundJavaFilesInSourceRoot)
@@ -397,6 +410,21 @@ public void analyzeSourceDirectories(MultiStatus result,
(List+ * This method finds all BUILD files in the workspace, checks if their directories lack direct Java files, and + * creates synthetic entries to establish proper package structure. + *
+ * + * @param sourceEntriesByParentFolder + * mapping from directories to file entry lists + * @param sourceEntriesBySourceRoot + * mapping from source roots to entries + */ + private void scanBuildDirectoriesForPackageInfo( + Map+ * This virtual entry is used to establish proper package path information for directories that contain BUILD files + * but no direct Java sources, enabling correct source root detection and preventing false positive split package + * warnings. + *
+ */ + private static class SyntheticPackageEntry extends JavaSourceEntry { + private final IPath inferredSourceRoot; + + public SyntheticPackageEntry(IPath buildDirectory, IPath packagePath, IPath sourceRoot) { + // Create virtual file path for marker purposes + super(buildDirectory.append("_synthetic_package_.java"), IPath.EMPTY); + this.detectedPackagePath = packagePath; + this.inferredSourceRoot = sourceRoot; + } + + @Override + public IPath getPotentialSourceDirectoryRoot() { + return inferredSourceRoot; + } + + @Override + public boolean isExternalOrGenerated() { + return false; // Treat as normal source + } + + @Override + public String toString() { + return format( + "SyntheticPackageEntry[dir=%s, package=%s, sourceRoot=%s]", + getPathParent(), + detectedPackagePath, + inferredSourceRoot); + } + } } diff --git a/bundles/testdata/workspaces/001/.bazelrc b/bundles/testdata/workspaces/001/.bazelrc new file mode 100644 index 000000000..711b1cc4a --- /dev/null +++ b/bundles/testdata/workspaces/001/.bazelrc @@ -0,0 +1,2 @@ +# bazelmod is enabled by default in bazel 7, but we are not ready yet +common --noenable_bzlmod diff --git a/bundles/testdata/workspaces/001/MODULE.bazel b/bundles/testdata/workspaces/001/MODULE.bazel new file mode 100644 index 000000000..00bb18361 --- /dev/null +++ b/bundles/testdata/workspaces/001/MODULE.bazel @@ -0,0 +1,6 @@ +############################################################################### +# Bazel now uses Bzlmod by default to manage external dependencies. +# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel. +# +# For more details, please check https://github.com/bazelbuild/bazel/issues/18958 +############################################################################### diff --git a/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/BUILD b/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/BUILD new file mode 100644 index 000000000..b8fc43c98 --- /dev/null +++ b/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/BUILD @@ -0,0 +1,13 @@ +load("@rules_java//java:defs.bzl", "java_library") + +java_library( + name = "async_commit_example", + srcs = glob([ + "*.java", + "async_commit_example/*.java", + "async_commit_example/annotations/*.java", + ]), + deps = [ + ], +) + diff --git a/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/ExampleDaemon.java b/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/ExampleDaemon.java new file mode 100644 index 000000000..31b6d6efa --- /dev/null +++ b/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/ExampleDaemon.java @@ -0,0 +1,9 @@ +package com.project.server.examples.async_commit_example; + +import com.project.server.examples.async_commit_example.annotations.RandomMessageGenSub0; +import com.project.server.examples.async_commit_example.annotations.RandomMessageGenSub1; + + +public class ExampleDaemon { + +} diff --git a/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/annotations/RandomMessageGenSub0.java b/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/annotations/RandomMessageGenSub0.java new file mode 100644 index 000000000..760cff1bb --- /dev/null +++ b/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/annotations/RandomMessageGenSub0.java @@ -0,0 +1,13 @@ +package com.project.server.examples.async_commit_example.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; + +@Retention(RetentionPolicy.RUNTIME) +@Target({METHOD, PARAMETER}) +public @interface RandomMessageGenSub0 { +} diff --git a/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/annotations/RandomMessageGenSub1.java b/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/annotations/RandomMessageGenSub1.java new file mode 100644 index 000000000..3ff0d8a14 --- /dev/null +++ b/bundles/testdata/workspaces/001/module4/java/com/project/server/examples/async_commit_example/annotations/RandomMessageGenSub1.java @@ -0,0 +1,13 @@ +package com.project.server.examples.async_commit_example.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; + +@Retention(RetentionPolicy.RUNTIME) +@Target({METHOD, PARAMETER}) +public @interface RandomMessageGenSub1 { +}