diff --git a/bundles/com.salesforce.bazel.eclipse.core/.classpath b/bundles/com.salesforce.bazel.eclipse.core/.classpath
index d4dbdb136..c5714f713 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/.classpath
+++ b/bundles/com.salesforce.bazel.eclipse.core/.classpath
@@ -1,6 +1,6 @@
-
+
diff --git a/bundles/com.salesforce.bazel.eclipse.core/.settings/org.eclipse.jdt.core.prefs b/bundles/com.salesforce.bazel.eclipse.core/.settings/org.eclipse.jdt.core.prefs
index fe700e3ba..f486898e3 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/com.salesforce.bazel.eclipse.core/.settings/org.eclipse.jdt.core.prefs
@@ -1,9 +1,9 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -12,7 +12,7 @@ org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=true
diff --git a/bundles/com.salesforce.bazel.eclipse.core/META-INF/MANIFEST.MF b/bundles/com.salesforce.bazel.eclipse.core/META-INF/MANIFEST.MF
index fdb0341c9..71f87ca96 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/META-INF/MANIFEST.MF
+++ b/bundles/com.salesforce.bazel.eclipse.core/META-INF/MANIFEST.MF
@@ -54,5 +54,5 @@ Require-Bundle: org.eclipse.core.jobs;bundle-version="3.12.0",
org.eclipse.jdt.junit.core;bundle-version="3.11.0",
org.eclipse.core.filesystem;bundle-version="1.9.500",
org.eclipse.core.variables;bundle-version="3.6.0"
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-ActivationPolicy: lazy
diff --git a/bundles/com.salesforce.bazel.eclipse.core/plugin.xml b/bundles/com.salesforce.bazel.eclipse.core/plugin.xml
index 656b40970..531feace2 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/plugin.xml
+++ b/bundles/com.salesforce.bazel.eclipse.core/plugin.xml
@@ -124,6 +124,10 @@
class="com.salesforce.bazel.eclipse.core.model.discovery.BazelBuildfileTargetDiscovery"
name="buildfiles">
+
+
diff --git a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/BazelModel.java b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/BazelModel.java
index 053c24d3f..cac9f2eca 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/BazelModel.java
+++ b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/BazelModel.java
@@ -13,6 +13,8 @@
*/
package com.salesforce.bazel.eclipse.core.model;
+import static java.util.Objects.requireNonNull;
+
import java.util.List;
import org.eclipse.core.resources.IProject;
@@ -105,7 +107,9 @@ public IPath getLocation() {
* @return the owning model manager
*/
public BazelModelManager getModelManager() {
- return modelManager;
+ return requireNonNull(
+ modelManager,
+ "not initialized properly; allowed only in unit tests, then mocking is required");
}
@Override
diff --git a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BaseProvisioningStrategy.java b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BaseProvisioningStrategy.java
index b5f5edf51..f98277b3d 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BaseProvisioningStrategy.java
+++ b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BaseProvisioningStrategy.java
@@ -1655,7 +1655,7 @@ private void linkSourceFilesWithoutCommonRoot(JavaSourceInfo sourceInfo, IFolder
Set linkedFiles = new HashSet<>();
for (JavaSourceEntry fileEntry : files) {
// peek at Java package to find proper "root"
- var packagePath = fileEntry.getDetectedPackagePath();
+ var packagePath = fileEntry.hasDetectedPackagePath() ? fileEntry.getDetectedPackagePath() : IPath.EMPTY;
var packageFolder = virtualSourceFolder.getFolder(packagePath);
if (!packageFolder.exists()) {
createFolderAndParents(packageFolder, monitor.split(1));
diff --git a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BuildfileDrivenProvisioningStrategy.java b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BuildfileDrivenProvisioningStrategy.java
index e546c98c6..6345a7e8f 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BuildfileDrivenProvisioningStrategy.java
+++ b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BuildfileDrivenProvisioningStrategy.java
@@ -26,12 +26,14 @@
import com.google.idea.blaze.base.model.primitives.TargetExpression;
import com.google.idea.blaze.base.model.primitives.TargetName;
+import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.salesforce.bazel.eclipse.core.classpath.BazelClasspathScope;
import com.salesforce.bazel.eclipse.core.classpath.CompileAndRuntimeClasspath;
import com.salesforce.bazel.eclipse.core.model.BazelProject;
import com.salesforce.bazel.eclipse.core.model.BazelTarget;
import com.salesforce.bazel.eclipse.core.model.BazelWorkspace;
import com.salesforce.bazel.eclipse.core.model.buildfile.FunctionCall;
+import com.salesforce.bazel.eclipse.core.model.discovery.analyzers.starlark.StarlarkMacroCallAnalyzer;
import com.salesforce.bazel.eclipse.core.model.discovery.classpath.ClasspathEntry;
import com.salesforce.bazel.eclipse.core.model.discovery.classpath.libs.ExternalLibrariesDiscovery;
import com.salesforce.bazel.eclipse.core.model.discovery.projects.JavaProjectInfo;
@@ -41,7 +43,7 @@
/**
* Implementation of {@link TargetProvisioningStrategy} which provisions projects based on parsing BUILD
- * files directly and computing their classpath based on visibility in the build graph.
+ * files directly.
*
* This strategy implements behavior which intentionally deviates from Bazel dominated strategies in favor of a better
* developer experience in IDEs.
@@ -50,8 +52,6 @@
*
The macro translation is extensible so translators for custom macros can be provided and included in the
* analysis.
* A heuristic is used to merge java_*
targets in the same package into a single Eclipse project.
- * The classpath is computed based on visibility, which eventually allows to compute the deps list by IDEs based on
- * actual use.
* Projects are created directly in the package location.
* The root (empty) package //
is not supported.
*
@@ -153,9 +153,30 @@ public Map computeClasspaths(Collectio
protected List doProvisionProjects(Collection targetsOrPackages,
BazelWorkspace workspace, TracingSubMonitor monitor) throws CoreException {
- // obtain package paths
+ // extract package paths from label to provision
var packages = targetsOrPackages.parallelStream().map(this::extractPackagePath).distinct().toList();
+ // load macro analyzers specified in project view
+ Map starlarkAnalyzers = new HashMap<>();
+ for (var settingsEntry : workspace.getBazelProjectView().targetProvisioningSettings().entrySet()) {
+ if (settingsEntry.getKey().startsWith("macro:")) {
+ try {
+ var macroName = settingsEntry.getKey().substring("macro:".length());
+ var sclFile = new WorkspacePath(settingsEntry.getValue());
+ var analyzer = new StarlarkMacroCallAnalyzer(workspace, sclFile);
+ starlarkAnalyzers.put(macroName, analyzer);
+ } catch (Exception e) {
+ throw new CoreException(
+ Status.error(
+ format(
+ "Error loading macro call analyzer for setting '%s': %s",
+ settingsEntry,
+ e.getMessage()),
+ e));
+ }
+ }
+ }
+
monitor.beginTask("Provisioning projects", packages.size() * 3);
var result = new ArrayList();
for (Path packagePath : packages) {
@@ -179,7 +200,7 @@ protected List doProvisionProjects(Collection ta
var javaInfo = new JavaProjectInfo(bazelPackage);
var relevantTargets = new ArrayList();
for (FunctionCall macroCall : topLevelMacroCalls) {
- var relevant = processMacroCall(macroCall, javaInfo);
+ var relevant = processMacroCall(macroCall, javaInfo, starlarkAnalyzers);
if (!relevant) {
if (LOG.isDebugEnabled()) {
LOG.debug("Skipping not relevant macro call '{}'.", macroCall);
@@ -241,13 +262,22 @@ private Path extractPackagePath(TargetExpression targetExpression) {
return Path.of(targetExpressionStr.substring(startIndex, colonIndex));
}
- private boolean processMacroCall(FunctionCall macroCall, JavaProjectInfo javaInfo) throws CoreException {
- var analyzers = extensionLookup.createMacroCallAnalyzers(macroCall.getResolvedFunctionName());
- if (analyzers.isEmpty()) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("No analyzers available for function '{}'", macroCall.getResolvedFunctionName());
+ private boolean processMacroCall(FunctionCall macroCall, JavaProjectInfo javaInfo,
+ Map projectViewAnalyzers) throws CoreException {
+ // get the analyzers to check
+ List analyzers;
+ var projectViewAnalyzer = projectViewAnalyzers.get(macroCall.getResolvedFunctionName());
+ if (projectViewAnalyzer != null) {
+ // any analyzer from project view takes precedences
+ analyzers = List.of(projectViewAnalyzer);
+ } else {
+ analyzers = extensionLookup.createMacroCallAnalyzers(macroCall.getResolvedFunctionName());
+ if (analyzers.isEmpty()) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("No analyzers available for function '{}'", macroCall.getResolvedFunctionName());
+ }
+ return false; // no analyzers
}
- return false; // no analyzers
}
for (MacroCallAnalyzer analyzer : analyzers) {
diff --git a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkAnalyzeInfo.java b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkAnalyzeInfo.java
index c8d166a80..63c0b4de9 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkAnalyzeInfo.java
+++ b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkAnalyzeInfo.java
@@ -26,12 +26,13 @@
import net.starlark.java.eval.Sequence;
import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkInt;
+import net.starlark.java.eval.StarlarkValue;
/**
* A data type for returning information from the analyze
function
*/
@StarlarkBuiltin(name = "AnalyzeInfo", documented = false)
-public class StarlarkAnalyzeInfo {
+public class StarlarkAnalyzeInfo implements StarlarkValue {
private List convertToStringList(Sequence> exclude, String nameForErrorMessage) throws EvalException {
List stringList = new ArrayList<>();
@@ -54,12 +55,11 @@ private List convertToStringList(Sequence> exclude, String nameForErro
@ParamType(type = Sequence.class, generic1 = String.class) }, defaultValue = "[]", named = true, documented = false),
@Param(name = "exclude_directories", defaultValue = "1", named = true, documented = false),
@Param(name = "allow_empty", defaultValue = "unbound", named = true, documented = false) })
- StarlarkGlobInfo glob(Sequence> include, Sequence> exclude, StarlarkInt excludeDirectories, Object allowEmpty)
- throws EvalException, InterruptedException {
+ StarlarkGlobInfo ProjectInfo(Sequence> include, Sequence> exclude, StarlarkInt excludeDirectories,
+ Object allowEmpty) throws EvalException, InterruptedException {
var includeStringList = convertToStringList(include, "include");
var excludeStringList = convertToStringList(exclude, "exclude");
return new StarlarkGlobInfo(new GlobInfo(includeStringList, excludeStringList));
-
}
}
diff --git a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkFunctionCallInfo.java b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkFunctionCallInfo.java
index 4778ce5da..088b32963 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkFunctionCallInfo.java
+++ b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkFunctionCallInfo.java
@@ -51,25 +51,23 @@ class StarlarkFunctionCallInfo implements StarlarkValue {
private static final Logger LOG = LoggerFactory.getLogger(StarlarkFunctionCallInfo.class);
private final FunctionCall functionCall;
+ private volatile Dict args;
public StarlarkFunctionCallInfo(FunctionCall functionCall) {
this.functionCall = functionCall;
}
private Dict evaluateArgs(StarlarkThread thread) {
- var callExpression = functionCall.getCallExpression();
-
Builder result = Dict.builder();
+ var callExpression = functionCall.getCallExpression();
for (Argument argument : callExpression.getArguments()) {
if (argument.getName() == null) {
continue;
}
try {
-
var parserInput = ParserInput
.fromString(argument.getValue().prettyPrint(), format("argument %s", argument.getName()));
-
result.put(argument.getName(), Starlark.eval(parserInput, FileOptions.DEFAULT, predeclared, thread));
} catch (InterruptedException e) {
throw new OperationCanceledException("Interrupted Starlark execution");
@@ -84,7 +82,11 @@ private Dict evaluateArgs(StarlarkThread thread) {
@StarlarkMethod(name = "args", structField = true, useStarlarkThread = true)
public Dict getArgs(StarlarkThread thread) {
- return evaluateArgs(thread);
+ var args = this.args;
+ if (args != null) {
+ return args;
+ }
+ return this.args = evaluateArgs(thread);
}
@StarlarkMethod(name = "resolved_function_name", structField = true)
diff --git a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkMacroCallAnalyzer.java b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkMacroCallAnalyzer.java
index f22f1638f..a87bfa156 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkMacroCallAnalyzer.java
+++ b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkMacroCallAnalyzer.java
@@ -16,6 +16,7 @@
import static java.lang.String.format;
import java.io.IOException;
+import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
@@ -48,7 +49,7 @@
* though. Bazel specific Starlark globals are not supported.
*
*
- * The analyzer must be defined in a .bzl
file. The file must define a function named analyze
.
+ * The analyzer must be defined in a .scl
file. The file must define a function named analyze
.
* The function will be called with the following named parameters:
*
* function_info
- info about the function call (see {@link StarlarkFunctionCallInfo} for details)
@@ -64,67 +65,103 @@
*/
public class StarlarkMacroCallAnalyzer implements MacroCallAnalyzer {
+ private static final Object[] NO_ARGS = {};
+
+ private static final String FUNCTION_INFO = "function_info";
+
private static final StarlarkSemantics starlarkSemantics =
StarlarkSemantics.builder().setBool(StarlarkSemantics.EXPERIMENTAL_ENABLE_STARLARK_SET, true).build();
- private final IPath analyzeFile;
- private final StarlarkFunction analyzeFunction;
-
- public StarlarkMacroCallAnalyzer(BazelWorkspace bazelWorkspace, WorkspacePath bzlFile)
+ /**
+ * Parses the given input for an 'analyze'
function.
+ *
+ * @param input
+ * the input to parse
+ * @param file
+ * for error reporting only
+ * @return the parsed function (never null
)
+ * @throws CoreException,
+ * {@link OperationCanceledException}
+ */
+ /* for test only */
+ static StarlarkFunction parseInputAndGetAnalyzeFunction(ParserInput input, String file)
throws CoreException, OperationCanceledException {
- analyzeFile = bazelWorkspace.getLocation().append(bzlFile.relativePath());
- ParserInput input;
- try {
- input = ParserInput.readFile(analyzeFile.toOSString());
- } catch (IOException e) {
- throw new CoreException(Status.error(format("Failed to read file '%s'", analyzeFile), e));
- }
-
try (var mu = Mutability.create("analyzer")) {
ImmutableMap.Builder env = ImmutableMap.builder();
- //Starlark.addMethods(env, new CqueryDialectGlobals(), starlarkSemantics);
+ Starlark.addMethods(env, new StarlarkAnalyzeInfo(), starlarkSemantics);
var module = Module.withPredeclared(starlarkSemantics, env.buildOrThrow());
var thread = StarlarkThread.createTransient(mu, starlarkSemantics);
Starlark.execFile(input, FileOptions.DEFAULT, module, thread);
var analyzeFn = module.getGlobal("analyze");
if (analyzeFn == null) {
- throw new CoreException(
- Status.error(format("File '%s' does not define 'analyze' function", analyzeFile)));
+ throw new CoreException(Status.error(format("File '%s' does not define 'analyze' function", file)));
}
- if (!(analyzeFn instanceof StarlarkFunction)) {
+ if (!(analyzeFn instanceof StarlarkFunction analyzeFunction)) {
throw new CoreException(
Status.error(
format(
"File '%s' 'analyze' is not a function. Got '%s'.",
- analyzeFile,
+ file,
Starlark.type(analyzeFn))));
}
- analyzeFunction = (StarlarkFunction) analyzeFn;
- if (analyzeFunction.getParameterNames().size() != 1) {
+ if (!analyzeFunction.getParameterNames().contains(FUNCTION_INFO)
+ || (analyzeFunction.getParameterNames().size() != 1)) {
throw new CoreException(
- Status.error(format("File '%s' 'format' function must take exactly 1 argument", analyzeFile)));
+ Status.error(
+ format(
+ "File '%s' 'analyze' function must take exactly 1 named argument 'function_info'",
+ file)));
}
+
+ return analyzeFunction;
} catch (SyntaxError.Exception e) {
- throw new CoreException(
- Status.error(format("Syntax error in file '%s': %s", analyzeFile, e.getMessage()), e));
+ throw new CoreException(Status.error(format("Syntax error in file '%s': %s", file, e.getMessage()), e));
} catch (EvalException e) {
- throw new CoreException(
- Status.error(format("Evaluation error in file '%s': %s", analyzeFile, e.getMessage()), e));
+ throw new CoreException(Status.error(format("Evaluation error in file '%s': %s", file, e.getMessage()), e));
} catch (InterruptedException e) {
throw new OperationCanceledException("Interrupted while executing Starlark");
}
}
+ private final IPath analyzeFile;
+
+ private final StarlarkFunction analyzeFunction;
+
+ public StarlarkMacroCallAnalyzer(BazelWorkspace bazelWorkspace, WorkspacePath sclFile)
+ throws CoreException, OperationCanceledException {
+
+ analyzeFile = bazelWorkspace.getLocation().append(sclFile.relativePath());
+
+ ParserInput input;
+ try {
+ input = ParserInput.readFile(analyzeFile.toOSString());
+ } catch (IOException e) {
+ throw new CoreException(Status.error(format("Failed to read file '%s'", analyzeFile), e));
+ }
+
+ analyzeFunction = parseInputAndGetAnalyzeFunction(input, analyzeFile.toOSString());
+ }
+
@Override
public boolean analyze(FunctionCall macroCall, JavaProjectInfo javaInfo) throws CoreException {
- try {
- var thread = StarlarkThread.createTransient(Mutability.create("analyze evaluation"), starlarkSemantics);
+ try (var mu = Mutability.create("analyze evaluation")) {
+ ImmutableMap.Builder env = ImmutableMap.builder();
+ //Starlark.addMethods(env, new CqueryDialectGlobals(), starlarkSemantics);
+ var module = Module.withPredeclared(starlarkSemantics, env.buildOrThrow());
+
+ var thread = StarlarkThread.createTransient(mu, starlarkSemantics);
thread.setMaxExecutionSteps(500_000L);
- var kwargs = Map. of("macro_info", new StarlarkFunctionCallInfo(macroCall));
- var result = Starlark.call(thread, analyzeFunction, null, kwargs);
- } catch (EvalException e) {
+ var kwargs = Map. of(FUNCTION_INFO, new StarlarkFunctionCallInfo(macroCall));
+ var result = Starlark.call(thread, analyzeFunction, List.of(), kwargs);
+ if (Starlark.isNullOrNone(result) || !Starlark.truth(result)) {
+ return false;
+ }
+ if (!(result instanceof StarlarkAnalyzeInfo)) {
+ throw Starlark.errorf("Return value is not of type AnalyzeInfo. Got '%s'", result);
+ }
+ } catch (EvalException | RuntimeException e) {
throw new CoreException(
Status.error(
format("Error executiong 'analyze' in file '%s': %s", analyzeFile, e.getMessage()),
diff --git a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkNativeModuleApiDummy.java b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkNativeModuleApiDummy.java
index e8b9065c3..b4322c054 100644
--- a/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkNativeModuleApiDummy.java
+++ b/bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkNativeModuleApiDummy.java
@@ -13,9 +13,6 @@
*/
package com.salesforce.bazel.eclipse.core.model.discovery.analyzers.starlark;
-import java.util.ArrayList;
-import java.util.List;
-
import com.salesforce.bazel.eclipse.core.model.buildfile.GlobInfo;
import net.starlark.java.annot.Param;
@@ -24,7 +21,6 @@
import net.starlark.java.annot.StarlarkMethod;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Sequence;
-import net.starlark.java.eval.Starlark;
import net.starlark.java.eval.StarlarkInt;
/**
@@ -33,17 +29,6 @@
@StarlarkBuiltin(name = "native", documented = false)
public class StarlarkNativeModuleApiDummy {
- private List convertToStringList(Sequence> exclude, String nameForErrorMessage) throws EvalException {
- List stringList = new ArrayList<>();
- for (Object value : exclude) {
- if (!(value instanceof String s)) {
- throw Starlark.errorf("Invalid 'glob' argument type in '%s': %s", nameForErrorMessage, value);
- }
- stringList.add(s);
- }
- return stringList;
- }
-
/**
* Support for glob
to turn into {@link StarlarkGlobInfo}.
*
@@ -56,12 +41,8 @@ private List convertToStringList(Sequence> exclude, String nameForErro
@ParamType(type = Sequence.class, generic1 = String.class) }, defaultValue = "[]", named = true, documented = false),
@Param(name = "exclude_directories", defaultValue = "1", named = true, documented = false),
@Param(name = "allow_empty", defaultValue = "unbound", named = true, documented = false) })
- StarlarkGlobInfo glob(Sequence> include, Sequence> exclude, StarlarkInt excludeDirectories, Object allowEmpty)
- throws EvalException, InterruptedException {
-
- var includeStringList = convertToStringList(include, "include");
- var excludeStringList = convertToStringList(exclude, "exclude");
- return new StarlarkGlobInfo(new GlobInfo(includeStringList, excludeStringList));
-
+ StarlarkGlobInfo glob(Sequence include, Sequence exclude, StarlarkInt excludeDirectories,
+ Object allowEmpty) throws EvalException, InterruptedException {
+ return new StarlarkGlobInfo(new GlobInfo(include, exclude));
}
}
diff --git a/bundles/testdata/src/testdata/SharedTestData.java b/bundles/testdata/src/testdata/SharedTestData.java
index 719697c79..2c906d8fe 100644
--- a/bundles/testdata/src/testdata/SharedTestData.java
+++ b/bundles/testdata/src/testdata/SharedTestData.java
@@ -10,6 +10,8 @@ public interface SharedTestData {
String WORKSPACE_001 = "/workspaces/001";
+ String WORKSPACE_002 = "/workspaces/001";
+
IPath BAZELPROJECT_FILE = new Path(".bazelproject");
}
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/002/.bazelproject b/bundles/testdata/workspaces/002/.bazelproject
new file mode 100644
index 000000000..dc6870eac
--- /dev/null
+++ b/bundles/testdata/workspaces/002/.bazelproject
@@ -0,0 +1,19 @@
+# The project view file (.bazelproject) is used to import targets into the IDE.
+#
+# See: https://ij.bazel.build/docs/project-views.html
+#
+# This files provides a default experience for developers working with the project
+
+
+directories:
+ .
+
+derive_targets_from_directories: true
+
+java_language_level: 21
+
+target_discovery_strategy: buildfiles
+target_provisioning_strategy: project-per-buildfile
+target_provisioning_settings:
+ macro:my_macro=tools/ide/my_macro_analyzer.scl
+
diff --git a/bundles/testdata/workspaces/002/.gitignore b/bundles/testdata/workspaces/002/.gitignore
new file mode 100644
index 000000000..772f56657
--- /dev/null
+++ b/bundles/testdata/workspaces/002/.gitignore
@@ -0,0 +1,11 @@
+# Eclipse metadata
+.classpath
+.project
+.settings/
+.eclipse/
+
+# Bazel folder
+/bazel-*
+
+# ignore the Bazel version file
+.bazelversion
diff --git a/bundles/testdata/workspaces/002/BUILD.bazel b/bundles/testdata/workspaces/002/BUILD.bazel
new file mode 100644
index 000000000..e69de29bb
diff --git a/bundles/testdata/workspaces/002/MODULE.bazel b/bundles/testdata/workspaces/002/MODULE.bazel
new file mode 100644
index 000000000..10b498b04
--- /dev/null
+++ b/bundles/testdata/workspaces/002/MODULE.bazel
@@ -0,0 +1,30 @@
+module(
+ name = "testdata_workspaces_002",
+)
+
+bazel_dep(name = "rules_java", version = "8.6.3")
+bazel_dep(name = "rules_jvm_external", version = "6.6")
+
+maven_deps = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
+maven_deps.artifact(
+ testonly = True,
+ artifact = "junit",
+ group = "junit",
+ version = "4.13.2",
+)
+maven_deps.install(
+ name = "maven_deps",
+ artifacts = [
+ "com.google.guava:guava:33.4.0-jre",
+ "junit:junit:4.13.2",
+ "org.apache.commons:commons-lang3:jar:3.17.0",
+ ],
+ fail_if_repin_required = True,
+ fetch_sources = True,
+ generate_compat_repositories = False,
+ lock_file = "@//:maven_install.json", # repin with: REPIN=1 bazel run @maven_deps//:pin
+ resolver = "maven",
+ strict_visibility = True,
+ version_conflict_policy = "pinned",
+)
+use_repo(maven_deps, "maven_deps")
diff --git a/bundles/testdata/workspaces/002/maven_install.json b/bundles/testdata/workspaces/002/maven_install.json
new file mode 100755
index 000000000..83c1d31af
--- /dev/null
+++ b/bundles/testdata/workspaces/002/maven_install.json
@@ -0,0 +1,243 @@
+{
+ "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
+ "__INPUT_ARTIFACTS_HASH": -772885195,
+ "__RESOLVED_ARTIFACTS_HASH": -1746335676,
+ "artifacts": {
+ "com.google.code.findbugs:jsr305": {
+ "shasums": {
+ "jar": "766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7",
+ "sources": "1c9e85e272d0708c6a591dc74828c71603053b48cc75ae83cce56912a2aa063b"
+ },
+ "version": "3.0.2"
+ },
+ "com.google.errorprone:error_prone_annotations": {
+ "shasums": {
+ "jar": "77440e270b0bc9a249903c5a076c36a722c4886ca4f42675f2903a1c53ed61a5",
+ "sources": "7e117e0931cb2cb4226372af336189b49edb79969d120ec958a6df0beacb0612"
+ },
+ "version": "2.36.0"
+ },
+ "com.google.guava:failureaccess": {
+ "shasums": {
+ "jar": "8a8f81cf9b359e3f6dfa691a1e776985c061ef2f223c9b2c80753e1b458e8064",
+ "sources": "dd3bfa5e2ec5bc5397efb2c3cef044c192313ff77089573667ff97a60c6978e0"
+ },
+ "version": "1.0.2"
+ },
+ "com.google.guava:guava": {
+ "shasums": {
+ "jar": "b918c98a7e44dbe94ebd9fe3e40cddaadb5a93e6a78eb6008b42df237241e538",
+ "sources": "55ef6603b6ab1f6e3ae810b127561650ed682eb5f3fb50a212a658a74087b457"
+ },
+ "version": "33.4.0-jre"
+ },
+ "com.google.guava:listenablefuture": {
+ "shasums": {
+ "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99"
+ },
+ "version": "9999.0-empty-to-avoid-conflict-with-guava"
+ },
+ "com.google.j2objc:j2objc-annotations": {
+ "shasums": {
+ "jar": "88241573467ddca44ffd4d74aa04c2bbfd11bf7c17e0c342c94c9de7a70a7c64",
+ "sources": "bd60019a0423c3a025ef6ab24fe0761f5f45ffb48a8cca74a01b678de1105d38"
+ },
+ "version": "3.0.0"
+ },
+ "junit:junit": {
+ "shasums": {
+ "jar": "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3",
+ "sources": "34181df6482d40ea4c046b063cb53c7ffae94bdf1b1d62695bdf3adf9dea7e3a"
+ },
+ "version": "4.13.2"
+ },
+ "org.apache.commons:commons-lang3": {
+ "shasums": {
+ "jar": "6ee731df5c8e5a2976a1ca023b6bb320ea8d3539fbe64c8a1d5cb765127c33b4",
+ "sources": "5fdcac21ad329766054a95367d7583dfcdca737d221d5e01a5f2a198c04c6b18"
+ },
+ "version": "3.17.0"
+ },
+ "org.checkerframework:checker-qual": {
+ "shasums": {
+ "jar": "3fbc2e98f05854c3df16df9abaa955b91b15b3ecac33623208ed6424640ef0f6",
+ "sources": "d6bdee58964cd05aabfca4e44947d3cbdada6bf617ed618b62b3b0d5a21de339"
+ },
+ "version": "3.43.0"
+ },
+ "org.hamcrest:hamcrest-core": {
+ "shasums": {
+ "jar": "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9",
+ "sources": "e223d2d8fbafd66057a8848cc94222d63c3cedd652cc48eddc0ab5c39c0f84df"
+ },
+ "version": "1.3"
+ }
+ },
+ "dependencies": {
+ "com.google.guava:guava": [
+ "com.google.code.findbugs:jsr305",
+ "com.google.errorprone:error_prone_annotations",
+ "com.google.guava:failureaccess",
+ "com.google.guava:listenablefuture",
+ "com.google.j2objc:j2objc-annotations",
+ "org.checkerframework:checker-qual"
+ ],
+ "junit:junit": [
+ "org.hamcrest:hamcrest-core"
+ ]
+ },
+ "packages": {
+ "com.google.code.findbugs:jsr305": [
+ "javax.annotation",
+ "javax.annotation.concurrent",
+ "javax.annotation.meta"
+ ],
+ "com.google.errorprone:error_prone_annotations": [
+ "com.google.errorprone.annotations",
+ "com.google.errorprone.annotations.concurrent"
+ ],
+ "com.google.guava:failureaccess": [
+ "com.google.common.util.concurrent.internal"
+ ],
+ "com.google.guava:guava": [
+ "com.google.common.annotations",
+ "com.google.common.base",
+ "com.google.common.base.internal",
+ "com.google.common.cache",
+ "com.google.common.collect",
+ "com.google.common.escape",
+ "com.google.common.eventbus",
+ "com.google.common.graph",
+ "com.google.common.hash",
+ "com.google.common.html",
+ "com.google.common.io",
+ "com.google.common.math",
+ "com.google.common.net",
+ "com.google.common.primitives",
+ "com.google.common.reflect",
+ "com.google.common.util.concurrent",
+ "com.google.common.xml",
+ "com.google.thirdparty.publicsuffix"
+ ],
+ "com.google.j2objc:j2objc-annotations": [
+ "com.google.j2objc.annotations"
+ ],
+ "junit:junit": [
+ "junit.extensions",
+ "junit.framework",
+ "junit.runner",
+ "junit.textui",
+ "org.junit",
+ "org.junit.experimental",
+ "org.junit.experimental.categories",
+ "org.junit.experimental.max",
+ "org.junit.experimental.results",
+ "org.junit.experimental.runners",
+ "org.junit.experimental.theories",
+ "org.junit.experimental.theories.internal",
+ "org.junit.experimental.theories.suppliers",
+ "org.junit.function",
+ "org.junit.internal",
+ "org.junit.internal.builders",
+ "org.junit.internal.management",
+ "org.junit.internal.matchers",
+ "org.junit.internal.requests",
+ "org.junit.internal.runners",
+ "org.junit.internal.runners.model",
+ "org.junit.internal.runners.rules",
+ "org.junit.internal.runners.statements",
+ "org.junit.matchers",
+ "org.junit.rules",
+ "org.junit.runner",
+ "org.junit.runner.manipulation",
+ "org.junit.runner.notification",
+ "org.junit.runners",
+ "org.junit.runners.model",
+ "org.junit.runners.parameterized",
+ "org.junit.validator"
+ ],
+ "org.apache.commons:commons-lang3": [
+ "org.apache.commons.lang3",
+ "org.apache.commons.lang3.arch",
+ "org.apache.commons.lang3.builder",
+ "org.apache.commons.lang3.compare",
+ "org.apache.commons.lang3.concurrent",
+ "org.apache.commons.lang3.concurrent.locks",
+ "org.apache.commons.lang3.event",
+ "org.apache.commons.lang3.exception",
+ "org.apache.commons.lang3.function",
+ "org.apache.commons.lang3.math",
+ "org.apache.commons.lang3.mutable",
+ "org.apache.commons.lang3.reflect",
+ "org.apache.commons.lang3.stream",
+ "org.apache.commons.lang3.text",
+ "org.apache.commons.lang3.text.translate",
+ "org.apache.commons.lang3.time",
+ "org.apache.commons.lang3.tuple",
+ "org.apache.commons.lang3.util"
+ ],
+ "org.checkerframework:checker-qual": [
+ "org.checkerframework.checker.builder.qual",
+ "org.checkerframework.checker.calledmethods.qual",
+ "org.checkerframework.checker.compilermsgs.qual",
+ "org.checkerframework.checker.fenum.qual",
+ "org.checkerframework.checker.formatter.qual",
+ "org.checkerframework.checker.guieffect.qual",
+ "org.checkerframework.checker.i18n.qual",
+ "org.checkerframework.checker.i18nformatter.qual",
+ "org.checkerframework.checker.index.qual",
+ "org.checkerframework.checker.initialization.qual",
+ "org.checkerframework.checker.interning.qual",
+ "org.checkerframework.checker.lock.qual",
+ "org.checkerframework.checker.mustcall.qual",
+ "org.checkerframework.checker.nullness.qual",
+ "org.checkerframework.checker.optional.qual",
+ "org.checkerframework.checker.propkey.qual",
+ "org.checkerframework.checker.regex.qual",
+ "org.checkerframework.checker.signature.qual",
+ "org.checkerframework.checker.signedness.qual",
+ "org.checkerframework.checker.tainting.qual",
+ "org.checkerframework.checker.units.qual",
+ "org.checkerframework.common.aliasing.qual",
+ "org.checkerframework.common.initializedfields.qual",
+ "org.checkerframework.common.reflection.qual",
+ "org.checkerframework.common.returnsreceiver.qual",
+ "org.checkerframework.common.subtyping.qual",
+ "org.checkerframework.common.util.count.report.qual",
+ "org.checkerframework.common.value.qual",
+ "org.checkerframework.dataflow.qual",
+ "org.checkerframework.framework.qual"
+ ],
+ "org.hamcrest:hamcrest-core": [
+ "org.hamcrest",
+ "org.hamcrest.core",
+ "org.hamcrest.internal"
+ ]
+ },
+ "repositories": {
+ "https://repo1.maven.org/maven2/": [
+ "com.google.code.findbugs:jsr305",
+ "com.google.code.findbugs:jsr305:jar:sources",
+ "com.google.errorprone:error_prone_annotations",
+ "com.google.errorprone:error_prone_annotations:jar:sources",
+ "com.google.guava:failureaccess",
+ "com.google.guava:failureaccess:jar:sources",
+ "com.google.guava:guava",
+ "com.google.guava:guava:jar:sources",
+ "com.google.guava:listenablefuture",
+ "com.google.j2objc:j2objc-annotations",
+ "com.google.j2objc:j2objc-annotations:jar:sources",
+ "junit:junit",
+ "junit:junit:jar:sources",
+ "org.apache.commons:commons-lang3",
+ "org.apache.commons:commons-lang3:jar:sources",
+ "org.checkerframework:checker-qual",
+ "org.checkerframework:checker-qual:jar:sources",
+ "org.hamcrest:hamcrest-core",
+ "org.hamcrest:hamcrest-core:jar:sources"
+ ]
+ },
+ "services": {},
+ "skipped": [],
+ "version": "2"
+}
diff --git a/bundles/testdata/workspaces/002/module1/.bazeltargets b/bundles/testdata/workspaces/002/module1/.bazeltargets
new file mode 100644
index 000000000..120d56ae4
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module1/.bazeltargets
@@ -0,0 +1,2 @@
+# targets used to setup the project
+# (do not modify manually; synchronize projects to update)
\ No newline at end of file
diff --git a/bundles/testdata/workspaces/002/module1/BUILD b/bundles/testdata/workspaces/002/module1/BUILD
new file mode 100644
index 000000000..5fed393a3
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module1/BUILD
@@ -0,0 +1,5 @@
+load("//tools/macro:defs.bzl", "my_macro")
+
+my_macro (
+ name = "module1",
+)
diff --git a/bundles/testdata/workspaces/002/module1/java/src/log/Logger.java b/bundles/testdata/workspaces/002/module1/java/src/log/Logger.java
new file mode 100644
index 000000000..e1bdd8c6c
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module1/java/src/log/Logger.java
@@ -0,0 +1,16 @@
+package log;
+
+import java.time.Instant;
+
+public final class Logger {
+
+ private Logger() {
+ throw new RuntimeException();
+ }
+
+ public static void logDebug(String message) {
+ String output = String.format("[DEBUG] %s", message);
+ System.out.println(output);
+ }
+
+}
diff --git a/bundles/testdata/workspaces/002/module2/.bazeltargets b/bundles/testdata/workspaces/002/module2/.bazeltargets
new file mode 100644
index 000000000..8a685b617
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module2/.bazeltargets
@@ -0,0 +1,4 @@
+# targets used to setup the project
+# (do not modify manually; synchronize projects to update)
+module2
+module2-test
\ No newline at end of file
diff --git a/bundles/testdata/workspaces/002/module2/BUILD b/bundles/testdata/workspaces/002/module2/BUILD
new file mode 100644
index 000000000..1af35428f
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module2/BUILD
@@ -0,0 +1,21 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+java_library (
+ name = "module2",
+ srcs = glob(["java/src/**/*.java"]),
+ visibility = ["//module1:__pkg__"],
+ deps = [
+ "//module3",
+ "@maven_deps//:org_apache_commons_commons_lang3"
+ ]
+)
+
+java_test(
+ name = "module2-test",
+ srcs = ["java/test/library/GreetingTest.java"],
+ test_class = "library.GreetingTest",
+ deps = [
+ "module2",
+ "@maven_deps//:junit_junit",
+ ],
+)
diff --git a/bundles/testdata/workspaces/002/module2/java/src/library/Greeting.java b/bundles/testdata/workspaces/002/module2/java/src/library/Greeting.java
new file mode 100644
index 000000000..ea3109f10
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module2/java/src/library/Greeting.java
@@ -0,0 +1,12 @@
+package library;
+
+import log.Logger;
+
+public class Greeting {
+
+ public String greet(String name) {
+ Logger.logDebug("Greeting.greet");
+ return "Hello ".concat(name);
+ }
+
+}
diff --git a/bundles/testdata/workspaces/002/module2/java/test/library/GreetingTest.java b/bundles/testdata/workspaces/002/module2/java/test/library/GreetingTest.java
new file mode 100644
index 000000000..462df6e83
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module2/java/test/library/GreetingTest.java
@@ -0,0 +1,11 @@
+package library;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GreetingTest {
+ @Test
+ public void testGreet() {
+ Assert.assertEquals("Hello JUnit", new Greeting().greet("JUnit"));
+ }
+}
diff --git a/bundles/testdata/workspaces/002/module3/.bazeltargets b/bundles/testdata/workspaces/002/module3/.bazeltargets
new file mode 100644
index 000000000..337763597
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module3/.bazeltargets
@@ -0,0 +1,3 @@
+# targets used to setup the project
+# (do not modify manually; synchronize projects to update)
+module3
\ No newline at end of file
diff --git a/bundles/testdata/workspaces/002/module3/BUILD b/bundles/testdata/workspaces/002/module3/BUILD
new file mode 100644
index 000000000..f2f951ffc
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module3/BUILD
@@ -0,0 +1,7 @@
+load("@rules_java//java:defs.bzl", "java_library")
+
+java_library (
+ name = "module3",
+ srcs = glob(["java/src/**/*.java"]),
+ visibility = ["//module1:__pkg__", "//module2:__pkg__"]
+)
diff --git a/bundles/testdata/workspaces/002/module3/java/src/log/Logger.java b/bundles/testdata/workspaces/002/module3/java/src/log/Logger.java
new file mode 100644
index 000000000..e1bdd8c6c
--- /dev/null
+++ b/bundles/testdata/workspaces/002/module3/java/src/log/Logger.java
@@ -0,0 +1,16 @@
+package log;
+
+import java.time.Instant;
+
+public final class Logger {
+
+ private Logger() {
+ throw new RuntimeException();
+ }
+
+ public static void logDebug(String message) {
+ String output = String.format("[DEBUG] %s", message);
+ System.out.println(output);
+ }
+
+}
diff --git a/bundles/testdata/workspaces/002/tools/ide/my_macro_analyzer.scl b/bundles/testdata/workspaces/002/tools/ide/my_macro_analyzer.scl
new file mode 100644
index 000000000..22a14d516
--- /dev/null
+++ b/bundles/testdata/workspaces/002/tools/ide/my_macro_analyzer.scl
@@ -0,0 +1,3 @@
+def analyze(function_info):
+
+ return False
diff --git a/bundles/testdata/workspaces/002/tools/macro/.bazeltargets b/bundles/testdata/workspaces/002/tools/macro/.bazeltargets
new file mode 100644
index 000000000..120d56ae4
--- /dev/null
+++ b/bundles/testdata/workspaces/002/tools/macro/.bazeltargets
@@ -0,0 +1,2 @@
+# targets used to setup the project
+# (do not modify manually; synchronize projects to update)
\ No newline at end of file
diff --git a/bundles/testdata/workspaces/002/tools/macro/BUILD b/bundles/testdata/workspaces/002/tools/macro/BUILD
new file mode 100644
index 000000000..e69de29bb
diff --git a/bundles/testdata/workspaces/002/tools/macro/defs.bzl b/bundles/testdata/workspaces/002/tools/macro/defs.bzl
new file mode 100644
index 000000000..fdbc2fbcb
--- /dev/null
+++ b/bundles/testdata/workspaces/002/tools/macro/defs.bzl
@@ -0,0 +1,9 @@
+load("@rules_java//java:defs.bzl", "java_library", "java_test")
+
+def my_macro(name, **kwargs):
+
+ java_library (
+ name = name,
+ srcs = native.glob(["java/src/**/*.java"]),
+ **kwargs
+ )
diff --git a/docs/common/projectviews.md b/docs/common/projectviews.md
index 53639796f..c464a3f06 100644
--- a/docs/common/projectviews.md
+++ b/docs/common/projectviews.md
@@ -75,7 +75,7 @@ Does nothing when `derive_targets_from_directories` is not set or set to `false`
The default value is `default`, which maps to `bazel-query` and will use `bazel query` to discover targets.
It's possible to add custom strategies via an extension point.
-#### `bazel query`
+#### `bazel-query`
This performs a `bazel query` to obtain all list of all `BUILD` files.
The list is then processed and directory information is translated into a list of Bazel packages.
@@ -86,6 +86,13 @@ The remaining list of packages is queried again using `bazel query` to obtain al
See [BazelQueryTargetDiscovery.java](../../bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BazelQueryTargetDiscovery.java) to read more about default discovery behavior.
+#### `buildfiles`
+
+This also performs a `bazel query` but ignores targets.
+It's a perfect combination (and performance optimization) when used with the `project-per-buildfile` target provisioning strategy.
+
+See [BazelBuildfileTargetDiscovery.java](../../bundles/com.salesforce.bazel.eclipse.core/src/com/salesforce/bazel/eclipse/core/model/discovery/BazelBuildfileTargetDiscovery.java) to read more about discovery behavior.
+
### `target_provisioning_strategy`
Customize how targets are imported/resolved.
@@ -146,6 +153,18 @@ For details please read the JavaDoc (and Java code) of [ProjectPerPackageProvisi
* It requires running `bazel build` to detect classpath configuration.
* Is not fully implemented and required help/work/contributions.
+#### `project-per-buildfile`
+
+This is an experimental strategy which tries to avoid running Bazel commands for importing projects.
+It does so by parsing `BUILD` files directly.
+Each `BUILD` file is mapped to a single project.
+Nested packages in the same source folder are ignored.
+
+When it discovers an unknown function it can delegate to extensible analyzers for computing project information.
+Analyzers can we written in Java as IDE plug-ins or Starlark functions.
+However, the Starlark dialect is very limited and does not support the full Bazel dialect and built-in functions.
+It purely exists to allow macro/rule implementors to also provide the IDE with necessary information.
+
### `target_provisioning_settings`
A list of settings to further tweak the `target_provisioning_strategy`.
diff --git a/tests/com.salesforce.bazel.eclipse.core.tests/.classpath b/tests/com.salesforce.bazel.eclipse.core.tests/.classpath
index 675a5e296..1aa9eca95 100644
--- a/tests/com.salesforce.bazel.eclipse.core.tests/.classpath
+++ b/tests/com.salesforce.bazel.eclipse.core.tests/.classpath
@@ -1,6 +1,6 @@
-
+
diff --git a/tests/com.salesforce.bazel.eclipse.core.tests/.settings/com.salesforce.bazel.eclipse.core.tests - all headless tests.launch b/tests/com.salesforce.bazel.eclipse.core.tests/.settings/com.salesforce.bazel.eclipse.core.tests - all headless tests.launch
index 1b2e4c3fd..83eeecb80 100644
--- a/tests/com.salesforce.bazel.eclipse.core.tests/.settings/com.salesforce.bazel.eclipse.core.tests - all headless tests.launch
+++ b/tests/com.salesforce.bazel.eclipse.core.tests/.settings/com.salesforce.bazel.eclipse.core.tests - all headless tests.launch
@@ -17,6 +17,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -47,30 +57,24 @@
-
-
+
-
+
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
@@ -87,16 +91,10 @@
-
-
-
-
-
+
-
-
+
-
@@ -105,15 +103,14 @@
-
+
-
-
+
@@ -134,23 +131,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -163,13 +143,6 @@
-
-
-
-
-
-
-
@@ -180,7 +153,7 @@
-
+
@@ -193,23 +166,12 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -224,6 +186,7 @@
+
@@ -249,15 +212,11 @@
-
-
-
-
-
-
-
+
+
-
+
+
@@ -267,12 +226,469 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/com.salesforce.bazel.eclipse.core.tests/.settings/org.eclipse.jdt.core.prefs b/tests/com.salesforce.bazel.eclipse.core.tests/.settings/org.eclipse.jdt.core.prefs
index 1f3e19a99..3ee841fb0 100644
--- a/tests/com.salesforce.bazel.eclipse.core.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/tests/com.salesforce.bazel.eclipse.core.tests/.settings/org.eclipse.jdt.core.prefs
@@ -1,13 +1,13 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
-org.eclipse.jdt.core.compiler.compliance=17
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
+org.eclipse.jdt.core.compiler.compliance=21
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
-org.eclipse.jdt.core.compiler.source=17
+org.eclipse.jdt.core.compiler.source=21
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line=true
diff --git a/tests/com.salesforce.bazel.eclipse.core.tests/META-INF/MANIFEST.MF b/tests/com.salesforce.bazel.eclipse.core.tests/META-INF/MANIFEST.MF
index 1ebe18c6a..f22cd4cc2 100644
--- a/tests/com.salesforce.bazel.eclipse.core.tests/META-INF/MANIFEST.MF
+++ b/tests/com.salesforce.bazel.eclipse.core.tests/META-INF/MANIFEST.MF
@@ -6,11 +6,12 @@ Bundle-Version: 2.0.0.qualifier
Bundle-Vendor: Bazel Eclipse Feature
Fragment-Host: com.salesforce.bazel.eclipse.core;bundle-version="2.0.0"
Automatic-Module-Name: com.salesforce.bazel.eclipse.core.tests
-Bundle-RequiredExecutionEnvironment: JavaSE-17
+Bundle-RequiredExecutionEnvironment: JavaSE-21
Import-Package: org.hamcrest;version="2.2.0",
org.hamcrest.collection;version="2.2.0",
- org.junit.jupiter.api;version="5.9.2",
- org.junit.jupiter.api.extension;version="5.9.2",
- org.junit.jupiter.api.io;version="5.9.2"
+ org.junit.jupiter.api;version="[5.11.0,6.0.0)",
+ org.junit.jupiter.api.extension;version="[5.11.0,6.0.0)",
+ org.junit.jupiter.api.function;version="[5.11.0,6.0.0)",
+ org.junit.jupiter.api.io;version="[5.11.0,6.0.0)"
Require-Bundle: testdata;bundle-version="1.0.0",
com.salesforce.bazel.sdk
diff --git a/tests/com.salesforce.bazel.eclipse.core.tests/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkMacroCallAnalyzerTest.java b/tests/com.salesforce.bazel.eclipse.core.tests/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkMacroCallAnalyzerTest.java
new file mode 100644
index 000000000..9e7622b3f
--- /dev/null
+++ b/tests/com.salesforce.bazel.eclipse.core.tests/src/com/salesforce/bazel/eclipse/core/model/discovery/analyzers/starlark/StarlarkMacroCallAnalyzerTest.java
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2024 Salesforce and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Salesforce - adapted from M2E, JDT or other Eclipse project
+ */
+package com.salesforce.bazel.eclipse.core.model.discovery.analyzers.starlark;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.eclipse.core.runtime.CoreException;
+import org.junit.jupiter.api.Test;
+
+import net.starlark.java.syntax.ParserInput;
+
+class StarlarkMacroCallAnalyzerTest {
+
+ @Test
+ void parseInputAndGetAnalyzeFunction_fails_for_missing_function() throws Exception {
+ assertThrows(CoreException.class, () -> {
+ StarlarkMacroCallAnalyzer.parseInputAndGetAnalyzeFunction(ParserInput.fromString("""
+ def analyze_wrong_name():
+ return None
+ """, "test only"), "test only");
+ });
+ assertThrows(CoreException.class, () -> {
+ StarlarkMacroCallAnalyzer.parseInputAndGetAnalyzeFunction(ParserInput.fromString("""
+ """, "test only"), "test only");
+ });
+ }
+
+ @Test
+ void parseInputAndGetAnalyzeFunction_fails_for_missing_or_misnamed_args() throws Exception {
+ assertThrows(CoreException.class, () -> {
+ StarlarkMacroCallAnalyzer.parseInputAndGetAnalyzeFunction(ParserInput.fromString("""
+ def analyze():
+ return None
+ """, "test only"), "test only");
+ });
+ assertThrows(CoreException.class, () -> {
+ StarlarkMacroCallAnalyzer.parseInputAndGetAnalyzeFunction(ParserInput.fromString("""
+ def analyze(wrong_name):
+ return None
+ """, "test only"), "test only");
+ });
+ assertThrows(CoreException.class, () -> {
+ StarlarkMacroCallAnalyzer.parseInputAndGetAnalyzeFunction(ParserInput.fromString("""
+ def analyze(function_info, additional_name):
+ return None
+ """, "test only"), "test only");
+ });
+ }
+
+ @Test
+ void parseInputAndGetAnalyzeFunction_ok() throws Exception {
+ StarlarkMacroCallAnalyzer.parseInputAndGetAnalyzeFunction(ParserInput.fromString("""
+ def analyze(function_info):
+ return None
+ """, "test only"), "test only");
+ }
+}
diff --git a/tests/com.salesforce.bazel.eclipse.core.tests/src/com/salesforce/bazel/eclipse/core/tests/it/Workspace002Test_Provisioning.java b/tests/com.salesforce.bazel.eclipse.core.tests/src/com/salesforce/bazel/eclipse/core/tests/it/Workspace002Test_Provisioning.java
new file mode 100644
index 000000000..71ace4afa
--- /dev/null
+++ b/tests/com.salesforce.bazel.eclipse.core.tests/src/com/salesforce/bazel/eclipse/core/tests/it/Workspace002Test_Provisioning.java
@@ -0,0 +1,101 @@
+package com.salesforce.bazel.eclipse.core.tests.it;
+
+import static com.salesforce.bazel.eclipse.core.BazelCoreSharedContstants.BAZEL_NATURE_ID;
+import static java.lang.String.format;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static testdata.SharedTestData.BAZELPROJECT_FILE;
+import static testdata.SharedTestData.WORKSPACE_002;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.IVMInstallType;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.salesforce.bazel.eclipse.core.BazelCore;
+import com.salesforce.bazel.sdk.BazelVersion;
+
+import testdata.SharedTestData;
+import testdata.utils.LoggingProgressProviderExtension;
+import testdata.utils.ProvisionWorkspaceExtension;
+
+/**
+ * Integration tests using the 001 test workspace.
+ *
+ * This test imports a Bazel workspace into Eclipse and then performs a bunch of tests with it. It cannot be execute as
+ * a plain JUnit test but needs to run in an Eclipse environment.
+ *
+ */
+@TestMethodOrder(MethodOrderer.MethodName.class)
+@ExtendWith(LoggingProgressProviderExtension.class)
+public class Workspace002Test_Provisioning {
+
+ private static final BazelVersion BAZEL_VERSION = new BazelVersion(7, 4, 1);
+
+ @RegisterExtension
+ static ProvisionWorkspaceExtension provisionedWorkspace =
+ new ProvisionWorkspaceExtension(WORKSPACE_002, SharedTestData.class, BAZELPROJECT_FILE, BAZEL_VERSION);
+
+ private void assertProjectWithProperNatures(IProject project) throws CoreException {
+ assertTrue(project.exists(), format("Project '%s' expected to exist!", project.getName()));
+ assertTrue(
+ project.hasNature(JavaCore.NATURE_ID),
+ format("Project '%s' expected to hava Java nature!", project.getName()));
+ assertTrue(
+ project.hasNature(BAZEL_NATURE_ID),
+ format("Project '%s' expected to hava Bazel nature!", project.getName()));
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @BeforeEach
+ void setUp() throws Exception {}
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @AfterEach
+ void tearDown() throws Exception {}
+
+ @Test
+ void test0001_check_basic_assumptions_in_the_model() throws CoreException {
+ var root = ResourcesPlugin.getWorkspace().getRoot();
+
+ var workspaceProject = root.getProject("testdata_workspaces_002");
+ assertProjectWithProperNatures(workspaceProject);
+
+ var bazelWorkspaceProject = BazelCore.create(workspaceProject);
+ assertTrue(bazelWorkspaceProject.isWorkspaceProject(), "Expect to have the workspace project at this point!");
+ }
+
+ @Test
+ void test0002_jdk_setup_for_workspace() throws CoreException {
+ var bazelWorkspace = provisionedWorkspace.getBazelWorkspace();
+
+ var vmInstallTypes = JavaRuntime.getVMInstallTypes();
+ IVMInstall workspaceVm = null;
+ for (IVMInstallType vmInstallType : vmInstallTypes) {
+ var vmInstalls = vmInstallType.getVMInstalls();
+ for (IVMInstall vm : vmInstalls) {
+ if (vm.getName().contains(bazelWorkspace.getName())) {
+ assertNull(workspaceVm, "multiple VMs found for workspace; this is not ok");
+ workspaceVm = vm;
+ }
+ }
+ }
+ assertNotNull(workspaceVm, "no VMs found for workspace; this is not ok");
+ }
+
+}