Introduce the 'same_pkg_direct_rdeps' query function.
RELNOTES[NEW]: There is now a 'same_pkg_direct_rdeps' query function. See the
query documentation for more details.
PiperOrigin-RevId: 214961929
diff --git a/site/docs/query-how-to.html b/site/docs/query-how-to.html
index 7bf0b33..18c38ef 100644
--- a/site/docs/query-how-to.html
+++ b/site/docs/query-how-to.html
@@ -421,7 +421,7 @@
<h4>What targets directly depend on T, in T's package?</h4>
-<pre>bazel query 'let t = T in rdeps(siblings($t), $t, 1)'</pre>
+<pre>bazel query 'same_pkg_direct_rdeps(T)'</pre>
<p><a name="How_do_I_break_a_dependency_"></a></p>
diff --git a/site/docs/query.html b/site/docs/query.html
index 605c159..9c7ede7 100644
--- a/site/docs/query.html
+++ b/site/docs/query.html
@@ -535,6 +535,7 @@
<a href="#loadfiles">loadfiles</a><br/>
<a href="#rdeps">rdeps</a><br/>
<a href="#allrdeps">allrdeps</a><br/>
+<a href="#same_pkg_direct_rdeps">same_pkg_direct_rdeps</a><br/>
<a href="#siblings">siblings</a><br/>
<a href="#some">some</a><br/>
<a href="#path-operators">somepath</a><br/>
@@ -617,6 +618,13 @@
equivalent to <code>rdeps(//foo/..., //bar)</code>.
</p>
+<h3 id="same_pkg_direct_rdeps">Direct reverse dependencies in the same package: same_pkg_direct_rdeps</h3>
+<pre>expr ::= same_pkg_direct_rdeps(<var>expr</var>)</pre>
+<p>
+ The <code>same_pkg_direct_rdeps(<var>x</var>)</code> operator evalutes to the full set of targets
+ that are in the same package as a target in the argument set, and which directly depend on it.
+</p>
+
<h3 id="siblings">Dealing with a target's package: siblings</h3>
<pre>expr ::= siblings(<var>expr</var>)</pre>
<p>
diff --git a/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java b/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java
index b301676..afdbee3 100644
--- a/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/query2/engine/QueryEnvironment.java
@@ -590,6 +590,7 @@
new LabelsFunction(),
new LoadFilesFunction(),
new RdepsFunction(),
+ new SamePkgDirectRdepsFunction(),
new SiblingsFunction(),
new SomeFunction(),
new SomePathFunction(),
diff --git a/src/main/java/com/google/devtools/build/lib/query2/engine/SamePkgDirectRdepsFunction.java b/src/main/java/com/google/devtools/build/lib/query2/engine/SamePkgDirectRdepsFunction.java
new file mode 100644
index 0000000..7b0067d
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/query2/engine/SamePkgDirectRdepsFunction.java
@@ -0,0 +1,71 @@
+// Copyright 2018 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.query2.engine;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Argument;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.ArgumentType;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryFunction;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.QueryTaskFuture;
+import com.google.devtools.build.lib.query2.engine.QueryEnvironment.ThreadSafeMutableSet;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A "same_pkg_direct_rdeps" query expression, which computes all of the targets in the same package
+ * of the given targets which directly depend on them.
+ *
+ * <pre>expr ::= SAME_PKG_DIRECT_RDEPS '(' expr ')'</pre>
+ */
+public class SamePkgDirectRdepsFunction implements QueryFunction {
+
+ @Override
+ public String getName() {
+ return "same_pkg_direct_rdeps";
+ }
+
+ @Override
+ public int getMandatoryArguments() {
+ return 1;
+ }
+
+ @Override
+ public Iterable<ArgumentType> getArgumentTypes() {
+ return ImmutableList.of(ArgumentType.EXPRESSION);
+ }
+
+ @Override
+ public <T> QueryTaskFuture<Void> eval(
+ QueryEnvironment<T> env,
+ QueryExpressionContext<T> context,
+ final QueryExpression expression,
+ List<Argument> args,
+ final Callback<T> callback) {
+ Uniquifier<T> uniquifier = env.createUniquifier();
+ return env.eval(
+ args.get(0).getExpression(),
+ context,
+ partialResult -> {
+ for (T target : partialResult) {
+ ThreadSafeMutableSet<T> siblings = env.createThreadSafeMutableSet();
+ siblings.addAll(env.getSiblingTargetsInPackage(target));
+ env.buildTransitiveClosure(expression, siblings, /*maxDepth=*/ 1);
+ Iterable<T> rdeps = env.getReverseDeps(Collections.singleton(target), context);
+ callback.process(uniquifier.unique(Iterables.filter(rdeps, siblings::contains)));
+ }
+ });
+ }
+}