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

[feature] build_flags support in project view #194

Merged
merged 22 commits into from
Apr 11, 2022
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### Features 🎉

- `build_flags` support in project view.
| [#194](https://github.com/JetBrains/bazel-bsp/pull/194)
- New installer - it is possible to specify installation directory
and project view file using flags.
| [#201](https://github.com/JetBrains/bazel-bsp/pull/201)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,39 @@ public class BazelRunner {
private final BspClientLogger bspClientLogger;
private final BazelInfo bazelInfo;

private final List<String> defaultFlags;

// This is runner without workspace path. It is used to determine workspace
// path and create a fully functional runner.
public static BazelRunner inCwd(String bazelBinaryPath, BspClientLogger bspClientLogger) {
return new BazelRunner(bazelBinaryPath, bspClientLogger, null);
public static BazelRunner inCwd(String bazelBinaryPath, BspClientLogger bspClientLogger, List<String> defaultFlags) {
return new BazelRunner(bazelBinaryPath, bspClientLogger, null, defaultFlags);
}

public static BazelRunner of(
String bazelBinaryPath, BspClientLogger bspClientLogger, BazelInfo bazelInfo) {
return new BazelRunner(bazelBinaryPath, bspClientLogger, bazelInfo);
String bazelBinaryPath, BspClientLogger bspClientLogger, BazelInfo bazelInfo, List<String> defaultFlags) {
return new BazelRunner(bazelBinaryPath, bspClientLogger, bazelInfo, defaultFlags);
}

private BazelRunner(
String bazelBinaryPath, BspClientLogger bspClientLogger, BazelInfo bazelInfo) {
String bazelBinaryPath, BspClientLogger bspClientLogger, BazelInfo bazelInfo, List<String> defaultFlags) {
this.bazel = bazelBinaryPath;
this.bspClientLogger = bspClientLogger;
this.bazelInfo = bazelInfo;
this.defaultFlags = defaultFlags;
}

public BazelRunnerCommandBuilder commandBuilder() {
return new BazelRunnerCommandBuilder(this);
}

BazelProcess runBazelCommandBes(String command, List<String> flags, List<String> arguments) {
List<String> newFlags = getBesFlags(flags);
var newFlags = getBesFlags(flags);

return runBazelCommand(command, newFlags, arguments);
}

private List<String> getBesFlags(List<String> flags) {
List<String> newFlags = Lists.newArrayList(getBesBackendAddress(), PUBLISH_ALL_ACTIONS);
var newFlags = Lists.newArrayList(getBesBackendAddress(), PUBLISH_ALL_ACTIONS);
newFlags.addAll(flags);

return newFlags;
Expand Down Expand Up @@ -87,6 +91,7 @@ private synchronized BazelProcess runBazelProcess(

private List<String> getProcessArgs(String command, List<String> flags, List<String> arguments) {
var processArgs = Lists.newArrayList(bazel, command);
processArgs.addAll(defaultFlags);
processArgs.addAll(flags);
processArgs.addAll(arguments);
return processArgs;
Expand Down
16 changes: 13 additions & 3 deletions executioncontext/projectview/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,7 @@ These sections are read when server is starting -- usually when you open a proje
A list of bazel target expressions, they support `/...` notation.

Targets are built during the server lifetime, so the more targets you have, the slower your IDE experience might be. You
can
use negative targets to have server ignore certain targets (
can use negative targets to have server ignore certain targets (
e.g. `-//executioncontext/projectview/src/main/java/org/jetbrains/bsp/bazel/projectview/parser/...`).

##### example:
Expand Down Expand Up @@ -200,7 +199,18 @@ _We are working on it, you can expect support for this section in future release

#### build_flags

_We are working on it, you can expect support for this section in future releases._
A set of bazel flags added to **all** bazel command invocations.

##### example:

```
build_flags:
--define=ij_product=intellij-latest
```

##### default:

No flags.

---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewBazelPathSection;
import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewBuildFlagsSection;
import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewDebuggerAddressSection;
import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewExcludableListSection;
import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewJavaPathSection;
import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewListSection;
import org.jetbrains.bsp.bazel.projectview.model.sections.ProjectViewSingletonSection;
Expand All @@ -37,15 +39,20 @@ public class ProjectView {
/** path to java to run a server */
private final Option<ProjectViewJavaPathSection> javaPath;

/** bazel flags added to all bazel command invocations */
private final Option<ProjectViewBuildFlagsSection> buildFlags;

private ProjectView(
Option<ProjectViewTargetsSection> targets,
Option<ProjectViewBazelPathSection> bazelPath,
Option<ProjectViewDebuggerAddressSection> debuggerAddress,
Option<ProjectViewJavaPathSection> javaPath) {
Option<ProjectViewJavaPathSection> javaPath,
Option<ProjectViewBuildFlagsSection> buildFlags) {
this.targets = targets;
this.bazelPath = bazelPath;
this.debuggerAddress = debuggerAddress;
this.javaPath = javaPath;
this.buildFlags = buildFlags;
}

public static ProjectView.Builder builder() {
Expand All @@ -58,7 +65,7 @@ public Option<ProjectViewTargetsSection> getTargets() {

public TargetSpecs targetSpecs() {
return targets
.map(s -> new TargetSpecs(s.getIncludedValues(), s.getExcludedValues()))
.map(s -> new TargetSpecs(s.getValues(), s.getExcludedValues()))
.getOrElse(TargetSpecs.empty());
}

Expand All @@ -74,6 +81,10 @@ public Option<ProjectViewJavaPathSection> getJavaPath() {
return javaPath;
}

public Option<ProjectViewBuildFlagsSection> getBuildFlags() {
return buildFlags;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand All @@ -82,12 +93,13 @@ public boolean equals(Object o) {
return targets.equals(that.targets)
&& bazelPath.equals(that.bazelPath)
&& debuggerAddress.equals(that.debuggerAddress)
&& javaPath.equals(that.javaPath);
&& javaPath.equals(that.javaPath)
&& buildFlags.equals(that.buildFlags);
}

@Override
public int hashCode() {
return Objects.hash(targets, bazelPath, debuggerAddress, javaPath);
return Objects.hash(targets, bazelPath, debuggerAddress, javaPath, buildFlags);
}

@Override
Expand All @@ -101,6 +113,8 @@ public String toString() {
+ debuggerAddress
+ ", javaPath="
+ javaPath
+ ", buildFlags="
+ buildFlags
+ '}';
}

Expand All @@ -116,6 +130,8 @@ public static class Builder {

private Option<ProjectViewJavaPathSection> javaPath = Option.none();

private Option<ProjectViewBuildFlagsSection> buildFlags = Option.none();

private Builder() {}

public Builder imports(List<Try<ProjectView>> importedProjectViews) {
Expand Down Expand Up @@ -143,6 +159,11 @@ public Builder javaPath(Option<ProjectViewJavaPathSection> javaPath) {
return this;
}

public Builder buildFlags(Option<ProjectViewBuildFlagsSection> buildFlags) {
this.buildFlags = buildFlags;
return this;
}

public Try<ProjectView> build() {
log.debug(
"Building project view with"
Expand All @@ -151,12 +172,14 @@ public Try<ProjectView> build() {
+ " targets: {},"
+ " bazel path: {},"
+ " debugger address: {},"
+ " java path: {}.",
+ " java path: {},"
+ " build flags: {}.",
importedProjectViews,
targets,
bazelPath,
debuggerAddress,
javaPath);
javaPath,
buildFlags);

return Try.sequence(importedProjectViews).map(Seq::toList).map(this::buildWithImports);
}
Expand All @@ -166,6 +189,7 @@ private ProjectView buildWithImports(List<ProjectView> importedProjectViews) {
var bazelPath = combineBazelPathSection(importedProjectViews);
var debuggerAddress = combineDebuggerAddressSection(importedProjectViews);
var javaPath = combineJavaPathSection(importedProjectViews);
var buildFlags = combineBuildFlagsSection(importedProjectViews);

log.debug(
"Building project view with combined"
Expand All @@ -178,7 +202,7 @@ private ProjectView buildWithImports(List<ProjectView> importedProjectViews) {
debuggerAddress,
javaPath);

return new ProjectView(targets, bazelPath, debuggerAddress, javaPath);
return new ProjectView(targets, bazelPath, debuggerAddress, javaPath, buildFlags);
}

private Option<ProjectViewTargetsSection> combineTargetsSection(
Expand All @@ -188,18 +212,30 @@ private Option<ProjectViewTargetsSection> combineTargetsSection(
importedProjectViews,
targets,
ProjectView::getTargets,
ProjectViewListSection::getIncludedValues);
ProjectViewExcludableListSection::getValues);
var excludedTargets =
combineListValuesWithImported(
importedProjectViews,
targets,
ProjectView::getTargets,
ProjectViewListSection::getExcludedValues);
ProjectViewExcludableListSection::getExcludedValues);

return createInstanceOfListSectionOrEmpty(
return createInstanceOfExcludableListSectionOrEmpty(
includedTargets, excludedTargets, ProjectViewTargetsSection::new);
}

private Option<ProjectViewBuildFlagsSection> combineBuildFlagsSection(
List<ProjectView> importedProjectViews) {
var flags =
combineListValuesWithImported(
importedProjectViews,
buildFlags,
ProjectView::getBuildFlags,
ProjectViewListSection::getValues);

return createInstanceOfListSectionOrEmpty(flags, ProjectViewBuildFlagsSection::new);
}

private <V, S extends ProjectViewListSection<V>, T extends Option<S>>
List<V> combineListValuesWithImported(
List<ProjectView> importedProjectViews,
Expand All @@ -215,14 +251,23 @@ List<V> combineListValuesWithImported(
.foldLeft(sectionValues, List::appendAll);
}

private <V, T extends ProjectViewExcludableListSection<V>>
Option<T> createInstanceOfExcludableListSectionOrEmpty(
List<V> includedElements,
List<V> excludedElements,
BiFunction<List<V>, List<V>, T> constructor) {
var areListsEmpty = includedElements.isEmpty() && excludedElements.isEmpty();
var isAnyElementInLists = !areListsEmpty;

return Option.when(
isAnyElementInLists, constructor.apply(includedElements, excludedElements));
}

private <V, T extends ProjectViewListSection<V>> Option<T> createInstanceOfListSectionOrEmpty(
List<V> includedElements,
List<V> excludedElements,
BiFunction<List<V>, List<V>, T> constructor) {
if (includedElements.isEmpty() && excludedElements.isEmpty()) {
return Option.none();
}
return Option.of(constructor.apply(includedElements, excludedElements));
List<V> values, Function<List<V>, T> constructor) {
var isAnyElementInList = !values.isEmpty();

return Option.when(isAnyElementInList, constructor.apply(values));
}

private Option<ProjectViewBazelPathSection> combineBazelPathSection(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.jetbrains.bsp.bazel.projectview.model.sections;

import io.vavr.collection.List;

public class ProjectViewBuildFlagsSection extends ProjectViewListSection<String> {

public static final String SECTION_NAME = "build_flags";

public ProjectViewBuildFlagsSection(List<String> values) {
super(SECTION_NAME, values);
}

@Override
public String toString() {
return "ProjectViewBuildFlagsSection{" + "values=" + values + '}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.jetbrains.bsp.bazel.projectview.model.sections;

import io.vavr.collection.List;
import java.util.Objects;
import org.apache.commons.collections4.CollectionUtils;

public abstract class ProjectViewExcludableListSection<T> extends ProjectViewListSection<T> {

protected final List<T> excludedValues;

protected ProjectViewExcludableListSection(
String sectionName, List<T> includedValues, List<T> excludedValues) {
super(sectionName, includedValues);
this.excludedValues = excludedValues;
}

public List<T> getExcludedValues() {
return excludedValues;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ProjectViewExcludableListSection)) return false;
ProjectViewExcludableListSection<?> that = (ProjectViewExcludableListSection<?>) o;
return CollectionUtils.isEqualCollection(values.toJavaList(), that.values.toJavaList())
&& CollectionUtils.isEqualCollection(
excludedValues.toJavaList(), that.excludedValues.toJavaList())
&& sectionName.equals(that.sectionName);
}

@Override
public int hashCode() {
return Objects.hash(values, excludedValues, sectionName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,28 @@

public abstract class ProjectViewListSection<T> extends ProjectViewSection {

protected final List<T> includedValues;
protected final List<T> excludedValues;
protected final List<T> values;

protected ProjectViewListSection(String sectionName) {
protected ProjectViewListSection(String sectionName, List<T> values) {
super(sectionName);
this.includedValues = List.of();
this.excludedValues = List.of();
this.values = values;
}

protected ProjectViewListSection(
String sectionName, List<T> includedValues, List<T> excludedValues) {
super(sectionName);
this.includedValues = includedValues;
this.excludedValues = excludedValues;
}

public List<T> getIncludedValues() {
return includedValues;
}

public List<T> getExcludedValues() {
return excludedValues;
public List<T> getValues() {
return values;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ProjectViewListSection)) return false;
ProjectViewListSection<?> that = (ProjectViewListSection<?>) o;
return CollectionUtils.isEqualCollection(
includedValues.toJavaList(), that.includedValues.toJavaList())
&& CollectionUtils.isEqualCollection(
excludedValues.toJavaList(), that.excludedValues.toJavaList())
return CollectionUtils.isEqualCollection(values.toJavaList(), that.values.toJavaList())
&& sectionName.equals(that.sectionName);
}

@Override
public int hashCode() {
return Objects.hash(includedValues, excludedValues, sectionName);
return Objects.hash(values, sectionName);
}
}