Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A strategy for parsing build files instead of queries & aspect #509

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bundles/com.salesforce.bazel.eclipse.core/.classpath
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21">
<attributes>
<attribute name="module" value="true"/>
</attributes>
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions bundles/com.salesforce.bazel.eclipse.core/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@
class="com.salesforce.bazel.eclipse.core.model.discovery.BazelBuildfileTargetDiscovery"
name="buildfiles">
</targetDiscoveryStrategy>
<targetProvisioningStrategy
class="com.salesforce.bazel.eclipse.core.model.discovery.BuildfileDrivenProvisioningStrategy"
name="project-per-buildfile">
</targetProvisioningStrategy>
<targetProvisioningStrategy
class="com.salesforce.bazel.eclipse.core.model.discovery.BuildFileAndVisibilityDrivenProvisioningStrategy"
name="build-file-and-visibility-driven">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1655,7 +1655,7 @@ private void linkSourceFilesWithoutCommonRoot(JavaSourceInfo sourceInfo, IFolder
Set<IFile> 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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <code>analyze</code> function
*/
@StarlarkBuiltin(name = "AnalyzeInfo", documented = false)
public class StarlarkAnalyzeInfo {
public class StarlarkAnalyzeInfo implements StarlarkValue {

private List<String> convertToStringList(Sequence<?> exclude, String nameForErrorMessage) throws EvalException {
List<String> stringList = new ArrayList<>();
Expand All @@ -54,12 +55,11 @@ private List<String> 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));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class StarlarkFunctionCallInfo implements StarlarkValue {
private static final Logger LOG = LoggerFactory.getLogger(StarlarkFunctionCallInfo.class);

private final FunctionCall functionCall;
private volatile Dict<String, Object> args;

public StarlarkFunctionCallInfo(FunctionCall functionCall) {
this.functionCall = functionCall;
Expand Down Expand Up @@ -84,7 +85,11 @@ private Dict<String, Object> evaluateArgs(StarlarkThread thread) {

@StarlarkMethod(name = "args", structField = true, useStarlarkThread = true)
public Dict<String, Object> 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,25 @@
*/
public class StarlarkMacroCallAnalyzer implements MacroCallAnalyzer {

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 <code>'analyze'</code> function.
*
* @param input
* the input to parse
* @param file
* for error reporting only
* @return the parsed function (never <code>null</code>)
* @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<String, Object> env = ImmutableMap.builder();
//Starlark.addMethods(env, new CqueryDialectGlobals(), starlarkSemantics);
Expand All @@ -89,41 +92,68 @@ public StarlarkMacroCallAnalyzer(BazelWorkspace bazelWorkspace, WorkspacePath bz
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 bzlFile)
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));
}

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);
thread.setMaxExecutionSteps(500_000L);

var kwargs = Map.<String, Object> of("macro_info", new StarlarkFunctionCallInfo(macroCall));
var kwargs = Map.<String, Object> of(FUNCTION_INFO, new StarlarkFunctionCallInfo(macroCall));
var result = Starlark.call(thread, analyzeFunction, null, 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 e) {
throw new CoreException(
Status.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

/**
Expand All @@ -33,17 +29,6 @@
@StarlarkBuiltin(name = "native", documented = false)
public class StarlarkNativeModuleApiDummy {

private List<String> convertToStringList(Sequence<?> exclude, String nameForErrorMessage) throws EvalException {
List<String> 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 <code>glob</code> to turn into {@link StarlarkGlobInfo}.
*
Expand All @@ -56,12 +41,8 @@ private List<String> 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<String> include, Sequence<String> exclude, StarlarkInt excludeDirectories,
Object allowEmpty) throws EvalException, InterruptedException {
return new StarlarkGlobInfo(new GlobInfo(include, exclude));
}
}
2 changes: 2 additions & 0 deletions bundles/testdata/src/testdata/SharedTestData.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public interface SharedTestData {

String WORKSPACE_001 = "/workspaces/001";

String WORKSPACE_002 = "/workspaces/001";

IPath BAZELPROJECT_FILE = new Path(".bazelproject");

}
6 changes: 6 additions & 0 deletions bundles/testdata/workspaces/001/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -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
###############################################################################
16 changes: 16 additions & 0 deletions bundles/testdata/workspaces/002/.bazelproject
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 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
11 changes: 11 additions & 0 deletions bundles/testdata/workspaces/002/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Eclipse metadata
.classpath
.project
.settings/
.eclipse/

# Bazel folder
/bazel-*

# ignore the Bazel version file
.bazelversion
6 changes: 6 additions & 0 deletions bundles/testdata/workspaces/002/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -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
###############################################################################
27 changes: 27 additions & 0 deletions bundles/testdata/workspaces/002/WORKSPACE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
workspace(name = "testdata_workspaces_002")

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

# bazel-skylib 0.8.0 released 2019.03.20 (https://github.com/bazelbuild/bazel-skylib/releases/tag/0.8.0)
skylib_version = "0.8.0"
http_archive(
name = "bazel_skylib",
type = "tar.gz",
url = "https://github.com/bazelbuild/bazel-skylib/releases/download/{}/bazel-skylib.{}.tar.gz".format (skylib_version, skylib_version),
sha256 = "2ef429f5d7ce7111263289644d233707dba35e39696377ebab8b0bc701f7818e",
)

http_archive(
name = "salesforce_rules_mybuilder",
url = "https://github.com/salesforce/bazel-java-builder-template/archive/c443e2391ff547c01f5ca3f14a1e84d85c13d16d.zip",
strip_prefix = "bazel-java-builder-template-c443e2391ff547c01f5ca3f14a1e84d85c13d16d",
sha256 = "8e0aac87c235744884161e69346d6a6d3d729ef8072e33a9883fbb27735d01d8",
)

load("@salesforce_rules_mybuilder//mybuilder:repositories.bzl", "rules_mybuilder_dependencies", "rules_mybuilder_toolchains")
rules_mybuilder_dependencies()
rules_mybuilder_toolchains()

# Maven dependencies
load("//third_party/maven:dependencies.bzl", "maven_dependencies")
maven_dependencies()
5 changes: 5 additions & 0 deletions bundles/testdata/workspaces/002/module1/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
load("//tools/macro:defs.bzl", "my_macro")

my_macro (
name = "module1",
)
Loading
Loading