This is an automated email from the ASF dual-hosted git repository.

xiazcy pushed a commit to branch steps-taking-traversal-poc
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 7456bf6389189f3664c4d05ed453f52dd3945166
Author: Yang Xia <[email protected]>
AuthorDate: Tue Jun 2 09:21:58 2026 -0700

    add hasLabel(Traversal)
---
 .../language/grammar/DefaultGremlinBaseVisitor.java     |  4 ++++
 .../language/grammar/TraversalMethodVisitor.java        |  9 +++++++++
 .../language/translator/DotNetTranslateVisitor.java     | 10 ++++++++++
 .../process/traversal/dsl/graph/GraphTraversal.java     | 17 +++++++++++++++++
 .../gremlin/process/traversal/dsl/graph/__.java         |  7 +++++++
 .../test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  1 +
 gremlin-go/driver/cucumber/gremlin.go                   |  1 +
 gremlin-js/gremlin-javascript/test/cucumber/gremlin.js  |  1 +
 gremlin-language/src/main/antlr4/Gremlin.g4             |  1 +
 gremlin-python/src/main/python/tests/feature/gremlin.py |  1 +
 10 files changed, 52 insertions(+)

diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
index 96cd5ef97a..4fdf7c0866 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/DefaultGremlinBaseVisitor.java
@@ -487,6 +487,10 @@ public class DefaultGremlinBaseVisitor<T> extends 
AbstractParseTreeVisitor<T> im
         * {@inheritDoc}
         */
        @Override public T visitTraversalMethod_hasLabel_P(final 
GremlinParser.TraversalMethod_hasLabel_PContext ctx) { notImplemented(ctx); 
return null; }
+       /**
+        * {@inheritDoc}
+        */
+       @Override public T visitTraversalMethod_hasLabel_Traversal(final 
GremlinParser.TraversalMethod_hasLabel_TraversalContext ctx) { 
notImplemented(ctx); return null; }
        /**
         * {@inheritDoc}
         */
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
index 1c99745f60..518196daef 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/TraversalMethodVisitor.java
@@ -771,6 +771,15 @@ public class TraversalMethodVisitor extends 
TraversalRootVisitor<GraphTraversal>
         return 
graphTraversal.hasLabel(antlr.traversalPredicateVisitor.visitTraversalPredicate(ctx.traversalPredicate()));
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public GraphTraversal visitTraversalMethod_hasLabel_Traversal(final 
GremlinParser.TraversalMethod_hasLabel_TraversalContext ctx) {
+        final Traversal.Admin<?, ?> traversal = (Traversal.Admin<?, ?>) 
antlr.tvisitor.visitNestedTraversal(ctx.nestedTraversal());
+        return graphTraversal.hasLabel((Traversal<?, ?>) traversal);
+    }
+
     /**
      * {@inheritDoc}
      */
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
index 7ce385c925..540f650039 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java
@@ -745,6 +745,16 @@ public class DotNetTranslateVisitor extends 
AbstractTranslateVisitor {
         return null;
     }
 
+    @Override
+    public Void visitTraversalMethod_hasLabel_Traversal(final 
GremlinParser.TraversalMethod_hasLabel_TraversalContext ctx) {
+        final String step = ctx.getChild(0).getText();
+        sb.append(convertToPascalCase(step));
+        sb.append("(");
+        visit(ctx.nestedTraversal());
+        sb.append(")");
+        return null;
+    }
+
     @Override
     public Void visitTraversalMethod_hasLabel_String_String(final 
GremlinParser.TraversalMethod_hasLabel_String_StringContext ctx) {
         // if there is only one argument then cast to string otherwise it's 
ambiguous with hasLabel(P)
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 8364cb8332..552dec3be8 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -2894,6 +2894,23 @@ public interface GraphTraversal<S, E> extends 
Traversal<S, E> {
         }
     }
 
+    /**
+     * Filters vertices, edges and vertex properties based on their label 
using a child traversal
+     * whose results are resolved at runtime against the current traverser.
+     *
+     * @param traversal the child traversal whose results are used as the 
label filter value
+     * @return the traversal with an appended {@link HasStep}
+     * @see <a 
href="http://tinkerpop.apache.org/docs/${project.version}/reference/#has-step"; 
target="_blank">Reference Documentation - Has Step</a>
+     * @since 4.0.0
+     */
+    public default GraphTraversal<S, E> hasLabel(final Traversal<?, ?> 
traversal) {
+        if (null == traversal) return hasLabel((String) null);
+        ChildTraversalValidator.validateFilterContext(traversal.asAdmin());
+        this.asAdmin().getGremlinLang().addStep(Symbols.hasLabel, traversal);
+        final HasContainer hasContainer = new 
HasContainer(T.label.getAccessor(), traversal.asAdmin());
+        return this.asAdmin().addStep(new HasStep(this.asAdmin(), 
hasContainer));
+    }
+
     /**
      * Filters vertices, edges and vertex properties based on their label.
      *
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index 3dc2ed0651..46eddc4e2f 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -1212,6 +1212,13 @@ public class __ {
         return __.<A>start().hasLabel(predicate);
     }
 
+    /**
+     * @see GraphTraversal#hasLabel(Traversal)
+     */
+    public static <A> GraphTraversal<A, A> hasLabel(final Traversal<?, ?> 
traversal) {
+        return __.<A>start().hasLabel(traversal);
+    }
+
     /**
      * @see GraphTraversal#hasId(Object, Object...)
      */
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 57c02cd13a..fe1b5a8e16 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -386,6 +386,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_VXaddVXxX_idX_rejected", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V(__.AddV((string) "x").Id())}}, 
                {"g_EXaddVXxX_idX_rejected", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.E(__.AddV((string) "x").Id())}}, 
                {"g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Property((ITraversal) 
__.V().Map<object>(__.Drop()).Project<object>("x").By("name"))}}, 
+               {"g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Property((ITraversal) __.AddV((string) 
"temp").Project<object>("k").By("name"))}}, 
                {"g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Has("name", __.V(p["vid1"]).Values<object>("name"))}}, 
                {"g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification", 
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Has("age", P.Gt(__.V(p["vid1"]).Values<object>("age")))}}, 
                {"g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V(p["vid1"]).V(__.Out("knows").Id()).Values<object>("name")}}, 
diff --git a/gremlin-go/driver/cucumber/gremlin.go 
b/gremlin-go/driver/cucumber/gremlin.go
index ee2808eca5..708a0efab3 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -356,6 +356,7 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_VXaddVXxX_idX_rejected": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V(gremlingo.T__.AddV("x").Id())}}, 
     "g_EXaddVXxX_idX_rejected": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.E(gremlingo.T__.AddV("x").Id())}}, 
     "g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().Property(gremlingo.T__.V().Map(gremlingo.T__.Drop()).Project("x").By("name"))}},
 
+    "g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().Property(gremlingo.T__.AddV("temp").Project("k").By("name"))}}, 
     "g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Has("name", 
gremlingo.T__.V(p["vid1"]).Values("name"))}}, 
     "g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Has("age", 
gremlingo.P.Gt(gremlingo.T__.V(p["vid1"]).Values("age")))}}, 
     "g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).V(gremlingo.T__.Out("knows").Id()).Values("name")}}, 
diff --git a/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js 
b/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js
index f34f594bf1..216589eff4 100644
--- a/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-js/gremlin-javascript/test/cucumber/gremlin.js
@@ -387,6 +387,7 @@ const gremlins = {
     g_VXaddVXxX_idX_rejected: [function({g}) { return g.V(__.addV("x").id()) 
}], 
     g_EXaddVXxX_idX_rejected: [function({g}) { return g.E(__.addV("x").id()) 
}], 
     g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected: [function({g}) { 
return g.V().property(__.V().map(__.drop()).project("x").by("name")) }], 
+    g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected: [function({g}) { 
return g.V().property(__.addV("temp").project("k").by("name")) }], 
     g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification: [function({g, 
vid1}) { return g.V().has("name", __.V(vid1).values("name")) }], 
     g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification: [function({g, 
vid1}) { return g.V().has("age", P.gt(__.V(vid1).values("age"))) }], 
     g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification: [function({g, 
vid1}) { return g.V(vid1).V(__.out("knows").id()).values("name") }], 
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 
b/gremlin-language/src/main/antlr4/Gremlin.g4
index 822cb59481..17dfbaec11 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -573,6 +573,7 @@ traversalMethod_hasKey
 traversalMethod_hasLabel
     : K_HASLABEL LPAREN traversalPredicate RPAREN #traversalMethod_hasLabel_P
     | K_HASLABEL LPAREN stringNullableArgument (COMMA 
stringNullableArgumentVarargs)? RPAREN #traversalMethod_hasLabel_String_String
+    | K_HASLABEL LPAREN nestedTraversal RPAREN 
#traversalMethod_hasLabel_Traversal
     ;
 
 traversalMethod_hasNot
diff --git a/gremlin-python/src/main/python/tests/feature/gremlin.py 
b/gremlin-python/src/main/python/tests/feature/gremlin.py
index 00c93cd082..7e43e4c884 100644
--- a/gremlin-python/src/main/python/tests/feature/gremlin.py
+++ b/gremlin-python/src/main/python/tests/feature/gremlin.py
@@ -361,6 +361,7 @@ world.gremlins = {
     'g_VXaddVXxX_idX_rejected': [(lambda g:g.V(__.add_v('x').id_()))], 
     'g_EXaddVXxX_idX_rejected': [(lambda g:g.E(__.add_v('x').id_()))], 
     'g_V_propertyXV_mapXdropX_projectXxX_byXnameXX_rejected': [(lambda 
g:g.V().property(__.V().map(__.drop()).project('x').by('name')))], 
+    'g_V_propertyXaddVXtempX_projectXkX_byXnameXX_rejected': [(lambda 
g:g.V().property(__.add_v('temp').project('k').by('name')))], 
     'g_V_hasXname_VXvid1X_valuesXnameXX_passes_verification': [(lambda g, 
vid1=None:g.V().has('name', __.V(vid1).values('name')))], 
     'g_V_hasXage_gtXVXvid1X_valuesXageXXX_passes_verification': [(lambda g, 
vid1=None:g.V().has('age', P.gt(__.V(vid1).values('age'))))], 
     'g_V_VXoutXknowsX_idX_valuesXnameX_passes_verification': [(lambda g, 
vid1=None:g.V(vid1).V(__.out('knows').id_()).values('name'))], 

Reply via email to