You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2026/04/27 15:21:19 UTC
(groovy) branch master updated: Add missing Javadoc for groovy-ginq,groovy-swing,etc.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 5a41b8f854 Add missing Javadoc for groovy-ginq,groovy-swing,etc.
5a41b8f854 is described below
commit 5a41b8f854511d96ed22c3ab3f52761e3cec8eeb
Author: Daniel Sun <su...@apache.org>
AuthorDate: Tue Apr 28 00:20:45 2026 +0900
Add missing Javadoc for groovy-ginq,groovy-swing,etc.
---
.../asciidoctor/DocLinkExtensionRegistry.java | 5 +
.../groovy/asciidoctor/DocLinkMacroProcessor.java | 8 ++
.../src/main/java/groovy/ant/AntBuilder.java | 5 +-
.../main/java/org/codehaus/groovy/ant/Groovy.java | 5 +-
.../ast/builder/AstBuilderTransformation.java | 9 +-
.../console/ui/AstNodeToScriptAdapter.groovy | 59 +++++++++
.../console/ui/ScriptToTreeNodeAdapter.groovy | 55 ++++++++
.../apache/groovy/docgenerator/GDKDocTool.groovy | 17 +++
.../groovy/docgenerator/MockSourceGenerator.groovy | 16 +++
.../docgenerator/PrimitiveNameRewriter.groovy | 6 +
.../apache/groovy/ginq/GinqGroovyMethods.groovy | 10 ++
.../apache/groovy/ginq/InvalidOptionException.java | 5 +
.../apache/groovy/ginq/dsl/GinqAstBaseVisitor.java | 78 +++++++++++
.../org/apache/groovy/ginq/dsl/GinqAstBuilder.java | 53 ++++++++
.../apache/groovy/ginq/dsl/GinqAstOptimizer.groovy | 6 +
.../org/apache/groovy/ginq/dsl/GinqAstVisitor.java | 88 +++++++++++++
.../apache/groovy/ginq/dsl/GinqSyntaxError.java | 23 ++++
.../groovy/ginq/dsl/SyntaxErrorReportable.java | 10 ++
.../dsl/expression/AbstractGinqExpression.java | 18 +++
.../ginq/dsl/expression/DataSourceExpression.java | 25 ++++
.../ginq/dsl/expression/DataSourceHolder.java | 10 ++
.../ginq/dsl/expression/FilterExpression.java | 16 +++
.../groovy/ginq/dsl/expression/FromExpression.java | 33 +++++
.../groovy/ginq/dsl/expression/GinqExpression.java | 92 +++++++++++++
.../ginq/dsl/expression/GroupExpression.java | 47 +++++++
.../ginq/dsl/expression/HavingExpression.java | 22 ++++
.../groovy/ginq/dsl/expression/JoinExpression.java | 90 +++++++++++++
.../ginq/dsl/expression/LimitExpression.java | 27 ++++
.../groovy/ginq/dsl/expression/OnExpression.java | 22 ++++
.../ginq/dsl/expression/OrderExpression.java | 27 ++++
.../ginq/dsl/expression/ProcessExpression.java | 10 ++
.../ginq/dsl/expression/SelectExpression.java | 27 ++++
.../dsl/expression/SetOperationExpression.java | 39 ++++++
.../ginq/dsl/expression/ShutdownExpression.java | 33 +++++
.../ginq/dsl/expression/WhereExpression.java | 22 ++++
.../ginq/provider/collection/GinqAstWalker.groovy | 83 ++++++++++++
.../collection/runtime/ConcurrentObjectHolder.java | 10 ++
.../provider/collection/runtime/GroupImpl.java | 5 +
.../collection/runtime/GroupResultImpl.java | 17 +++
.../provider/collection/runtime/NamedRecord.groovy | 35 +++++
.../provider/collection/runtime/NamedTuple.groovy | 34 +++++
.../ginq/provider/collection/runtime/Null.groovy | 74 +++++++++++
.../provider/collection/runtime/PartitionImpl.java | 5 +
.../provider/collection/runtime/Queryable.java | 40 ++++++
.../collection/runtime/QueryableCollection.java | 102 +++++++++++++++
.../collection/runtime/QueryableHelper.groovy | 42 ++++++
.../collection/runtime/SourceRecord.groovy | 20 ++-
.../collection/runtime/TooManyValuesException.java | 5 +
.../collection/runtime/WindowDefinitionImpl.java | 87 ++++++++++++-
.../provider/collection/runtime/WindowImpl.java | 67 ++++++++++
.../ginq/transform/GinqASTTransformation.java | 6 +
.../main/groovy/groovy/grape/ivy/GrapeIvy.groovy | 143 +++++++++++++++++++++
.../grape/ivy/PlatformLoggingMessageLogger.java | 23 ++++
.../groovy/groovy/grape/maven/GrapeMaven.groovy | 130 +++++++++++++++++++
.../codehaus/groovy/tools/groovydoc/Main.groovy | 5 +
.../tools/groovydoc/GroovyDocTemplateEngine.java | 35 +++++
.../groovy/tools/groovydoc/GroovyDocTool.java | 3 +
.../groovy/tools/groovydoc/TagRenderer.java | 12 ++
.../groovy/groovysh/jline/GroovyCommands.groovy | 110 ++++++++++++++++
.../groovy/groovysh/jline/GroovyPosixCommands.java | 32 +++++
.../groovy/groovysh/jline/SystemRegistryImpl.java | 21 +++
.../src/main/java/groovy/http/Header.java | 11 ++
.../src/main/java/groovy/http/Headers.java | 5 +
.../groovy/jmx/builder/JmxBuilderModelMBean.java | 11 ++
.../java/groovy/jmx/builder/JmxEventEmitter.java | 5 +
.../groovy/jsr223/GroovyScriptEngineImpl.java | 44 ++++++-
.../codehaus/groovy/macro/matcher/ASTFinder.java | 63 +++++++++
.../groovy/macro/matcher/ASTMatcher.groovy | 45 +++++++
.../macro/matcher/ContextualClassCodeVisitor.java | 73 +++++++++++
.../groovy/macro/matcher/MatcherUtils.java | 3 +
.../codehaus/groovy/macro/matcher/TreeContext.java | 20 +++
.../internal/MatchingConstraintsBuilder.groovy | 2 +
.../groovy/macro/methods/MacroGroovyMethods.java | 15 +++
.../groovy/macro/runtime/MacroBuilder.java | 12 ++
.../codehaus/groovy/macro/runtime/MacroStub.java | 1 +
.../transform/MacroCallTransformingVisitor.java | 5 +
.../macro/transform/MacroClassTransformation.java | 16 +++
.../src/main/java/groovy/sql/CallResultSet.java | 12 ++
.../groovy-sql/src/main/java/groovy/sql/Sql.java | 14 ++
.../swing/binding/AbstractButtonProperties.java | 16 +++
.../swing/binding/AbstractSyntheticBinding.java | 19 +++
.../groovy/swing/binding/JComboBoxProperties.java | 68 ++++++++++
.../groovy/swing/binding/JComponentProperties.java | 11 ++
.../groovy/swing/binding/JScrollBarProperties.java | 21 +++
.../groovy/swing/binding/JSliderProperties.java | 16 +++
.../groovy/swing/binding/JSpinnerProperties.java | 16 +++
.../groovy/swing/binding/JTableProperties.java | 32 +++++
.../swing/binding/JTextComponentProperties.java | 26 ++++
.../groovy/groovy/swing/impl/ClosureRenderer.java | 33 +++++
.../groovy/groovy/swing/impl/DefaultAction.java | 5 +
.../groovy/swing/impl/ListWrapperListModel.java | 11 ++
.../main/java/groovy/swing/model/ClosureModel.java | 5 +
.../groovy/swing/model/DefaultTableColumn.java | 5 +
.../java/groovy/swing/model/DefaultTableModel.java | 56 +++++++-
.../java/groovy/swing/model/PropertyModel.java | 5 +
.../main/java/groovy/swing/model/ValueHolder.java | 15 +++
.../src/main/java/groovy/swing/table/TableMap.java | 43 +++++++
.../main/java/groovy/swing/table/TableSorter.java | 24 ++++
.../groovy/swing/binding/AbstractFullBinding.java | 6 +
.../groovy/swing/binding/AggregateBinding.java | 15 +++
.../org/apache/groovy/swing/binding/BindPath.java | 6 +
.../apache/groovy/swing/binding/BindingProxy.java | 15 +++
.../groovy/swing/binding/ClosureSourceBinding.java | 5 +
.../swing/binding/MutualPropertyBinding.java | 67 +++++++++-
.../groovy/swing/binding/PropertyBinding.java | 44 ++++++-
.../binding/PropertyChangeProxyTargetBinding.java | 5 +
.../swing/binding/PropertyPathFullBinding.java | 14 ++
.../swing/binding/SwingTimerTriggerBinding.java | 14 ++
.../groovy/groovy/text/markup/IncludeType.java | 13 +-
.../org/apache/groovy/bench/Ackermann.groovy | 9 ++
.../org/apache/groovy/bench/AckermannBench.java | 11 ++
.../jmh/groovy/org/apache/groovy/bench/Ary.groovy | 13 ++
.../groovy/org/apache/groovy/bench/AryBench.java | 15 +++
.../jmh/groovy/org/apache/groovy/bench/Fibo.groovy | 8 ++
.../groovy/org/apache/groovy/bench/FiboBench.java | 11 ++
.../apache/groovy/bench/GeneratedHashCode.groovy | 5 +
.../groovy/bench/GeneratedHashCodeBench.java | 7 +
.../apache/groovy/bench/NonCapturingLambda.groovy | 23 ++++
.../groovy/bench/NonCapturingLambdaBench.java | 16 +++
.../groovy/bench/StaticMethodCallIndy.groovy | 112 ++++++++++++++++
.../groovy/bench/StaticMethodCallIndyBench.java | 51 ++++++++
.../bench/StaticMethodCallIndyColdBench.java | 19 +++
.../apache/groovy/bench/dispatch/Callsite.groovy | 13 ++
.../groovy/bench/dispatch/CallsiteBench.java | 87 +++++++++++++
.../org/apache/groovy/perf/ClosureBench.groovy | 8 ++
.../org/apache/groovy/perf/GStringBench.groovy | 1 +
.../org/apache/groovy/perf/GroovyIdiomBench.groovy | 23 +++-
.../org/apache/groovy/perf/LoopsBench.groovy | 6 +
.../org/apache/groovy/perf/MetaclassBench.groovy | 39 ++++++
.../groovy/perf/MethodInvocationBench.groovy | 52 +++++++-
.../org/apache/groovy/perf/OperatorBench.groovy | 1 +
.../apache/groovy/perf/PropertyAccessBench.groovy | 14 ++
.../apache/groovy/perf/RunnerRegistryBench.java | 18 +++
.../perf/grails/CallSiteInvalidationBench.groovy | 26 ++++
.../apache/groovy/perf/grails/CategoryBench.groovy | 24 +++-
.../groovy/perf/grails/DynamicDispatchBench.groovy | 34 ++++-
.../perf/grails/GrailsLikePatternsBench.groovy | 77 +++++++++--
.../groovy/perf/grails/GrailsWorkloadBench.groovy | 64 ++++++++-
.../groovy/perf/grails/MetaclassChangeBench.groovy | 22 +++-
.../perf/grails/MetaclassVariationBench.groovy | 46 ++++++-
140 files changed, 3961 insertions(+), 46 deletions(-)
diff --git a/subprojects/asciidoc-extensions/src/main/java/org/apache/groovy/asciidoctor/DocLinkExtensionRegistry.java b/subprojects/asciidoc-extensions/src/main/java/org/apache/groovy/asciidoctor/DocLinkExtensionRegistry.java
index a679e7f2fd..c1502b9a1f 100644
--- a/subprojects/asciidoc-extensions/src/main/java/org/apache/groovy/asciidoctor/DocLinkExtensionRegistry.java
+++ b/subprojects/asciidoc-extensions/src/main/java/org/apache/groovy/asciidoctor/DocLinkExtensionRegistry.java
@@ -26,6 +26,11 @@ import org.asciidoctor.jruby.extension.spi.ExtensionRegistry;
* (jdk, gjdk, gapi, gapid) when this JAR is on the AsciidoctorJ classpath.
*/
public class DocLinkExtensionRegistry implements ExtensionRegistry {
+ /**
+ * Registers Groovy's documentation link macros with the supplied Asciidoctor instance.
+ *
+ * @param asciidoctor the Asciidoctor instance to extend
+ */
@Override
public void register(Asciidoctor asciidoctor) {
asciidoctor.javaExtensionRegistry()
diff --git a/subprojects/asciidoc-extensions/src/main/java/org/apache/groovy/asciidoctor/DocLinkMacroProcessor.java b/subprojects/asciidoc-extensions/src/main/java/org/apache/groovy/asciidoctor/DocLinkMacroProcessor.java
index 9cf388132c..c0972ef874 100644
--- a/subprojects/asciidoc-extensions/src/main/java/org/apache/groovy/asciidoctor/DocLinkMacroProcessor.java
+++ b/subprojects/asciidoc-extensions/src/main/java/org/apache/groovy/asciidoctor/DocLinkMacroProcessor.java
@@ -48,6 +48,14 @@ public class DocLinkMacroProcessor extends InlineMacroProcessor {
this.directPath = directPath;
}
+ /**
+ * Creates a link phrase for the supplied documentation target.
+ *
+ * @param parent the parent node receiving the rendered phrase
+ * @param target the macro target containing the class name and optional anchor
+ * @param attributes the macro attributes, including optional display text
+ * @return the rendered documentation link phrase
+ */
@Override
public PhraseNode process(StructuralNode parent, String target, Map<String, Object> attributes) {
String baseUrl = (String) parent.getDocument().getAttribute(baseUrlAttribute);
diff --git a/subprojects/groovy-ant/src/main/java/groovy/ant/AntBuilder.java b/subprojects/groovy-ant/src/main/java/groovy/ant/AntBuilder.java
index 09541b9ba4..6ec36eb308 100644
--- a/subprojects/groovy-ant/src/main/java/groovy/ant/AntBuilder.java
+++ b/subprojects/groovy-ant/src/main/java/groovy/ant/AntBuilder.java
@@ -77,7 +77,10 @@ public class AntBuilder extends BuilderSupport {
private final Target implicitTarget;
private Target definingTarget;
private Object lastCompletedNode;
- // true when inside a task so special ant.target handling occurs just at top level
+ /**
+ * Tracks whether builder execution is currently inside a task so top-level {@code ant.target}
+ * handling can be applied correctly.
+ */
boolean insideTask;
private boolean saveStreams = true;
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
index d0ed77e980..ceeecf8e1a 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
@@ -731,7 +731,10 @@ public class Groovy extends Java {
}
}
- // package-private for testing
+ /**
+ * Copies Ant project properties into the forked process unless they were already supplied as
+ * explicit system properties.
+ */
void passParentAntProperties() {
Set<String> alreadySet = new HashSet<>();
for (Environment.Variable v : super.getSysProperties().getVariablesVector()) {
diff --git a/subprojects/groovy-astbuilder/src/main/java/org/apache/groovy/ast/builder/AstBuilderTransformation.java b/subprojects/groovy-astbuilder/src/main/java/org/apache/groovy/ast/builder/AstBuilderTransformation.java
index 46bd5a92db..22c33b5915 100644
--- a/subprojects/groovy-astbuilder/src/main/java/org/apache/groovy/ast/builder/AstBuilderTransformation.java
+++ b/subprojects/groovy-astbuilder/src/main/java/org/apache/groovy/ast/builder/AstBuilderTransformation.java
@@ -51,6 +51,14 @@ import java.util.List;
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class AstBuilderTransformation extends MethodCallTransformation {
+ /**
+ * Creates the visitor that rewrites {@code AstBuilder} closure invocations into string-based
+ * builder calls.
+ *
+ * @param nodes the AST nodes being transformed
+ * @param sourceUnit the source unit currently under compilation
+ * @return the visitor that performs the rewrite
+ */
@Override
protected GroovyCodeVisitor getTransformer(ASTNode[] nodes, SourceUnit sourceUnit) {
// todo : are there other import types that can be specified?
@@ -180,4 +188,3 @@ public class AstBuilderTransformation extends MethodCallTransformation {
}
}
-
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
index 67677329c9..94752b740b 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
@@ -370,6 +370,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a class or interface declaration. */
@Override
void visitClass(ClassNode node) {
@@ -459,6 +460,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a constructor declaration. */
@Override
void visitConstructor(ConstructorNode node) {
visitMethod(node)
@@ -486,6 +488,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a method or initializer declaration. */
@Override
void visitMethod(MethodNode node) {
node?.annotations?.each {
@@ -536,6 +539,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print mods
}
+ /** Renders a field declaration. */
@Override
void visitField(FieldNode node) {
node?.annotations?.each {
@@ -566,6 +570,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders an annotation and its members. */
void visitAnnotationNode(AnnotationNode node) {
print '@' + node?.classNode?.name
if (node?.members) {
@@ -585,11 +590,13 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
+ /** Skips property rendering because fields already emit the corresponding output. */
@Override
void visitProperty(PropertyNode node) {
// is a FieldNode, avoid double dispatch
}
+ /** Renders a block statement. */
@Override
void visitBlockStatement(BlockStatement block) {
if (printStatementLabels(block)) {
@@ -614,6 +621,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a for-loop statement. */
@Override
void visitForLoop(ForStatement statement) {
printStatementLabels(statement)
@@ -636,6 +644,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders an if/else statement. */
@Override
void visitIfElse(IfStatement ifElse) {
printStatementLabels(ifElse)
@@ -659,11 +668,13 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a standalone expression statement. */
@Override
void visitExpressionStatement(ExpressionStatement statement) {
statement.expression.visit this
}
+ /** Renders a return statement. */
@Override
void visitReturnStatement(ReturnStatement statement) {
printLineBreak()
@@ -672,6 +683,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a switch statement. */
@Override
void visitSwitch(SwitchStatement statement) {
printStatementLabels(statement)
@@ -693,6 +705,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a switch case. */
@Override
void visitCaseStatement(CaseStatement statement) {
print 'case '
@@ -704,6 +717,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a break statement. */
@Override
void visitBreakStatement(BreakStatement statement) {
print 'break'
@@ -713,6 +727,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a continue statement. */
@Override
void visitContinueStatement(ContinueStatement statement) {
print 'continue'
@@ -722,6 +737,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a method call expression. */
@Override
void visitMethodCallExpression(MethodCallExpression expression) {
printExpression expression.objectExpression
@@ -741,6 +757,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
expression.arguments.visit(this)
}
+ /** Renders a static method call expression. */
@Override
void visitStaticMethodCallExpression(StaticMethodCallExpression expression) {
boolean parens = expression?.arguments instanceof MethodCallExpression
@@ -751,6 +768,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
if (parens) print ')'
}
+ /** Renders a constructor invocation expression. */
@Override
void visitConstructorCallExpression(ConstructorCallExpression expression) {
if (expression?.isSuperCall()) {
@@ -764,6 +782,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
expression?.arguments?.visit this
}
+ /** Renders a binary or assignment expression. */
@Override
void visitBinaryExpression(BinaryExpression expression) {
if (expression !instanceof DeclarationExpression && expression?.leftExpression instanceof VariableExpression) {
@@ -782,6 +801,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a postfix expression. */
@Override
void visitPostfixExpression(PostfixExpression expression) {
if (expression?.expression instanceof VariableExpression) {
@@ -794,6 +814,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print expression?.operation?.text
}
+ /** Renders a prefix expression. */
@Override
void visitPrefixExpression(PrefixExpression expression) {
print expression?.operation?.text
@@ -806,6 +827,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a closure expression. */
@Override
void visitClosureExpression(ClosureExpression expression) {
print '{ '
@@ -820,6 +842,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print '}'
}
+ /** Renders a lambda expression. */
@Override
void visitLambdaExpression(LambdaExpression expression) {
print '('
@@ -834,6 +857,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print '}'
}
+ /** Renders a tuple expression. */
@Override
void visitTupleExpression(TupleExpression expression) {
print '('
@@ -841,6 +865,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print ')'
}
+ /** Renders a range expression. */
@Override
void visitRangeExpression(RangeExpression expression) {
print '('
@@ -850,6 +875,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print ')'
}
+ /** Renders a property access expression. */
@Override
void visitPropertyExpression(PropertyExpression expression) {
printExpression expression?.objectExpression
@@ -866,16 +892,19 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders an attribute access expression. */
@Override
void visitAttributeExpression(AttributeExpression attributeExpression) {
visitPropertyExpression attributeExpression
}
+ /** Renders a field reference expression. */
@Override
void visitFieldExpression(FieldExpression expression) {
print expression?.field?.name
}
+ /** Renders a constant expression. */
@Override
void visitConstantExpression(ConstantExpression expression, boolean unwrapQuotes = false) {
if (expression.value instanceof String && !unwrapQuotes) {
@@ -887,11 +916,13 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a class literal expression. */
@Override
void visitClassExpression(ClassExpression expression) {
print expression.text
}
+ /** Renders a variable reference. */
@Override
void visitVariableExpression(VariableExpression expression, boolean spacePad = true) {
if (spacePad) {
@@ -901,6 +932,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a declaration expression. */
@Override
void visitDeclarationExpression(DeclarationExpression expression) {
if (!expression.isMultipleAssignmentDeclaration()) {
@@ -921,11 +953,13 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
expression.rightExpression.visit this
}
+ /** Renders a GString expression. */
@Override
void visitGStringExpression(GStringExpression expression) {
print '"' + expression.text + '"'
}
+ /** Renders a spread expression. */
@Override
void visitSpreadExpression(SpreadExpression expression) {
print '*'
@@ -946,21 +980,25 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a logical negation expression. */
@Override
void visitNotExpression(NotExpression expression) {
printUnaryExpression('!', expression)
}
+ /** Renders a unary minus expression. */
@Override
void visitUnaryMinusExpression(UnaryMinusExpression expression) {
printUnaryExpression('-', expression)
}
+ /** Renders a unary plus expression. */
@Override
void visitUnaryPlusExpression(UnaryPlusExpression expression) {
printUnaryExpression('+', expression)
}
+ /** Renders a cast or coercion expression. */
@Override
void visitCastExpression(CastExpression expression) {
print '('
@@ -1001,12 +1039,14 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
visitGenerics classNode?.genericsTypes
}
+ /** Emits a placeholder for a bytecode expression. */
@Override
void visitBytecodeExpression(BytecodeExpression expression) {
print '/*BytecodeExpression*/'
printLineBreak()
}
+ /** Renders a map expression. */
@Override
void visitMapExpression(MapExpression expression) {
print '['
@@ -1018,6 +1058,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print ']'
}
+ /** Renders a map entry expression. */
@Override
void visitMapEntryExpression(MapEntryExpression expression) {
if (expression?.keyExpression instanceof SpreadMapExpression) {
@@ -1029,6 +1070,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
expression?.valueExpression?.visit this
}
+ /** Renders a list expression. */
@Override
void visitListExpression(ListExpression expression) {
print '['
@@ -1036,6 +1078,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print ']'
}
+ /** Renders a try/catch/finally statement. */
@Override
void visitTryCatchFinally(TryCatchStatement statement) {
printStatementLabels(statement)
@@ -1061,6 +1104,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a throw statement. */
@Override
void visitThrowStatement(ThrowStatement statement) {
print 'throw '
@@ -1068,6 +1112,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a synchronized statement. */
@Override
void visitSynchronizedStatement(SynchronizedStatement statement) {
printStatementLabels(statement)
@@ -1081,6 +1126,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print '}'
}
+ /** Renders a ternary expression. */
@Override
void visitTernaryExpression(TernaryExpression expression) {
expression?.booleanExpression?.visit this
@@ -1090,16 +1136,19 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
expression?.falseExpression?.visit this
}
+ /** Renders an Elvis expression. */
@Override
void visitShortTernaryExpression(ElvisOperatorExpression expression) {
visitTernaryExpression expression
}
+ /** Renders a boolean expression. */
@Override
void visitBooleanExpression(BooleanExpression expression) {
printExpression expression?.expression
}
+ /** Renders a while-loop statement. */
@Override
void visitWhileLoop(WhileStatement statement) {
printStatementLabels(statement)
@@ -1115,6 +1164,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a do/while-loop statement. */
@Override
void visitDoWhileLoop(DoWhileStatement statement) {
printStatementLabels(statement)
@@ -1129,6 +1179,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a catch clause. */
@Override
void visitCatchStatement(CatchStatement statement) {
print 'catch ('
@@ -1142,6 +1193,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
printLineBreak()
}
+ /** Renders a bitwise negation expression. */
@Override
void visitBitwiseNegationExpression(BitwiseNegationExpression expression) {
print '~('
@@ -1149,6 +1201,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print ') '
}
+ /** Renders an assert statement. */
@Override
void visitAssertStatement(AssertStatement statement) {
print 'assert '
@@ -1165,11 +1218,13 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
visitArgumentlistExpression(expression)
}
+ /** Renders an argument list expression. */
@Override
void visitArgumentlistExpression(ArgumentListExpression expression) {
visitTupleExpression expression
}
+ /** Renders a closure list expression. */
@Override
void visitClosureListExpression(ClosureListExpression expression) {
int i = 0
@@ -1184,6 +1239,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
}
}
+ /** Renders a method pointer expression. */
@Override
void visitMethodPointerExpression(MethodPointerExpression expression) {
expression?.expression?.visit this
@@ -1191,6 +1247,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
expression?.methodName?.visit this
}
+ /** Renders a method reference expression. */
@Override
void visitMethodReferenceExpression(MethodReferenceExpression expression) {
expression?.expression?.visit this
@@ -1198,6 +1255,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
expression?.methodName?.visit this
}
+ /** Renders an array expression. */
@Override
void visitArrayExpression(ArrayExpression expression) {
print 'new '
@@ -1207,6 +1265,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
print ']'
}
+ /** Renders a spread-map expression. */
@Override
void visitSpreadMapExpression(SpreadMapExpression expression) {
print '*:'
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ScriptToTreeNodeAdapter.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ScriptToTreeNodeAdapter.groovy
index e0e406ab77..1238556507 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ScriptToTreeNodeAdapter.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ScriptToTreeNodeAdapter.groovy
@@ -571,136 +571,163 @@ class TreeNodeBuildingVisitor extends CodeVisitorSupport {
}
}
+ /** Adds a block statement node to the tree. */
@Override
void visitBlockStatement(BlockStatement node) {
addNode(node, BlockStatement, { super.visitBlockStatement(it) })
}
+ /** Adds a for-loop node to the tree. */
@Override
void visitForLoop(ForStatement node) {
addNode(node, ForStatement, { super.visitForLoop(it) })
}
+ /** Adds a while-loop node to the tree. */
@Override
void visitWhileLoop(WhileStatement node) {
addNode(node, WhileStatement, { super.visitWhileLoop(it) })
}
+ /** Adds a do/while-loop node to the tree. */
@Override
void visitDoWhileLoop(DoWhileStatement node) {
addNode(node, DoWhileStatement, { super.visitDoWhileLoop(it) })
}
+ /** Adds an if/else node to the tree. */
@Override
void visitIfElse(IfStatement node) {
addNode(node, IfStatement, { super.visitIfElse(it) })
}
+ /** Adds an expression statement node to the tree. */
@Override
void visitExpressionStatement(ExpressionStatement node) {
addNode(node, ExpressionStatement, { super.visitExpressionStatement(it) })
}
+ /** Adds a return statement node to the tree. */
@Override
void visitReturnStatement(ReturnStatement node) {
addNode(node, ReturnStatement, { super.visitReturnStatement(it) })
}
+ /** Adds an assert statement node to the tree. */
@Override
void visitAssertStatement(AssertStatement node) {
addNode(node, AssertStatement, { super.visitAssertStatement(it) })
}
+ /** Adds a try/catch/finally node to the tree. */
@Override
void visitTryCatchFinally(TryCatchStatement node) {
addNode(node, TryCatchStatement, { super.visitTryCatchFinally(it) })
}
+ /** Adds an empty statement node to the tree. */
@Override
void visitEmptyStatement(EmptyStatement node) {
addNode(node, EmptyStatement, { super.visitEmptyStatement(it) })
}
+ /** Adds a switch node to the tree. */
@Override
void visitSwitch(SwitchStatement node) {
addNode(node, SwitchStatement, { super.visitSwitch(it) })
}
+ /** Adds a case statement node to the tree. */
@Override
void visitCaseStatement(CaseStatement node) {
addNode(node, CaseStatement, { super.visitCaseStatement(it) })
}
+ /** Adds a break statement node to the tree. */
@Override
void visitBreakStatement(BreakStatement node) {
addNode(node, BreakStatement, { super.visitBreakStatement(it) })
}
+ /** Adds a continue statement node to the tree. */
@Override
void visitContinueStatement(ContinueStatement node) {
addNode(node, ContinueStatement, { super.visitContinueStatement(it) })
}
+ /** Adds a synchronized statement node to the tree. */
@Override
void visitSynchronizedStatement(SynchronizedStatement node) {
addNode(node, SynchronizedStatement, { super.visitSynchronizedStatement(it) })
}
+ /** Adds a throw statement node to the tree. */
@Override
void visitThrowStatement(ThrowStatement node) {
addNode(node, ThrowStatement, { super.visitThrowStatement(it) })
}
+ /** Adds a method call expression node to the tree. */
@Override
void visitMethodCallExpression(MethodCallExpression node) {
addNode(node, MethodCallExpression, { super.visitMethodCallExpression(it) })
}
+ /** Adds a static method call node to the tree. */
@Override
void visitStaticMethodCallExpression(StaticMethodCallExpression node) {
addNode(node, StaticMethodCallExpression, { super.visitStaticMethodCallExpression(it) })
}
+ /** Adds a constructor call node to the tree. */
@Override
void visitConstructorCallExpression(ConstructorCallExpression node) {
addNode(node, ConstructorCallExpression, { super.visitConstructorCallExpression(it) })
}
+ /** Adds a binary expression node to the tree. */
@Override
void visitBinaryExpression(BinaryExpression node) {
addNode(node, BinaryExpression, { super.visitBinaryExpression(it) })
}
+ /** Adds a ternary expression node to the tree. */
@Override
void visitTernaryExpression(TernaryExpression node) {
addNode(node, TernaryExpression, { super.visitTernaryExpression(it) })
}
+ /** Adds an Elvis expression node to the tree. */
@Override
void visitShortTernaryExpression(ElvisOperatorExpression node) {
addNode(node, ElvisOperatorExpression, { super.visitShortTernaryExpression(it) })
}
+ /** Adds a postfix expression node to the tree. */
@Override
void visitPostfixExpression(PostfixExpression node) {
addNode(node, PostfixExpression, { super.visitPostfixExpression(it) })
}
+ /** Adds a prefix expression node to the tree. */
@Override
void visitPrefixExpression(PrefixExpression node) {
addNode(node, PrefixExpression, { super.visitPrefixExpression(it) })
}
+ /** Adds a boolean expression node to the tree. */
@Override
void visitBooleanExpression(BooleanExpression node) {
addNode(node, BooleanExpression, { super.visitBooleanExpression(it) })
}
+ /** Adds a logical negation expression node to the tree. */
@Override
void visitNotExpression(NotExpression node) {
addNode(node, NotExpression, { super.visitNotExpression(it) })
}
+ /** Adds a closure expression node to the tree. */
@Override
void visitClosureExpression(ClosureExpression node) {
addNode(node, ClosureExpression, {
@@ -709,6 +736,7 @@ class TreeNodeBuildingVisitor extends CodeVisitorSupport {
})
}
+ /** Adds a lambda expression node to the tree. */
@Override
void visitLambdaExpression(LambdaExpression node) {
addNode(node, LambdaExpression, {
@@ -727,86 +755,103 @@ class TreeNodeBuildingVisitor extends CodeVisitorSupport {
addNode(node, Parameter, { })
}
+ /** Adds a tuple expression node to the tree. */
@Override
void visitTupleExpression(TupleExpression node) {
addNode(node, TupleExpression, { super.visitTupleExpression(it) })
}
+ /** Adds a list expression node to the tree. */
@Override
void visitListExpression(ListExpression node) {
addNode(node, ListExpression, { super.visitListExpression(it) })
}
+ /** Adds an array expression node to the tree. */
@Override
void visitArrayExpression(ArrayExpression node) {
addNode(node, ArrayExpression, { super.visitArrayExpression(it) })
}
+ /** Adds a map expression node to the tree. */
@Override
void visitMapExpression(MapExpression node) {
addNode(node, MapExpression, { super.visitMapExpression(it) })
}
+ /** Adds a map entry expression node to the tree. */
@Override
void visitMapEntryExpression(MapEntryExpression node) {
addNode(node, MapEntryExpression, { super.visitMapEntryExpression(it) })
}
+ /** Adds a range expression node to the tree. */
@Override
void visitRangeExpression(RangeExpression node) {
addNode(node, RangeExpression, { super.visitRangeExpression(it) })
}
+ /** Adds a spread expression node to the tree. */
@Override
void visitSpreadExpression(SpreadExpression node) {
addNode(node, SpreadExpression, { super.visitSpreadExpression(it) })
}
+ /** Adds a spread-map expression node to the tree. */
@Override
void visitSpreadMapExpression(SpreadMapExpression node) {
addNode(node, SpreadMapExpression, { super.visitSpreadMapExpression(it) })
}
+ /** Adds a method pointer expression node to the tree. */
@Override
void visitMethodPointerExpression(MethodPointerExpression node) {
addNode(node, MethodPointerExpression, { super.visitMethodPointerExpression(it) })
}
+ /** Adds a method reference expression node to the tree. */
@Override
void visitMethodReferenceExpression(MethodReferenceExpression node) {
addNode(node, MethodReferenceExpression, { super.visitMethodReferenceExpression(it) })
}
+ /** Adds a unary minus expression node to the tree. */
@Override
void visitUnaryMinusExpression(UnaryMinusExpression node) {
addNode(node, UnaryMinusExpression, { super.visitUnaryMinusExpression(it) })
}
+ /** Adds a unary plus expression node to the tree. */
@Override
void visitUnaryPlusExpression(UnaryPlusExpression node) {
addNode(node, UnaryPlusExpression, { super.visitUnaryPlusExpression(it) })
}
+ /** Adds a bitwise negation expression node to the tree. */
@Override
void visitBitwiseNegationExpression(BitwiseNegationExpression node) {
addNode(node, BitwiseNegationExpression, { super.visitBitwiseNegationExpression(it) })
}
+ /** Adds a cast expression node to the tree. */
@Override
void visitCastExpression(CastExpression node) {
addNode(node, CastExpression, { super.visitCastExpression(it) })
}
+ /** Adds a constant expression node to the tree. */
@Override
void visitConstantExpression(ConstantExpression node) {
addNode(node, ConstantExpression, { super.visitConstantExpression(it) })
}
+ /** Adds a class expression node to the tree. */
@Override
void visitClassExpression(ClassExpression node) {
addNode(node, ClassExpression, { super.visitClassExpression(it) })
}
+ /** Adds a variable expression node to the tree. */
@Override
void visitVariableExpression(VariableExpression node) {
addNode(node, VariableExpression, { VariableExpression it ->
@@ -820,31 +865,37 @@ class TreeNodeBuildingVisitor extends CodeVisitorSupport {
})
}
+ /** Adds a declaration expression node to the tree. */
@Override
void visitDeclarationExpression(DeclarationExpression node) {
addNode(node, DeclarationExpression, { super.visitDeclarationExpression(it) })
}
+ /** Adds a property expression node to the tree. */
@Override
void visitPropertyExpression(PropertyExpression node) {
addNode(node, PropertyExpression, { super.visitPropertyExpression(it) })
}
+ /** Adds an attribute expression node to the tree. */
@Override
void visitAttributeExpression(AttributeExpression node) {
addNode(node, AttributeExpression, { super.visitAttributeExpression(it) })
}
+ /** Adds a field expression node to the tree. */
@Override
void visitFieldExpression(FieldExpression node) {
addNode(node, FieldExpression, { super.visitFieldExpression(it) })
}
+ /** Adds a GString expression node to the tree. */
@Override
void visitGStringExpression(GStringExpression node) {
addNode(node, GStringExpression, { super.visitGStringExpression(it) })
}
+ /** Adds a catch clause node to the tree. */
@Override
void visitCatchStatement(CatchStatement node) {
addNode(node, CatchStatement, {
@@ -853,21 +904,25 @@ class TreeNodeBuildingVisitor extends CodeVisitorSupport {
})
}
+ /** Adds an argument list expression node to the tree. */
@Override
void visitArgumentlistExpression(ArgumentListExpression node) {
addNode(node, ArgumentListExpression, { super.visitArgumentlistExpression(it) })
}
+ /** Adds a closure list expression node to the tree. */
@Override
void visitClosureListExpression(ClosureListExpression node) {
addNode(node, ClosureListExpression, { super.visitClosureListExpression(it) })
}
+ /** Adds a bytecode expression node to the tree. */
@Override
void visitBytecodeExpression(BytecodeExpression node) {
addNode(node, BytecodeExpression, { super.visitBytecodeExpression(it) })
}
+ /** Adds each expression from the supplied list to the tree. */
@Override
void visitListOfExpressions(List<? extends Expression> list) {
list.each { Expression node ->
diff --git a/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/GDKDocTool.groovy b/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/GDKDocTool.groovy
index 4a89d73a39..99c1264cfe 100644
--- a/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/GDKDocTool.groovy
+++ b/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/GDKDocTool.groovy
@@ -35,14 +35,26 @@ import org.codehaus.groovy.tools.groovydoc.gstringTemplates.GroovyDocTemplateInf
*/
class GDKDocTool {
+ /** Title used for generated documentation pages. */
String title
+ /** Directory containing the mock source files to document. */
File sourceDir
+ /** Directory where generated documentation is written. */
File outputDir
+ /** External documentation links forwarded to GroovyDoc. */
List<LinkArgument> links = []
+ /** Language hint used when rewriting generated {@code <pre>} blocks. */
String preLanguage = 'groovy'
+ /** Syntax highlighter identifier passed to the documentation templates. */
String syntaxHighlighter = 'prism'
+ /** Theme name passed to the documentation templates. */
String theme = 'auto'
+ /**
+ * Generates Groovy JDK documentation for the configured source tree.
+ *
+ * @return the GroovyDoc error count
+ */
int run() {
if (!sourceDir.directory) {
throw new IllegalStateException("source directory not found: $sourceDir")
@@ -97,6 +109,11 @@ class GDKDocTool {
out
}
+ /**
+ * Runs the documentation generator from the command line.
+ *
+ * @param args command-line arguments
+ */
static void main(String... args) {
def cli = new CliBuilderInternal(usage: 'GDKDocTool [options]', posix: false)
cli.help(longOpt: 'help', 'Print this help')
diff --git a/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/MockSourceGenerator.groovy b/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/MockSourceGenerator.groovy
index 7379bdba2b..0f500caa55 100644
--- a/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/MockSourceGenerator.groovy
+++ b/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/MockSourceGenerator.groovy
@@ -43,7 +43,9 @@ import org.codehaus.groovy.runtime.DefaultGroovyMethods
*/
class MockSourceGenerator {
+ /** Synthetic package used for primitive and primitive-array receiver mocks. */
static final String PRIMITIVES_PKG = 'primitives'
+ /** Primitive base names that require dedicated mock types. */
static final List<String> PRIMITIVE_BASES = [
'int', 'long', 'double', 'float', 'boolean', 'byte', 'short', 'char'
]
@@ -51,6 +53,12 @@ class MockSourceGenerator {
private final List<File> sourceFiles
private final File outputDir
+ /**
+ * Creates a generator for the supplied extension source files.
+ *
+ * @param sourceFiles source files that contribute extension methods
+ * @param outputDir directory where mock sources should be written
+ */
MockSourceGenerator(List<File> sourceFiles, File outputDir) {
this.sourceFiles = sourceFiles
this.outputDir = outputDir
@@ -63,6 +71,9 @@ class MockSourceGenerator {
*/
static final String MANIFEST_FILE = 'mocks.manifest'
+ /**
+ * Generates mock source files for all supported receiver types.
+ */
void generateAll() {
def builder = new JavaProjectBuilder()
sourceFiles.each {
@@ -325,6 +336,11 @@ class MockSourceGenerator {
(fqcn.length() - base.length()) / 2 as int
}
+ /**
+ * Runs the mock-source generator from the command line.
+ *
+ * @param args command-line arguments
+ */
static void main(String... args) {
def cli = new CliBuilderInternal(usage: 'MockSourceGenerator [options] [sourcefiles]', posix: false)
cli.help(longOpt: 'help', 'Print this help')
diff --git a/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/PrimitiveNameRewriter.groovy b/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/PrimitiveNameRewriter.groovy
index 5e902f2ed4..7024657fc8 100644
--- a/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/PrimitiveNameRewriter.groovy
+++ b/subprojects/groovy-docgenerator/src/main/groovy/org/apache/groovy/docgenerator/PrimitiveNameRewriter.groovy
@@ -36,6 +36,12 @@ import java.util.regex.Pattern
*/
class PrimitiveNameRewriter {
+ /**
+ * Rewrites generated GroovyDoc output to use historical Groovy JDK names and locations.
+ *
+ * @param outputDir directory containing generated documentation
+ * @param manifestFile manifest that describes mock-to-display name mappings
+ */
static void rewrite(File outputDir, File manifestFile) {
if (!manifestFile.exists()) return
def renames = []
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/GinqGroovyMethods.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/GinqGroovyMethods.groovy
index 4841fd2588..ca87e54986 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/GinqGroovyMethods.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/GinqGroovyMethods.groovy
@@ -101,6 +101,14 @@ class GinqGroovyMethods {
callX(GQ(ctx, ginqConfigurationMapExpression, ginqClosureExpression), 'toList')
}
+ /**
+ * Transforms parsed GINQ code into the corresponding queryable method calls.
+ *
+ * @param sourceUnit the source unit owning the code
+ * @param ginqConfigurationMapExpression the optional GINQ configuration
+ * @param code the GINQ code block
+ * @return the transformed expression
+ */
static Expression transformGinqCode(SourceUnit sourceUnit, MapExpression ginqConfigurationMapExpression, Statement code) {
GinqAstBuilder ginqAstBuilder = new GinqAstBuilder(sourceUnit)
AbstractGinqExpression ginqExpression = ginqAstBuilder.buildAST(code)
@@ -144,7 +152,9 @@ class GinqGroovyMethods {
private GinqGroovyMethods() {}
+ /** Supported GINQ configuration keys. */
public static final List<String> CONF_LIST = [CONF_PARALLEL, CONF_AST_WALKER, CONF_OPTIMIZE]
+ /** Configuration key enabling parallel execution. */
public static final String CONF_PARALLEL = 'parallel'
private static final String CONF_AST_WALKER = 'astWalker'
private static final String CONF_OPTIMIZE = 'optimize'
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/InvalidOptionException.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/InvalidOptionException.java
index 22e74dfbf0..7fbbbc786f 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/InvalidOptionException.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/InvalidOptionException.java
@@ -30,6 +30,11 @@ import java.io.Serial;
public class InvalidOptionException extends GroovyException {
@Serial private static final long serialVersionUID = -8644282992572200089L;
+ /**
+ * Creates an invalid-option exception with the supplied message.
+ *
+ * @param message the validation failure message
+ */
public InvalidOptionException(String message) {
super(message);
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBaseVisitor.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBaseVisitor.java
index 2cad321b45..7b0a681dc4 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBaseVisitor.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBaseVisitor.java
@@ -39,6 +39,12 @@ import org.codehaus.groovy.ast.CodeVisitorSupport;
* @since 4.0.0
*/
public class GinqAstBaseVisitor extends CodeVisitorSupport implements GinqAstVisitor<Void> {
+ /**
+ * Visits a GINQ expression and its child clauses.
+ *
+ * @param ginqExpression the expression to visit
+ * @return {@code null}
+ */
@Override
public Void visitGinqExpression(GinqExpression ginqExpression) {
visit(ginqExpression.getFromExpression());
@@ -71,6 +77,12 @@ public class GinqAstBaseVisitor extends CodeVisitorSupport implements GinqAstVis
return null;
}
+ /**
+ * Visits a {@code from} clause.
+ *
+ * @param fromExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitFromExpression(FromExpression fromExpression) {
visit(fromExpression.getAliasExpr());
@@ -78,6 +90,12 @@ public class GinqAstBaseVisitor extends CodeVisitorSupport implements GinqAstVis
return null;
}
+ /**
+ * Visits a join clause.
+ *
+ * @param joinExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitJoinExpression(JoinExpression joinExpression) {
visit((joinExpression.getAliasExpr()));
@@ -86,18 +104,36 @@ public class GinqAstBaseVisitor extends CodeVisitorSupport implements GinqAstVis
return null;
}
+ /**
+ * Visits an {@code on} clause.
+ *
+ * @param onExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitOnExpression(OnExpression onExpression) {
visit(onExpression.getFilterExpr());
return null;
}
+ /**
+ * Visits a {@code where} clause.
+ *
+ * @param whereExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitWhereExpression(WhereExpression whereExpression) {
visit(whereExpression.getFilterExpr());
return null;
}
+ /**
+ * Visits a {@code groupby} clause.
+ *
+ * @param groupExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitGroupExpression(GroupExpression groupExpression) {
visit(groupExpression.getClassifierExpr());
@@ -105,30 +141,60 @@ public class GinqAstBaseVisitor extends CodeVisitorSupport implements GinqAstVis
return null;
}
+ /**
+ * Visits a {@code having} clause.
+ *
+ * @param havingExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitHavingExpression(HavingExpression havingExpression) {
visit(havingExpression.getFilterExpr());
return null;
}
+ /**
+ * Visits an {@code orderby} clause.
+ *
+ * @param orderExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitOrderExpression(OrderExpression orderExpression) {
visit(orderExpression.getOrdersExpr());
return null;
}
+ /**
+ * Visits a {@code limit} clause.
+ *
+ * @param limitExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitLimitExpression(LimitExpression limitExpression) {
visit(limitExpression.getOffsetAndSizeExpr());
return null;
}
+ /**
+ * Visits a {@code select} clause.
+ *
+ * @param selectExpression the clause to visit
+ * @return {@code null}
+ */
@Override
public Void visitSelectExpression(SelectExpression selectExpression) {
visit(selectExpression.getProjectionExpr());
return null;
}
+ /**
+ * Visits a set-operation expression.
+ *
+ * @param setOperationExpression the expression to visit
+ * @return {@code null}
+ */
@Override
public Void visitSetOperationExpression(SetOperationExpression setOperationExpression) {
setOperationExpression.getLeft().accept(this);
@@ -136,12 +202,24 @@ public class GinqAstBaseVisitor extends CodeVisitorSupport implements GinqAstVis
return null;
}
+ /**
+ * Visits a shutdown expression.
+ *
+ * @param shutdownExpression the expression to visit
+ * @return {@code null}
+ */
@Override
public Void visitShutdownExpression(ShutdownExpression shutdownExpression) {
visit(shutdownExpression.getExpr());
return null;
}
+ /**
+ * Visits the supplied expression when present.
+ *
+ * @param expression the expression to visit
+ * @return {@code null}
+ */
@Override
public Void visit(AbstractGinqExpression expression) {
if (null == expression) return null;
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBuilder.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBuilder.java
index a56feebf4b..436beb7ec5 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBuilder.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstBuilder.java
@@ -67,12 +67,19 @@ import java.util.Set;
* @since 4.0.0
*/
public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorReportable {
+ /** Metadata key storing the root GINQ expression. */
public static final String ROOT_GINQ_EXPRESSION = "__ROOT_GINQ_EXPRESSION";
+ /** Metadata key marking {@code select distinct}. */
public static final String GINQ_SELECT_DISTINCT = "__GINQ_SELECT_DISTINCT";
private final Deque<GinqExpression> ginqExpressionStack = new ArrayDeque<>();
private GinqExpression latestGinqExpression;
private final SourceUnit sourceUnit;
+ /**
+ * Creates a builder for the supplied source unit.
+ *
+ * @param sourceUnit the source unit being processed
+ */
public GinqAstBuilder(SourceUnit sourceUnit) {
this.sourceUnit = sourceUnit;
}
@@ -82,6 +89,12 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
private String setOperationOp;
private static final List<String> SHUTDOWN_OPTION_LIST = Arrays.asList("immediate", "abort");
+ /**
+ * Builds a GINQ AST from the supplied AST node.
+ *
+ * @param astNode the node containing GINQ code
+ * @return the built GINQ expression
+ */
public AbstractGinqExpression buildAST(ASTNode astNode) {
if (astNode instanceof BlockStatement) {
List<Statement> statementList = ((BlockStatement) astNode).getStatements();
@@ -172,6 +185,11 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
private boolean visitingOverClause;
+ /**
+ * Visits method-call expressions while assembling GINQ clauses.
+ *
+ * @param call the method call to visit
+ */
@Override
public void visitMethodCallExpression(MethodCallExpression call) {
final String methodName = call.getMethodAsString();
@@ -419,6 +437,11 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
}
}
+ /**
+ * Visits binary expressions to wire nested GINQ expressions into filters.
+ *
+ * @param expression the expression to visit
+ */
@Override
public void visitBinaryExpression(BinaryExpression expression) {
super.visitBinaryExpression(expression);
@@ -438,6 +461,11 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
}
}
+ /**
+ * Visits variable expressions and validates GINQ keywords.
+ *
+ * @param expression the expression to visit
+ */
@Override
public void visitVariableExpression(VariableExpression expression) {
if (SET_OP_SET.contains(expression.getText())) {
@@ -474,6 +502,11 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
super.visitVariableExpression(expression);
}
+ /**
+ * Visits property expressions and reports malformed aliases in {@code select}.
+ *
+ * @param expression the expression to visit
+ */
@Override
public void visitPropertyExpression(PropertyExpression expression) {
super.visitPropertyExpression(expression);
@@ -487,6 +520,11 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
}
}
+ /**
+ * Visits declaration expressions and rejects assignments inside clause keywords.
+ *
+ * @param expression the expression to visit
+ */
@Override
public void visitDeclarationExpression(DeclarationExpression expression) {
final String typeName = expression.getLeftExpression().getType().getNameWithoutPackage();
@@ -501,6 +539,11 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
super.visitDeclarationExpression(expression);
}
+ /**
+ * Visits cast expressions and substitutes nested GINQ expressions when needed.
+ *
+ * @param expression the expression to visit
+ */
@Override
public void visitCastExpression(CastExpression expression) {
super.visitCastExpression(expression);
@@ -512,6 +555,11 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
}
}
+ /**
+ * Visits argument lists and replaces nested {@code select} expressions with built GINQ AST nodes.
+ *
+ * @param expression the expression to visit
+ */
@Override
public void visitArgumentlistExpression(ArgumentListExpression expression) {
List<Expression> list = expression.getExpressions();
@@ -533,6 +581,11 @@ public class GinqAstBuilder extends CodeVisitorSupport implements SyntaxErrorRep
return expression instanceof MethodCallExpression && KW_SELECT.equals(((MethodCallExpression) expression).getMethodAsString());
}
+ /**
+ * Returns the source unit used for syntax reporting.
+ *
+ * @return the current source unit
+ */
@Override
public SourceUnit getSourceUnit() {
return sourceUnit;
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstOptimizer.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstOptimizer.groovy
index 225984f2c7..4ad726c8e8 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstOptimizer.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstOptimizer.groovy
@@ -69,6 +69,12 @@ import java.util.stream.Collectors
@CompileStatic
class GinqAstOptimizer extends GinqAstBaseVisitor {
+ /**
+ * Visits a GINQ expression and rewrites join inputs when the optimization rules apply.
+ *
+ * @param ginqExpression the expression to optimize
+ * @return {@code null}
+ */
@Override
Void visitGinqExpression(GinqExpression ginqExpression) {
super.visitGinqExpression(ginqExpression)
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstVisitor.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstVisitor.java
index fbbb52d639..3a04dd62ec 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstVisitor.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstVisitor.java
@@ -42,19 +42,107 @@ import java.util.Map;
* @since 4.0.0
*/
public interface GinqAstVisitor<R> {
+ /**
+ * Visits a full GINQ expression.
+ *
+ * @param ginqExpression the expression to visit
+ * @return the visit result
+ */
R visitGinqExpression(GinqExpression ginqExpression);
+ /**
+ * Visits a {@code from} clause.
+ *
+ * @param fromExpression the clause to visit
+ * @return the visit result
+ */
R visitFromExpression(FromExpression fromExpression);
+ /**
+ * Visits a join clause.
+ *
+ * @param joinExpression the clause to visit
+ * @return the visit result
+ */
R visitJoinExpression(JoinExpression joinExpression);
+ /**
+ * Visits an {@code on} clause.
+ *
+ * @param onExpression the clause to visit
+ * @return the visit result
+ */
R visitOnExpression(OnExpression onExpression);
+ /**
+ * Visits a {@code where} clause.
+ *
+ * @param whereExpression the clause to visit
+ * @return the visit result
+ */
R visitWhereExpression(WhereExpression whereExpression);
+ /**
+ * Visits a {@code groupby} clause.
+ *
+ * @param groupExpression the clause to visit
+ * @return the visit result
+ */
R visitGroupExpression(GroupExpression groupExpression);
+ /**
+ * Visits a {@code having} clause.
+ *
+ * @param havingExpression the clause to visit
+ * @return the visit result
+ */
R visitHavingExpression(HavingExpression havingExpression);
+ /**
+ * Visits an {@code orderby} clause.
+ *
+ * @param orderExpression the clause to visit
+ * @return the visit result
+ */
R visitOrderExpression(OrderExpression orderExpression);
+ /**
+ * Visits a {@code limit} clause.
+ *
+ * @param limitExpression the clause to visit
+ * @return the visit result
+ */
R visitLimitExpression(LimitExpression limitExpression);
+ /**
+ * Visits a {@code select} clause.
+ *
+ * @param selectExpression the clause to visit
+ * @return the visit result
+ */
R visitSelectExpression(SelectExpression selectExpression);
+ /**
+ * Visits a set-operation expression.
+ *
+ * @param setOperationExpression the expression to visit
+ * @return the visit result
+ */
R visitSetOperationExpression(SetOperationExpression setOperationExpression);
+ /**
+ * Visits a shutdown expression.
+ *
+ * @param shutdownExpression the expression to visit
+ * @return the visit result
+ */
R visitShutdownExpression(ShutdownExpression shutdownExpression);
+ /**
+ * Visits an arbitrary GINQ expression.
+ *
+ * @param expression the expression to visit
+ * @return the visit result
+ */
R visit(AbstractGinqExpression expression);
+ /**
+ * Updates the visitor configuration.
+ *
+ * @param configuration the configuration to apply
+ */
default void setConfiguration(Map<String, String> configuration) {}
+ /**
+ * Returns the visitor configuration.
+ *
+ * @return the current configuration
+ */
default Map<String, String> getConfiguration() { return Collections.emptyMap(); }
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqSyntaxError.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqSyntaxError.java
index c3c879e1ae..c2a4aac8b7 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqSyntaxError.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqSyntaxError.java
@@ -32,20 +32,43 @@ public class GinqSyntaxError extends AssertionError {
private final int line;
private final int column;
+ /**
+ * Creates a syntax error using the position of the given expression.
+ *
+ * @param message the error message
+ * @param expression the expression supplying line and column information
+ */
public GinqSyntaxError(String message, Expression expression) {
this(message, expression.getLineNumber(), expression.getColumnNumber());
}
+ /**
+ * Creates a syntax error at the supplied source position.
+ *
+ * @param message the error message
+ * @param line the source line
+ * @param column the source column
+ */
public GinqSyntaxError(String message, int line, int column) {
super(message, null);
this.line = line;
this.column = column;
}
+ /**
+ * Returns the source line of the error.
+ *
+ * @return the line number
+ */
public int getLine() {
return line;
}
+ /**
+ * Returns the source column of the error.
+ *
+ * @return the column number
+ */
public int getColumn() {
return column;
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/SyntaxErrorReportable.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/SyntaxErrorReportable.java
index e160107dc3..dda466ddc2 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/SyntaxErrorReportable.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/SyntaxErrorReportable.java
@@ -28,8 +28,18 @@ import org.codehaus.groovy.syntax.SyntaxException;
* @since 4.0.0
*/
public interface SyntaxErrorReportable {
+ /**
+ * Returns the source unit collecting syntax errors.
+ *
+ * @return the source unit used for reporting
+ */
SourceUnit getSourceUnit();
+ /**
+ * Adds the supplied GINQ syntax error to the current source unit.
+ *
+ * @param ginqSyntaxError the error to report
+ */
default void collectSyntaxError(GinqSyntaxError ginqSyntaxError) {
SourceUnit sourceUnit = getSourceUnit();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/AbstractGinqExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/AbstractGinqExpression.java
index e15792e5c7..6e3b8cba48 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/AbstractGinqExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/AbstractGinqExpression.java
@@ -30,14 +30,32 @@ import org.codehaus.groovy.ast.expr.ExpressionTransformer;
* @since 4.0.0
*/
public abstract class AbstractGinqExpression extends Expression implements NodeMetaDataHandler {
+ /**
+ * Returns this expression because GINQ expressions are transformed elsewhere.
+ *
+ * @param transformer the transformer requesting the change
+ * @return this expression
+ */
@Override
public Expression transformExpression(ExpressionTransformer transformer) {
// do nothing for now
return this;
}
+ /**
+ * Accepts a GINQ visitor.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
public abstract <R> R accept(GinqAstVisitor<R> visitor);
+ /**
+ * Does nothing because GINQ expressions are visited through {@link GinqAstVisitor}.
+ *
+ * @param visitor the Groovy code visitor
+ */
@Override
public void visit(GroovyCodeVisitor visitor) {
// do nothing for now
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/DataSourceExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/DataSourceExpression.java
index f9d871558a..17b738a1c3 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/DataSourceExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/DataSourceExpression.java
@@ -26,20 +26,45 @@ import org.codehaus.groovy.ast.expr.Expression;
* @since 4.0.0
*/
public abstract class DataSourceExpression extends AbstractGinqExpression implements DataSourceHolder {
+ /** Alias expression bound to the data source. */
protected final Expression aliasExpr;
+ /** Expression yielding the data source. */
protected Expression dataSourceExpr;
+ /**
+ * Creates a data-source expression.
+ *
+ * @param aliasExpr the alias expression
+ * @param dataSourceExpr the source expression
+ */
public DataSourceExpression(Expression aliasExpr, Expression dataSourceExpr) {
this.aliasExpr = aliasExpr;
this.dataSourceExpr = dataSourceExpr;
}
+ /**
+ * Returns the alias expression.
+ *
+ * @return the alias expression
+ */
public Expression getAliasExpr() {
return aliasExpr;
}
+
+ /**
+ * Returns the data-source expression.
+ *
+ * @return the data-source expression
+ */
public Expression getDataSourceExpr() {
return dataSourceExpr;
}
+
+ /**
+ * Replaces the data-source expression.
+ *
+ * @param dataSourceExpr the new data-source expression
+ */
public void setDataSourceExpr(Expression dataSourceExpr) {
this.dataSourceExpr = dataSourceExpr;
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/DataSourceHolder.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/DataSourceHolder.java
index 9eb30d68c2..7073c19303 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/DataSourceHolder.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/DataSourceHolder.java
@@ -24,6 +24,16 @@ package org.apache.groovy.ginq.dsl.expression;
* @since 4.0.0
*/
public interface DataSourceHolder {
+ /**
+ * Returns the current data-source expression.
+ *
+ * @return the current data source
+ */
DataSourceExpression getDataSourceExpression();
+ /**
+ * Updates the current data-source expression.
+ *
+ * @param dataSourceExpression the new data source
+ */
void setDataSourceExpression(DataSourceExpression dataSourceExpression);
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/FilterExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/FilterExpression.java
index 2fea982619..a751b1ba9d 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/FilterExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/FilterExpression.java
@@ -26,16 +26,32 @@ import org.codehaus.groovy.ast.expr.Expression;
* @since 4.0.0
*/
public abstract class FilterExpression extends ProcessExpression {
+ /** Filter expression applied by the clause. */
protected Expression filterExpr;
+ /**
+ * Creates a filter expression.
+ *
+ * @param filterExpr the filter condition
+ */
public FilterExpression(Expression filterExpr) {
this.filterExpr = filterExpr;
}
+ /**
+ * Returns the filter condition.
+ *
+ * @return the filter condition
+ */
public Expression getFilterExpr() {
return filterExpr;
}
+ /**
+ * Replaces the filter condition.
+ *
+ * @param filterExpr the new filter condition
+ */
public void setFilterExpr(Expression filterExpr) {
this.filterExpr = filterExpr;
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/FromExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/FromExpression.java
index 85d44cecc5..585b799f06 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/FromExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/FromExpression.java
@@ -27,25 +27,53 @@ import org.codehaus.groovy.ast.expr.Expression;
* @since 4.0.0
*/
public class FromExpression extends DataSourceExpression {
+ /**
+ * Creates a {@code from} clause.
+ *
+ * @param aliasExpr the alias expression
+ * @param dataSourceExpr the source expression
+ */
public FromExpression(Expression aliasExpr, Expression dataSourceExpr) {
super(aliasExpr, dataSourceExpr);
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitFromExpression(this);
}
+ /**
+ * Returns this clause as its own data-source expression.
+ *
+ * @return this instance
+ */
@Override
public DataSourceExpression getDataSourceExpression() {
return this;
}
+ /**
+ * Rejects replacing the {@code from} clause with another data source.
+ *
+ * @param dataSourceExpression the ignored replacement
+ */
@Override
public void setDataSourceExpression(DataSourceExpression dataSourceExpression) {
throw new UnsupportedOperationException(FromExpression.class.getName() + " can not be set to another DataSourceExpression instance");
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return "from " + aliasExpr.getText() + " in "
@@ -54,6 +82,11 @@ public class FromExpression extends DataSourceExpression {
: dataSourceExpr.getText());
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/GinqExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/GinqExpression.java
index 58a19f0bf4..c51a5e9f02 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/GinqExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/GinqExpression.java
@@ -52,72 +52,159 @@ public class GinqExpression extends AbstractGinqExpression {
private LimitExpression limitExpression;
private SelectExpression selectExpression;
+ /**
+ * Dispatches this expression to a GINQ-aware Groovy visitor.
+ *
+ * @param visitor the visitor to invoke
+ */
@Override
public void visit(GroovyCodeVisitor visitor) {
((GinqAstVisitor) visitor).visitGinqExpression(this);
}
+ /**
+ * Accepts a GINQ visitor.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitGinqExpression(this);
}
+ /**
+ * Returns the {@code from} clause.
+ *
+ * @return the {@code from} clause
+ */
public FromExpression getFromExpression() {
return fromExpression;
}
+ /**
+ * Sets the {@code from} clause.
+ *
+ * @param fromExpression the clause to set
+ */
public void setFromExpression(FromExpression fromExpression) {
this.fromExpression = fromExpression;
}
+ /**
+ * Returns the join clauses.
+ *
+ * @return the join clauses
+ */
public List<JoinExpression> getJoinExpressionList() {
return joinExpressionList;
}
+ /**
+ * Adds a join clause.
+ *
+ * @param joinExpression the clause to add
+ */
public void addJoinExpression(JoinExpression joinExpression) {
joinExpressionList.add(joinExpression);
}
+ /**
+ * Sets the {@code where} clause.
+ *
+ * @param whereExpression the clause to set
+ */
public void setWhereExpression(WhereExpression whereExpression) {
this.whereExpression = whereExpression;
}
+ /**
+ * Returns the {@code where} clause.
+ *
+ * @return the {@code where} clause
+ */
public WhereExpression getWhereExpression() {
return whereExpression;
}
+ /**
+ * Returns the {@code groupby} clause.
+ *
+ * @return the {@code groupby} clause
+ */
public GroupExpression getGroupExpression() {
return groupExpression;
}
+ /**
+ * Sets the {@code groupby} clause.
+ *
+ * @param groupExpression the clause to set
+ */
public void setGroupExpression(GroupExpression groupExpression) {
this.groupExpression = groupExpression;
}
+ /**
+ * Returns the {@code orderby} clause.
+ *
+ * @return the {@code orderby} clause
+ */
public OrderExpression getOrderExpression() {
return orderExpression;
}
+ /**
+ * Sets the {@code orderby} clause.
+ *
+ * @param orderExpression the clause to set
+ */
public void setOrderExpression(OrderExpression orderExpression) {
this.orderExpression = orderExpression;
}
+ /**
+ * Returns the {@code limit} clause.
+ *
+ * @return the {@code limit} clause
+ */
public LimitExpression getLimitExpression() {
return limitExpression;
}
+ /**
+ * Sets the {@code limit} clause.
+ *
+ * @param limitExpression the clause to set
+ */
public void setLimitExpression(LimitExpression limitExpression) {
this.limitExpression = limitExpression;
}
+ /**
+ * Returns the {@code select} clause.
+ *
+ * @return the {@code select} clause
+ */
public SelectExpression getSelectExpression() {
return selectExpression;
}
+ /**
+ * Sets the {@code select} clause.
+ *
+ * @param selectExpression the clause to set
+ */
public void setSelectExpression(SelectExpression selectExpression) {
this.selectExpression = selectExpression;
}
+ /**
+ * Returns the textual GINQ form of this expression.
+ *
+ * @return the expression text
+ */
@Override
public String getText() {
return fromExpression.getText() + " "
@@ -129,6 +216,11 @@ public class GinqExpression extends AbstractGinqExpression {
+ selectExpression.getText();
}
+ /**
+ * Returns the textual form of this expression.
+ *
+ * @return the expression text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/GroupExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/GroupExpression.java
index 1ad3a9c34c..12576d1f73 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/GroupExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/GroupExpression.java
@@ -31,35 +31,77 @@ public class GroupExpression extends ProcessExpression {
private HavingExpression havingExpression;
private String intoAlias;
+ /**
+ * Creates a {@code groupby} clause.
+ *
+ * @param classifierExpr the grouping classifier
+ */
public GroupExpression(Expression classifierExpr) {
this.classifierExpr = classifierExpr;
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitGroupExpression(this);
}
+ /**
+ * Returns the grouping classifier.
+ *
+ * @return the grouping classifier
+ */
public Expression getClassifierExpr() {
return classifierExpr;
}
+ /**
+ * Returns the optional {@code having} clause.
+ *
+ * @return the {@code having} clause, or {@code null}
+ */
public HavingExpression getHavingExpression() {
return havingExpression;
}
+ /**
+ * Sets the optional {@code having} clause.
+ *
+ * @param havingExpression the clause to set
+ */
public void setHavingExpression(HavingExpression havingExpression) {
this.havingExpression = havingExpression;
}
+ /**
+ * Returns the {@code into} alias.
+ *
+ * @return the alias, or {@code null}
+ */
public String getIntoAlias() {
return intoAlias;
}
+ /**
+ * Sets the {@code into} alias.
+ *
+ * @param intoAlias the alias to set
+ */
public void setIntoAlias(String intoAlias) {
this.intoAlias = intoAlias;
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return "groupby " + classifierExpr.getText() +
@@ -67,6 +109,11 @@ public class GroupExpression extends ProcessExpression {
(null == havingExpression ? "" : " " + havingExpression.getText());
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/HavingExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/HavingExpression.java
index ddbf708aa2..a3b8a2559e 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/HavingExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/HavingExpression.java
@@ -27,20 +27,42 @@ import org.codehaus.groovy.ast.expr.Expression;
* @since 4.0.0
*/
public class HavingExpression extends FilterExpression {
+ /**
+ * Creates a {@code having} clause.
+ *
+ * @param filterExpr the filter condition
+ */
public HavingExpression(Expression filterExpr) {
super(filterExpr);
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitHavingExpression(this);
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return "having " + filterExpr.getText();
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/JoinExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/JoinExpression.java
index 7bada2bfaa..2614684a08 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/JoinExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/JoinExpression.java
@@ -29,12 +29,17 @@ import java.util.List;
* @since 4.0.0
*/
public class JoinExpression extends DataSourceExpression implements DataSourceHolder {
+ /** Clause name for a smart inner join. */
public static final String SMART_INNER_JOIN = "join";
+ /** Clause name for a regular inner join. */
public static final String INNER_JOIN = "innerjoin";
+ /** Clause name for an inner hash join. */
public static final String INNER_HASH_JOIN = "innerhashjoin";
private static final String LEFT_JOIN = "leftjoin";
+ /** Clause name for a left hash join. */
public static final String LEFT_HASH_JOIN = "lefthashjoin";
private static final String CROSS_JOIN = "crossjoin";
+ /** All supported join clause names. */
public static final List<String> JOIN_NAME_LIST =
List.of(SMART_INNER_JOIN, INNER_JOIN, INNER_HASH_JOIN, LEFT_JOIN, LEFT_HASH_JOIN, "rightjoin", "righthashjoin", "fulljoin", "fullhashjoin", CROSS_JOIN);
@@ -42,66 +47,146 @@ public class JoinExpression extends DataSourceExpression implements DataSourceHo
private OnExpression onExpression;
private DataSourceExpression dataSourceExpression;
+ /**
+ * Creates a join clause.
+ *
+ * @param joinName the join keyword
+ * @param aliasExpr the join alias
+ * @param dataSourceExpr the join data source
+ */
public JoinExpression(String joinName, Expression aliasExpr, Expression dataSourceExpr) {
super(aliasExpr, dataSourceExpr);
this.joinName = joinName;
}
+ /**
+ * Checks whether the supplied method name denotes a join clause.
+ *
+ * @param methodName the method name to test
+ * @return {@code true} if the method name is a join clause
+ */
public static boolean isJoinExpression(String methodName) {
return JOIN_NAME_LIST.contains(methodName);
}
+ /**
+ * Indicates whether this clause is a cross join.
+ *
+ * @return {@code true} for a cross join
+ */
public boolean isCrossJoin() {
return CROSS_JOIN.equals(joinName);
}
+ /**
+ * Indicates whether this clause is a smart inner join.
+ *
+ * @return {@code true} for a smart inner join
+ */
public boolean isSmartInnerJoin() {
return SMART_INNER_JOIN.equals(joinName);
}
+ /**
+ * Indicates whether this clause is an inner join.
+ *
+ * @return {@code true} for an inner join
+ */
public boolean isInnerJoin() {
return INNER_JOIN.equals(joinName);
}
+ /**
+ * Indicates whether this clause is an inner hash join.
+ *
+ * @return {@code true} for an inner hash join
+ */
public boolean isInnerHashJoin() {
return INNER_HASH_JOIN.equals(joinName);
}
+ /**
+ * Indicates whether this clause is a left join.
+ *
+ * @return {@code true} for a left join
+ */
public boolean isLeftJoin() {
return LEFT_JOIN.equals(joinName);
}
+ /**
+ * Indicates whether this clause is a left hash join.
+ *
+ * @return {@code true} for a left hash join
+ */
public boolean isLeftHashJoin() {
return LEFT_HASH_JOIN.equals(joinName);
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitJoinExpression(this);
}
+ /**
+ * Returns the join keyword.
+ *
+ * @return the join keyword
+ */
public String getJoinName() {
return joinName;
}
+ /**
+ * Returns the optional {@code on} clause.
+ *
+ * @return the {@code on} clause, or {@code null}
+ */
public OnExpression getOnExpression() {
return onExpression;
}
+ /**
+ * Sets the optional {@code on} clause.
+ *
+ * @param onExpression the clause to set
+ */
public void setOnExpression(OnExpression onExpression) {
this.onExpression = onExpression;
}
+ /**
+ * Returns the preceding data-source expression.
+ *
+ * @return the preceding data source
+ */
@Override
public DataSourceExpression getDataSourceExpression() {
return dataSourceExpression;
}
+ /**
+ * Sets the preceding data-source expression.
+ *
+ * @param dataSourceExpression the preceding data source
+ */
@Override
public void setDataSourceExpression(DataSourceExpression dataSourceExpression) {
this.dataSourceExpression = dataSourceExpression;
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return joinName + " " + aliasExpr.getText()
@@ -109,6 +194,11 @@ public class JoinExpression extends DataSourceExpression implements DataSourceHo
+ (null == onExpression ? "" : " " + onExpression.getText());
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/LimitExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/LimitExpression.java
index 2ebc379f9d..7a7fe4c337 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/LimitExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/LimitExpression.java
@@ -29,24 +29,51 @@ import org.codehaus.groovy.ast.expr.Expression;
public class LimitExpression extends ProcessExpression {
private final Expression offsetAndSizeExpr;
+ /**
+ * Creates a {@code limit} clause.
+ *
+ * @param offsetAndSizeExpr the limit expression
+ */
public LimitExpression(Expression offsetAndSizeExpr) {
this.offsetAndSizeExpr = offsetAndSizeExpr;
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitLimitExpression(this);
}
+ /**
+ * Returns the offset-and-size expression.
+ *
+ * @return the limit expression
+ */
public Expression getOffsetAndSizeExpr() {
return offsetAndSizeExpr;
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return "limit " + offsetAndSizeExpr.getText();
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/OnExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/OnExpression.java
index 04db8a5c67..f0b4ba4a22 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/OnExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/OnExpression.java
@@ -27,20 +27,42 @@ import org.codehaus.groovy.ast.expr.Expression;
* @since 4.0.0
*/
public class OnExpression extends FilterExpression {
+ /**
+ * Creates an {@code on} clause.
+ *
+ * @param filterExpr the join condition
+ */
public OnExpression(Expression filterExpr) {
super(filterExpr);
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitOnExpression(this);
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return "on " + filterExpr.getText();
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/OrderExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/OrderExpression.java
index ba21fbf057..7ad92fb461 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/OrderExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/OrderExpression.java
@@ -29,24 +29,51 @@ import org.codehaus.groovy.ast.expr.Expression;
public class OrderExpression extends ProcessExpression {
private final Expression ordersExpr;
+ /**
+ * Creates an {@code orderby} clause.
+ *
+ * @param ordersExpr the order expression
+ */
public OrderExpression(Expression ordersExpr) {
this.ordersExpr = ordersExpr;
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitOrderExpression(this);
}
+ /**
+ * Returns the order expression.
+ *
+ * @return the order expression
+ */
public Expression getOrdersExpr() {
return ordersExpr;
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return "orderby " + ordersExpr.getText();
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/ProcessExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/ProcessExpression.java
index bc4cb5c703..baa8a5b975 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/ProcessExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/ProcessExpression.java
@@ -26,11 +26,21 @@ package org.apache.groovy.ginq.dsl.expression;
public abstract class ProcessExpression extends AbstractGinqExpression implements DataSourceHolder {
private DataSourceExpression dataSourceExpression;
+ /**
+ * Returns the data source feeding this clause.
+ *
+ * @return the data source
+ */
@Override
public DataSourceExpression getDataSourceExpression() {
return dataSourceExpression;
}
+ /**
+ * Sets the data source feeding this clause.
+ *
+ * @param dataSourceExpression the data source to set
+ */
@Override
public void setDataSourceExpression(DataSourceExpression dataSourceExpression) {
this.dataSourceExpression = dataSourceExpression;
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/SelectExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/SelectExpression.java
index 6c03a742f3..18c4da47a4 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/SelectExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/SelectExpression.java
@@ -29,24 +29,51 @@ import org.codehaus.groovy.ast.expr.Expression;
public class SelectExpression extends ProcessExpression {
private final Expression projectionExpr;
+ /**
+ * Creates a {@code select} clause.
+ *
+ * @param projectionExpr the projection expression
+ */
public SelectExpression(Expression projectionExpr) {
this.projectionExpr = projectionExpr;
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitSelectExpression(this);
}
+ /**
+ * Returns the projection expression.
+ *
+ * @return the projection expression
+ */
public Expression getProjectionExpr() {
return projectionExpr;
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return "select " + projectionExpr.getText();
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/SetOperationExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/SetOperationExpression.java
index 76bb5e96a9..4a9a3419d7 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/SetOperationExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/SetOperationExpression.java
@@ -31,34 +31,73 @@ public class SetOperationExpression extends AbstractGinqExpression {
private final String operation;
private final GinqExpression right;
+ /**
+ * Creates a set-operation expression.
+ *
+ * @param left the left query
+ * @param operation the set-operation name
+ * @param right the right query
+ */
public SetOperationExpression(AbstractGinqExpression left, String operation, GinqExpression right) {
this.left = left;
this.operation = operation;
this.right = right;
}
+ /**
+ * Returns the left query.
+ *
+ * @return the left query
+ */
public AbstractGinqExpression getLeft() {
return left;
}
+ /**
+ * Returns the operation name.
+ *
+ * @return the operation name
+ */
public String getOperation() {
return operation;
}
+ /**
+ * Returns the right query.
+ *
+ * @return the right query
+ */
public GinqExpression getRight() {
return right;
}
+ /**
+ * Accepts a visitor for this expression.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitSetOperationExpression(this);
}
+ /**
+ * Returns the textual GINQ form of this expression.
+ *
+ * @return the expression text
+ */
@Override
public String getText() {
return left.getText() + " " + operation + " " + right.getText();
}
+ /**
+ * Returns the textual form of this expression.
+ *
+ * @return the expression text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/ShutdownExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/ShutdownExpression.java
index d26a93a6a6..51505bb4d2 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/ShutdownExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/ShutdownExpression.java
@@ -30,29 +30,62 @@ public class ShutdownExpression extends AbstractGinqExpression {
private final Expression expr;
private final int mode;
+ /**
+ * Creates a shutdown expression.
+ *
+ * @param expr the original shutdown expression
+ * @param mode the shutdown mode
+ */
public ShutdownExpression(Expression expr, int mode) {
this.expr = expr;
this.mode = mode;
}
+ /**
+ * Accepts a visitor for this expression.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitShutdownExpression(this);
}
+ /**
+ * Returns the original shutdown expression.
+ *
+ * @return the original expression
+ */
public Expression getExpr() {
return expr;
}
+ /**
+ * Returns the shutdown mode.
+ *
+ * @return the shutdown mode
+ */
public int getMode() {
return mode;
}
+ /**
+ * Returns the textual form of the shutdown expression.
+ *
+ * @return the expression text
+ */
@Override
public String getText() {
return expr.getText();
}
+ /**
+ * Returns the textual form of this expression.
+ *
+ * @return the expression text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/WhereExpression.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/WhereExpression.java
index e43ee95380..a348388e48 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/WhereExpression.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/expression/WhereExpression.java
@@ -27,20 +27,42 @@ import org.codehaus.groovy.ast.expr.Expression;
* @since 4.0.0
*/
public class WhereExpression extends FilterExpression {
+ /**
+ * Creates a {@code where} clause.
+ *
+ * @param filterExpr the filter condition
+ */
public WhereExpression(Expression filterExpr) {
super(filterExpr);
}
+ /**
+ * Accepts a visitor for this clause.
+ *
+ * @param visitor the visitor to accept
+ * @param <R> the visit result type
+ * @return the visit result
+ */
@Override
public <R> R accept(GinqAstVisitor<R> visitor) {
return visitor.visitWhereExpression(this);
}
+ /**
+ * Returns the textual GINQ form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String getText() {
return "where " + filterExpr.getText();
}
+ /**
+ * Returns the textual form of this clause.
+ *
+ * @return the clause text
+ */
@Override
public String toString() {
return getText();
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
index 9d62d13f11..44c3387f3f 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
@@ -113,6 +113,11 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.varX
@CompileStatic
class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable {
+ /**
+ * Creates a walker for the supplied source unit.
+ *
+ * @param sourceUnit the source unit being transformed
+ */
GinqAstWalker(SourceUnit sourceUnit) {
this.sourceUnit = sourceUnit
}
@@ -121,6 +126,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
ginqExpressionStack.peek()
}
+ /**
+ * Visits a full GINQ expression and converts it into chained queryable calls.
+ *
+ * @param ginqExpression the expression to transform
+ * @return the transformed method call
+ */
@Override
MethodCallExpression visitGinqExpression(GinqExpression ginqExpression) {
if (!ginqExpression) {
@@ -317,6 +328,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
}
}
+ /**
+ * Visits a {@code from} clause.
+ *
+ * @param fromExpression the clause to transform
+ * @return the transformed method call
+ */
@Override
MethodCallExpression visitFromExpression(FromExpression fromExpression) {
MethodCallExpression fromMethodCallExpression = constructFromMethodCallExpression(fromExpression.dataSourceExpr)
@@ -325,6 +342,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
return fromMethodCallExpression
}
+ /**
+ * Visits a join clause.
+ *
+ * @param joinExpression the clause to transform
+ * @return the transformed method call
+ */
@Override
MethodCallExpression visitJoinExpression(JoinExpression joinExpression) {
Expression receiver = joinExpression.getNodeMetaData(__METHOD_CALL_RECEIVER)
@@ -345,6 +368,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
return joinMethodCallExpression
}
+ /**
+ * Leaves {@code on} clauses to their owning join clause.
+ *
+ * @param onExpression the clause being visited
+ * @return {@code null}
+ */
@Override
MethodCallExpression visitOnExpression(OnExpression onExpression) {
// do nothing
@@ -528,6 +557,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
}
}
+ /**
+ * Visits a {@code where} clause.
+ *
+ * @param whereExpression the clause to transform
+ * @return the transformed method call
+ */
@Override
MethodCallExpression visitWhereExpression(WhereExpression whereExpression) {
DataSourceExpression dataSourceExpression = whereExpression.getDataSourceExpression()
@@ -576,6 +611,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
return callX(visit(expression), "toList")
}
+ /**
+ * Visits a {@code groupby} clause.
+ *
+ * @param groupExpression the clause to transform
+ * @return the transformed method call
+ */
@Override
MethodCallExpression visitGroupExpression(GroupExpression groupExpression) {
DataSourceExpression dataSourceExpression = groupExpression.dataSourceExpression
@@ -620,11 +661,23 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
return groupMethodCallExpression
}
+ /**
+ * Leaves {@code having} clauses to their owning group clause.
+ *
+ * @param havingExpression the clause being visited
+ * @return {@code null}
+ */
@Override
Expression visitHavingExpression(HavingExpression havingExpression) {
// do nothing
}
+ /**
+ * Visits an {@code orderby} clause.
+ *
+ * @param orderExpression the clause to transform
+ * @return the transformed method call
+ */
@Override
MethodCallExpression visitOrderExpression(OrderExpression orderExpression) {
DataSourceExpression dataSourceExpression = orderExpression.dataSourceExpression
@@ -696,6 +749,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
}
}
+ /**
+ * Visits a {@code limit} clause.
+ *
+ * @param limitExpression the clause to transform
+ * @return the transformed method call
+ */
@Override
MethodCallExpression visitLimitExpression(LimitExpression limitExpression) {
Expression limitMethodCallReceiver = limitExpression.getNodeMetaData(__METHOD_CALL_RECEIVER)
@@ -706,6 +765,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
return limitMethodCallExpression
}
+ /**
+ * Visits a {@code select} clause.
+ *
+ * @param selectExpression the clause to transform
+ * @return the transformed method call
+ */
@Override
MethodCallExpression visitSelectExpression(SelectExpression selectExpression) {
currentGinqExpression.putNodeMetaData(__VISITING_SELECT, true)
@@ -871,6 +936,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
return selectMethodCallExpression
}
+ /**
+ * Visits a set-operation expression.
+ *
+ * @param setOperationExpression the expression to transform
+ * @return the transformed expression
+ */
@Override
Expression visitSetOperationExpression(SetOperationExpression setOperationExpression) {
Expression leftExpr = visit(setOperationExpression.left)
@@ -888,6 +959,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
return callX(leftExpr, methodName, args(rightExpr))
}
+ /**
+ * Visits a shutdown expression.
+ *
+ * @param shutdownExpression the expression to transform
+ * @return the shutdown call expression
+ */
@Override
Expression visitShutdownExpression(ShutdownExpression shutdownExpression) {
return callX(classX(makeCached(QueryableHelper)), 'shutdown', constX(shutdownExpression.mode))
@@ -1427,6 +1504,12 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
expression
}
+ /**
+ * Visits an arbitrary GINQ expression.
+ *
+ * @param expression the expression to transform
+ * @return the transformed expression
+ */
@Override
Expression visit(AbstractGinqExpression expression) {
expression.accept(this)
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/ConcurrentObjectHolder.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/ConcurrentObjectHolder.java
index b0d708a95a..9102652b60 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/ConcurrentObjectHolder.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/ConcurrentObjectHolder.java
@@ -30,10 +30,20 @@ class ConcurrentObjectHolder<T> {
private volatile T object;
private final Supplier<T> supplier;
+ /**
+ * Creates a holder that lazily initializes its object from the given supplier.
+ *
+ * @param supplier the supplier used to create the object
+ */
ConcurrentObjectHolder(Supplier<T> supplier) {
this.supplier = supplier;
}
+ /**
+ * Returns the cached object, creating it on first access.
+ *
+ * @return the cached object
+ */
public T getObject() {
if (null != object) return object;
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/GroupImpl.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/GroupImpl.java
index f03e35814e..009373d3bf 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/GroupImpl.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/GroupImpl.java
@@ -30,6 +30,11 @@ import java.util.stream.Stream;
class GroupImpl<T> extends QueryableCollection<T> implements Group<T> {
@Serial private static final long serialVersionUID = 5737735821215711785L;
+ /**
+ * Creates a group backed by the supplied stream.
+ *
+ * @param sourceStream the group elements
+ */
GroupImpl(Stream<T> sourceStream) {
super(sourceStream);
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/GroupResultImpl.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/GroupResultImpl.java
index b9106a41a3..14f89d95ef 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/GroupResultImpl.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/GroupResultImpl.java
@@ -32,11 +32,22 @@ class GroupResultImpl<K, T> extends QueryableCollection<T> implements GroupResul
private final K key;
+ /**
+ * Creates a group result.
+ *
+ * @param key the group key
+ * @param group the grouped elements
+ */
GroupResultImpl(K key, Queryable<T> group) {
super(group.toList());
this.key = key;
}
+ /**
+ * Returns the group key, unwrapping single-value named keys.
+ *
+ * @return the group key
+ */
@SuppressWarnings("unchecked")
@Override
public K getKey() {
@@ -48,6 +59,12 @@ class GroupResultImpl<K, T> extends QueryableCollection<T> implements GroupResul
return key;
}
+ /**
+ * Resolves a named key component for grouped results created with aliases.
+ *
+ * @param name the key component name
+ * @return the named key component
+ */
@Override
public Object get(String name) {
if (key instanceof NamedRecord) {
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/NamedRecord.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/NamedRecord.groovy
index 28ee82634f..3f24b0a641 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/NamedRecord.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/NamedRecord.groovy
@@ -37,21 +37,45 @@ class NamedRecord<E, T> extends NamedTuple<E> {
private final List<String> aliasList
private SourceRecord<T> sourceRecord
+ /**
+ * Creates a named record from projected values and aliases.
+ *
+ * @param elementList the projected values
+ * @param nameList the projected names
+ * @param aliasList the source aliases available for lookup
+ */
NamedRecord(List<E> elementList, List<String> nameList, List<String> aliasList = Collections.emptyList()) {
super(elementList, nameList)
this.aliasList = aliasList
}
+ /**
+ * Returns the tuple-style string form of this record.
+ *
+ * @return the string form of this record
+ */
@Override
String toString() {
return super.toString()
}
+ /**
+ * Returns the value for the supplied name.
+ *
+ * @param name the projected name or source alias
+ * @return the matching value
+ */
@Override
def get(String name) {
return getAt(name)
}
+ /**
+ * Returns the value for the supplied name, falling back to the source record.
+ *
+ * @param name the projected name or source alias
+ * @return the matching value
+ */
@Override
def getAt(String name) {
if (exists(name)) {
@@ -60,10 +84,21 @@ class NamedRecord<E, T> extends NamedTuple<E> {
return sourceRecord?.get(name)
}
+ /**
+ * Returns the source aliases available to this record.
+ *
+ * @return the source aliases
+ */
List<String> getAliasList() {
return Collections.unmodifiableList(aliasList)
}
+ /**
+ * Attaches the original source record for alias-based lookups.
+ *
+ * @param sr the source record
+ * @return this record
+ */
NamedRecord<E, T> sourceRecord(T sr) {
sourceRecord = new SourceRecord<>(sr, getAliasList())
return this
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/NamedTuple.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/NamedTuple.groovy
index 5240c2728b..a955d2ac5c 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/NamedTuple.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/NamedTuple.groovy
@@ -40,6 +40,12 @@ class NamedTuple<E> extends Tuple<E> {
private final Map<String, E> data
+ /**
+ * Creates an immutable tuple backed by the supplied names.
+ *
+ * @param elementList the element values
+ * @param nameList the names matching those values
+ */
NamedTuple(List<E> elementList, List<String> nameList) {
super(elementList as E[])
@@ -60,22 +66,50 @@ class NamedTuple<E> extends Tuple<E> {
}
}
+ /**
+ * Returns the value bound to the supplied name.
+ *
+ * @param name the tuple element name
+ * @return the bound value
+ */
public get(String name) {
return data.get(name)
}
+ /**
+ * Returns the value bound to the supplied name.
+ *
+ * @param name the tuple element name
+ * @return the bound value
+ */
public getAt(String name) {
return data.get(name)
}
+ /**
+ * Tests whether this tuple contains the supplied name.
+ *
+ * @param name the tuple element name
+ * @return {@code true} if the name exists
+ */
boolean exists(String name) {
return data.containsKey(name)
}
+ /**
+ * Returns the tuple element names in order.
+ *
+ * @return the tuple element names
+ */
List<String> getNameList() {
return new ArrayList<>(data.keySet())
}
+ /**
+ * Returns the tuple contents in {@code name:value} form.
+ *
+ * @return the tuple string form
+ */
@Override
public String toString() {
StringJoiner sj = new StringJoiner(', ', '(', ')')
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Null.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Null.groovy
index b1785a82d7..87fd0db1ae 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Null.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Null.groovy
@@ -27,56 +27,130 @@ import groovy.transform.PackageScope
*/
@PackageScope
class Null {
+ /** Shared null-object instance. */
public static final Null INSTANCE = new Null()
private Null() {}
+ /**
+ * Ignores missing instance methods and returns {@code null}.
+ *
+ * @param name the missing method name
+ * @param args the method arguments
+ * @return {@code null}
+ */
def methodMissing(String name, def args) {
return null
}
+ /**
+ * Ignores missing instance properties and returns {@code null}.
+ *
+ * @param name the missing property name
+ * @return {@code null}
+ */
def propertyMissing(String name) {
return null
}
+ /**
+ * Ignores writes to missing instance properties.
+ *
+ * @param name the missing property name
+ * @param value the ignored value
+ * @return {@code null}
+ */
def propertyMissing(String name, def value) {
return null
}
+ /**
+ * Ignores missing static methods and returns {@code null}.
+ *
+ * @param name the missing method name
+ * @param args the method arguments
+ * @return {@code null}
+ */
static $static_methodMissing(String name, def args) {
return null
}
+ /**
+ * Ignores missing static properties and returns {@code null}.
+ *
+ * @param name the missing property name
+ * @return {@code null}
+ */
static $static_propertyMissing(String name) {
return null
}
+ /**
+ * Ignores writes to missing static properties.
+ *
+ * @param name the missing property name
+ * @param value the ignored value
+ * @return {@code null}
+ */
static $static_propertyMissing(String name, def value) {
return null
}
+ /**
+ * Evaluates this null object as {@code false}.
+ *
+ * @return {@code false}
+ */
boolean asBoolean() {
return false
}
+ /**
+ * Returns this null object for any coercion target.
+ *
+ * @param c the requested target type
+ * @return this instance
+ */
def asType(Class c) {
return this
}
+ /**
+ * Checks identity against another object.
+ *
+ * @param other the object to compare with
+ * @return {@code true} if both references are identical
+ */
boolean is(Object other) {
return other === this
}
+ /**
+ * Returns the stable hash code for the null object.
+ *
+ * @return {@code 0}
+ */
@Override
int hashCode() {
return 0
}
+ /**
+ * Tests whether the other object is the same null-object instance.
+ *
+ * @param obj the other object
+ * @return {@code true} if it is this instance
+ */
@Override
boolean equals(Object obj) {
return obj === this
}
+ /**
+ * Returns this singleton instance.
+ *
+ * @return this instance
+ */
@Override
Object clone() {
return this
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/PartitionImpl.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/PartitionImpl.java
index fae2ae9a2d..fdc77e284b 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/PartitionImpl.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/PartitionImpl.java
@@ -29,6 +29,11 @@ import java.io.Serial;
class PartitionImpl<T> extends QueryableCollection<T> implements Partition<T> {
@Serial private static final long serialVersionUID = -3650144225768070117L;
+ /**
+ * Creates a partition backed by the supplied iterable.
+ *
+ * @param sourceIterable the partition elements
+ */
PartitionImpl(Iterable<T> sourceIterable) {
super(sourceIterable);
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
index 5f4809d9a3..a3b013b56f 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
@@ -547,34 +547,69 @@ public interface Queryable<T> {
* @since 4.0.0
*/
class Order<T, U extends Comparable<? super U>> {
+ /** Shared empty array for order clauses. */
@SuppressWarnings("rawtypes")
public static final Order[] EMPTY_ARRAY = new Order[0];
private final Function<? super T, ? extends U> keyExtractor;
private final boolean asc;
private final boolean nullsLast;
+ /**
+ * Creates an order rule with nulls sorted last.
+ *
+ * @param keyExtractor the sort key extractor
+ * @param asc whether to sort ascending
+ */
public Order(Function<? super T, ? extends U> keyExtractor, boolean asc) {
this(keyExtractor, asc, true);
}
+ /**
+ * Creates an order rule.
+ *
+ * @param keyExtractor the sort key extractor
+ * @param asc whether to sort ascending
+ * @param nullsLast whether nulls should be ordered last
+ */
public Order(Function<? super T, ? extends U> keyExtractor, boolean asc, boolean nullsLast) {
this.keyExtractor = keyExtractor;
this.asc = asc;
this.nullsLast = nullsLast;
}
+ /**
+ * Returns the sort key extractor.
+ *
+ * @return the sort key extractor
+ */
public Function<? super T, ? extends U> getKeyExtractor() {
return keyExtractor;
}
+ /**
+ * Indicates whether this rule sorts ascending.
+ *
+ * @return {@code true} for ascending order
+ */
public boolean isAsc() {
return asc;
}
+ /**
+ * Indicates whether this rule places null values last.
+ *
+ * @return {@code true} if nulls are ordered last
+ */
public boolean isNullsLast() {
return nullsLast;
}
+ /**
+ * Compares this rule with another one.
+ *
+ * @param o the other object
+ * @return {@code true} if both rules are equal
+ */
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -583,6 +618,11 @@ public interface Queryable<T> {
keyExtractor.equals(order.keyExtractor);
}
+ /**
+ * Returns the hash code of this rule.
+ *
+ * @return the hash code
+ */
@Override
public int hashCode() {
return Objects.hash(keyExtractor, asc);
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableCollection.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableCollection.java
index deba75f769..c0af0370d4 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableCollection.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableCollection.java
@@ -82,14 +82,29 @@ import static org.codehaus.groovy.runtime.typehandling.NumberMath.toBigDecimal;
@Internal
class QueryableCollection<T> implements Queryable<T>, Serializable {
+ /**
+ * Creates a queryable collection backed by an iterable.
+ *
+ * @param sourceIterable the source elements
+ */
QueryableCollection(Iterable<T> sourceIterable) {
this.sourceIterable = sourceIterable;
}
+ /**
+ * Creates a queryable collection backed by a stream.
+ *
+ * @param sourceStream the source stream
+ */
QueryableCollection(Stream<T> sourceStream) {
this.sourceStream = sourceStream;
}
+ /**
+ * Returns an iterator over the current source.
+ *
+ * @return an iterator over the elements
+ */
public Iterator<T> iterator() {
readLock.lock();
try {
@@ -223,6 +238,13 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
return lj.union(rj);
}
+ /**
+ * Produces the Cartesian product with another queryable source.
+ *
+ * @param queryable the other source
+ * @param <U> the element type of the other source
+ * @return the joined result
+ */
@Override
public <U> Queryable<Tuple2<T, U>> crossJoin(Queryable<? extends U> queryable) {
Stream<Tuple2<T, U>> stream =
@@ -314,6 +336,13 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
return comparator;
}
+ /**
+ * Applies offset and size limits to the current stream.
+ *
+ * @param offset the number of rows to skip
+ * @param size the maximum number of rows to keep
+ * @return the limited queryable
+ */
@Override
public Queryable<T> limit(long offset, long size) {
Stream<T> stream = this.stream().skip(offset).limit(size);
@@ -365,6 +394,11 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
}
}
+ /**
+ * Removes duplicate elements.
+ *
+ * @return the distinct queryable
+ */
@Override
public Queryable<T> distinct() {
Stream<T> stream = this.stream().distinct();
@@ -372,6 +406,12 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
return from(stream);
}
+ /**
+ * Appends all elements from another queryable.
+ *
+ * @param queryable the other queryable
+ * @return the combined queryable
+ */
@Override
public Queryable<T> unionAll(Queryable<? extends T> queryable) {
Stream<T> stream = Stream.concat(this.stream(), queryable.stream());
@@ -379,6 +419,12 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
return from(stream);
}
+ /**
+ * Keeps only elements that also occur in the other queryable.
+ *
+ * @param queryable the other queryable
+ * @return the intersection
+ */
@Override
public Queryable<T> intersect(Queryable<? extends T> queryable) {
Stream<T> stream = this.stream().filter(a -> {
@@ -392,6 +438,12 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
return from(stream);
}
+ /**
+ * Removes elements that also occur in the other queryable.
+ *
+ * @param queryable the other queryable
+ * @return the difference
+ */
@Override
public Queryable<T> minus(Queryable<? extends T> queryable) {
Stream<T> stream = this.stream().filter(a -> {
@@ -406,6 +458,11 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
}
// ------------------------------ BEGIN AGGREGATE FUNCTIONS --------------------------------
+ /**
+ * Counts all elements.
+ *
+ * @return the number of elements
+ */
@Override
public Long count() {
return agg(q -> q.stream().count());
@@ -594,6 +651,11 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
.map(c -> tuple(p, c.original));
}
+ /**
+ * Materializes this queryable as a list.
+ *
+ * @return the materialized list
+ */
@Override
public List<T> toList() {
writeLock.lock();
@@ -611,11 +673,21 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
}
}
+ /**
+ * Counts the current elements.
+ *
+ * @return the number of elements
+ */
@Override
public long size() {
return stream().count();
}
+ /**
+ * Returns a reusable stream over the current elements.
+ *
+ * @return the element stream
+ */
@Override
public Stream<T> stream() {
writeLock.lock();
@@ -634,6 +706,14 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
}
}
+ /**
+ * Opens a window for the supplied current record.
+ *
+ * @param currentRecord the current record with its index
+ * @param windowDefinition the window definition
+ * @param <U> the order value type
+ * @return the window for the current record
+ */
@Override
public <U extends Comparable<? super U>> Window<T> over(Tuple2<T, Long> currentRecord, WindowDefinition<T, U> windowDefinition) {
@SuppressWarnings("unchecked")
@@ -750,6 +830,12 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
}
}
+ /**
+ * Coerces this queryable to a supported target type.
+ *
+ * @param clazz the requested target type
+ * @return the coerced value
+ */
public Object asType(Class<?> clazz) {
if (Queryable.class == clazz || QueryableCollection.class == clazz) {
return this;
@@ -799,6 +885,12 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
return DefaultGroovyMethods.asType(this, clazz);
}
+ /**
+ * Compares this collection with another queryable collection.
+ *
+ * @param o the other object
+ * @return {@code true} if both contain the same elements
+ */
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -806,11 +898,21 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
return toList().equals(that.toList());
}
+ /**
+ * Returns the hash code of the materialized contents.
+ *
+ * @return the hash code
+ */
@Override
public int hashCode() {
return Objects.hash(toList());
}
+ /**
+ * Returns the ASCII-table representation of this queryable.
+ *
+ * @return the string representation
+ */
@Override
public String toString() {
return AsciiTableMaker.makeAsciiTable(this);
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableHelper.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableHelper.groovy
index 1ffd8e21aa..40febc064b 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableHelper.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableHelper.groovy
@@ -85,30 +85,72 @@ class QueryableHelper {
throw new TooManyValuesException("subquery returns more than one value: $list")
}
+ /**
+ * Executes a supplier asynchronously on the shared thread pool.
+ *
+ * @param supplier the supplier to execute
+ * @return the asynchronous result
+ */
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
return CompletableFuture.supplyAsync(supplier, ThreadPoolHolder.THREAD_POOL)
}
+ /**
+ * Executes a single-argument function asynchronously on the shared thread pool.
+ *
+ * @param function the function to execute
+ * @param param the argument passed to the function
+ * @return the asynchronous result
+ */
static <T, U> CompletableFuture<U> supplyAsync(Function<? super T, ? extends U> function, T param) {
return CompletableFuture.supplyAsync(() -> { function.apply(param) }, ThreadPoolHolder.THREAD_POOL)
}
+ /**
+ * Submits work to the shared fork-join pool.
+ *
+ * @param callable the task to submit
+ * @return the submitted task
+ */
static <T> ForkJoinTask<T> submit(Callable<T> callable) {
return ThreadPoolHolder.FORKJOIN_POOL.submit(callable)
}
+ /**
+ * Indicates whether the current query is executing in parallel mode.
+ *
+ * @return {@code true} if parallel mode is enabled
+ */
static boolean isParallel() {
return TRUE_STR == getVar(PARALLEL)
}
+ /**
+ * Stores a named execution variable in the thread-local context.
+ *
+ * @param name the variable name
+ * @param value the variable value
+ */
static <T> void setVar(String name, T value) {
VAR_HOLDER.get().put(name, value)
}
+ /**
+ * Returns a named execution variable from the thread-local context.
+ *
+ * @param name the variable name
+ * @return the stored value
+ */
static <T> T getVar(String name) {
(T) VAR_HOLDER.get().get(name)
}
+ /**
+ * Removes a named execution variable from the thread-local context.
+ *
+ * @param name the variable name
+ * @return the removed value
+ */
static <T> T removeVar(String name) {
(T) VAR_HOLDER.get().remove(name)
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/SourceRecord.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/SourceRecord.groovy
index 12862cf731..3bde1e44b0 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/SourceRecord.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/SourceRecord.groovy
@@ -37,17 +37,35 @@ class SourceRecord<T> implements Serializable {
private final List<String> aliasList
private Map<String, Object> sourceRecordCache
+ /**
+ * Creates a source record wrapper for alias-based access.
+ *
+ * @param sourceRecord the underlying source record
+ * @param aliasList the aliases available for lookup
+ */
SourceRecord(T sourceRecord, List<String> aliasList) {
this.sourceRecord = sourceRecord
this.aliasList = aliasList
}
+ /**
+ * Returns the value associated with the supplied alias.
+ *
+ * @param name the alias name
+ * @return the resolved value
+ */
def getAt(String name) {
if (null == sourceRecordCache) sourceRecordCache = new HashMap<>(4)
return sourceRecordCache.computeIfAbsent(name, n -> findSourceRecordByName(n))
}
+ /**
+ * Returns the value associated with the supplied alias.
+ *
+ * @param name the alias name
+ * @return the resolved value
+ */
def get(String name) {
return getAt(name)
}
@@ -78,4 +96,4 @@ class SourceRecord<T> implements Serializable {
return accessPath
}
-}
\ No newline at end of file
+}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/TooManyValuesException.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/TooManyValuesException.java
index 1b35e46ff0..94e9bb886e 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/TooManyValuesException.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/TooManyValuesException.java
@@ -30,6 +30,11 @@ import java.io.Serial;
public class TooManyValuesException extends GroovyRuntimeException {
@Serial private static final long serialVersionUID = -2479599910868287387L;
+ /**
+ * Creates an exception for a sub-query that returned too many values.
+ *
+ * @param msg the error message
+ */
public TooManyValuesException(String msg) {
super(msg);
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinitionImpl.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinitionImpl.java
index 97b94811a6..a6f6636989 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinitionImpl.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowDefinitionImpl.java
@@ -36,44 +36,97 @@ class WindowDefinitionImpl<T, U extends Comparable<? super U>> implements Window
private final RowBound rows;
private final ValueBound<? extends U> range;
+ /**
+ * Creates a window definition with explicit partitioning, ordering, and bounds.
+ *
+ * @param partitionBy the partitioning function
+ * @param orderBy the ordering rules
+ * @param rows the row bounds
+ * @param range the range bounds
+ */
WindowDefinitionImpl(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy,
- RowBound rows, ValueBound<? extends U> range) {
+ RowBound rows, ValueBound<? extends U> range) {
this.partitionBy = partitionBy;
this.orderBy = orderBy;
this.rows = rows;
this.range = range;
}
+ /**
+ * Creates the default window definition.
+ */
WindowDefinitionImpl() {
this((T t) -> Queryable.NULL, Collections.emptyList(), RowBound.DEFAULT, null);
}
+ /**
+ * Creates a partitioned window definition.
+ *
+ * @param partitionBy the partitioning function
+ */
WindowDefinitionImpl(Function<? super T, ?> partitionBy) {
this(partitionBy, Collections.emptyList(), RowBound.DEFAULT, null);
}
+ /**
+ * Creates an ordered window definition.
+ *
+ * @param orderBy the ordering rules
+ */
WindowDefinitionImpl(List<Queryable.Order<? super T, ? extends U>> orderBy) {
this((T t) -> Queryable.NULL, orderBy, RowBound.DEFAULT, null);
}
+ /**
+ * Creates a partitioned and ordered window definition.
+ *
+ * @param partitionBy the partitioning function
+ * @param orderBy the ordering rules
+ */
WindowDefinitionImpl(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy) {
this(partitionBy, orderBy, RowBound.DEFAULT, null);
}
+ /**
+ * Creates an ordered window definition with row bounds.
+ *
+ * @param orderBy the ordering rules
+ * @param rows the row bounds
+ */
WindowDefinitionImpl(List<Queryable.Order<? super T, ? extends U>> orderBy, RowBound rows) {
this((T t) -> Queryable.NULL, orderBy, rows, null);
}
+ /**
+ * Creates a partitioned and ordered window definition with row bounds.
+ *
+ * @param partitionBy the partitioning function
+ * @param orderBy the ordering rules
+ * @param rows the row bounds
+ */
WindowDefinitionImpl(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy,
RowBound rows) {
this(partitionBy, orderBy, rows, null);
}
+ /**
+ * Creates a partitioned and ordered window definition with range bounds.
+ *
+ * @param partitionBy the partitioning function
+ * @param orderBy the ordering rules
+ * @param range the range bounds
+ */
WindowDefinitionImpl(Function<? super T, ?> partitionBy, List<Queryable.Order<? super T, ? extends U>> orderBy,
ValueBound<? extends U> range) {
this(partitionBy, orderBy, RowBound.DEFAULT, range);
}
+ /**
+ * Creates an ordered window definition with range bounds.
+ *
+ * @param orderBy the ordering rules
+ * @param range the range bounds
+ */
WindowDefinitionImpl(List<Queryable.Order<? super T, ? extends U>> orderBy, ValueBound<? extends U> range) {
this((T t) -> Queryable.NULL, orderBy, RowBound.DEFAULT, range);
}
@@ -88,27 +141,54 @@ class WindowDefinitionImpl<T, U extends Comparable<? super U>> implements Window
return orderBy;
}
+ /**
+ * Returns the row bounds for this window.
+ *
+ * @return the row bounds
+ */
@Override
public RowBound rows() {
return rows;
}
+ /**
+ * Returns the range bounds for this window.
+ *
+ * @return the range bounds
+ */
@Override
public ValueBound<? extends U> range() {
return range;
}
+ /**
+ * Returns the cached window-definition identifier.
+ *
+ * @return the identifier
+ */
@Override
public Object getId() {
return id;
}
+ /**
+ * Sets the cached window-definition identifier.
+ *
+ * @param id the identifier to set
+ * @return this definition
+ */
@Override
public WindowDefinition<T, U> setId(Object id) {
this.id = id;
return this;
}
+ /**
+ * Compares this definition with another one by identifier.
+ *
+ * @param o the other object
+ * @return {@code true} if both identifiers match
+ */
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -116,6 +196,11 @@ class WindowDefinitionImpl<T, U extends Comparable<? super U>> implements Window
return Objects.equals(id, that.id);
}
+ /**
+ * Returns the hash code of this definition identifier.
+ *
+ * @return the hash code
+ */
@Override
public int hashCode() {
return Objects.hash(id);
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
index 1de6912c76..27490ffaa8 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/WindowImpl.java
@@ -42,6 +42,15 @@ import static org.codehaus.groovy.runtime.typehandling.NumberMath.toBigDecimal;
*/
class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection<T> implements Window<T> {
+ /**
+ * Creates a window for the current record.
+ *
+ * @param currentRecord the current record and row index
+ * @param index the current zero-based row index
+ * @param value the current order value
+ * @param list the window contents
+ * @param order the order rule backing the window
+ */
WindowImpl(Tuple2<T, Long> currentRecord, int index, U value, List<T> list, Order<? super T, ? extends U> order) {
super(list);
this.currentRecord = currentRecord;
@@ -52,6 +61,11 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
this.list = list;
}
+ /**
+ * Returns the current row number inside the partition.
+ *
+ * @return the current row number
+ */
@Override
public long rowNumber() {
return index;
@@ -101,6 +115,11 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
return extractor.apply(list.get((int) index));
}
+ /**
+ * Returns the rank of the current row.
+ *
+ * @return the rank, or {@code null} when no ordering exists
+ */
@Override
public Long rank() {
if (null == order) {
@@ -118,6 +137,11 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
}
+ /**
+ * Returns the dense rank of the current row.
+ *
+ * @return the dense rank, or {@code null} when no ordering exists
+ */
@Override
public Long denseRank() {
if (null == order) {
@@ -135,6 +159,11 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
return result;
}
+ /**
+ * Returns the percent rank of the current row.
+ *
+ * @return the percent rank, or {@code null} when no ordering exists
+ */
@Override
public BigDecimal percentRank() {
if (null == order) {
@@ -154,6 +183,11 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
return toBigDecimal(r - 1).divide(toBigDecimal(size - 1), 16, RoundingMode.HALF_UP);
}
+ /**
+ * Returns the cumulative distribution of the current row.
+ *
+ * @return the cumulative distribution, or {@code null} when no ordering exists
+ */
@Override
public BigDecimal cumeDist() {
if (null == order) {
@@ -165,6 +199,12 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
return toBigDecimal(cnt).divide(toBigDecimal(list.size()), 16, RoundingMode.HALF_UP);
}
+ /**
+ * Assigns the current row to a bucket.
+ *
+ * @param bucketCnt the number of buckets
+ * @return the bucket number
+ */
@Override
public long ntile(long bucketCnt) {
return bucketCnt * rowNumber() / list.size();
@@ -182,6 +222,17 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
return null == upper || Long.MAX_VALUE == upper ? size - 1 : index + upper;
}
+ /**
+ * Resolves valid row bounds for the supplied window definition.
+ *
+ * @param windowDefinition the window definition
+ * @param index the current row index
+ * @param value the current order value
+ * @param listWithIndex the partition values with indexes
+ * @param <T> the row type
+ * @param <U> the order value type
+ * @return the effective row bounds, or {@code null} if none apply
+ */
static <T, U extends Comparable<? super U>> RowBound getValidRowBound(WindowDefinition<T, U> windowDefinition, int index, U value, List<Tuple2<T, Long>> listWithIndex) {
int size = listWithIndex.size();
long firstIndex = 0;
@@ -270,12 +321,28 @@ class WindowImpl<T, U extends Comparable<? super U>> extends QueryableCollection
return valueIndex;
}
+ /**
+ * Converts row orders into tuple-based orders.
+ *
+ * @param orderList the row orders
+ * @param <T> the row type
+ * @param <U> the order value type
+ * @return the tuple-based orders
+ */
static <T, U extends Comparable<? super U>> List<Order<Tuple2<T, Long>, U>> composeOrders(List<Queryable.Order<? super T, ? extends U>> orderList) {
return orderList.stream()
.map(order -> new Order<Tuple2<T, Long>, U>(t -> order.getKeyExtractor().apply(t.getV1()), order.isAsc(), order.isNullsLast()))
.collect(Collectors.toList());
}
+ /**
+ * Converts the orders of a window definition into tuple-based orders.
+ *
+ * @param windowDefinition the window definition
+ * @param <T> the row type
+ * @param <U> the order value type
+ * @return the tuple-based orders
+ */
static <T, U extends Comparable<? super U>> List<Order<Tuple2<T, Long>, U>> composeOrders(WindowDefinition<T, U> windowDefinition) {
return composeOrders(windowDefinition.orderBy());
}
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/transform/GinqASTTransformation.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/transform/GinqASTTransformation.java
index 7087ffb9e4..b8680cafc2 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/transform/GinqASTTransformation.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/transform/GinqASTTransformation.java
@@ -60,6 +60,12 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
*/
@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
public class GinqASTTransformation extends AbstractASTTransformation {
+ /**
+ * Rewrites annotated methods by replacing their bodies with transformed GINQ queries.
+ *
+ * @param nodes the transformation nodes
+ * @param sourceUnit the source unit being transformed
+ */
@Override
public void visit(ASTNode[] nodes, SourceUnit sourceUnit) {
init(nodes, sourceUnit);
diff --git a/subprojects/groovy-grape-ivy/src/main/groovy/groovy/grape/ivy/GrapeIvy.groovy b/subprojects/groovy-grape-ivy/src/main/groovy/groovy/grape/ivy/GrapeIvy.groovy
index 3ef2531c82..badb5950ea 100644
--- a/subprojects/groovy-grape-ivy/src/main/groovy/groovy/grape/ivy/GrapeIvy.groovy
+++ b/subprojects/groovy-grape-ivy/src/main/groovy/groovy/grape/ivy/GrapeIvy.groovy
@@ -76,17 +76,26 @@ class GrapeIvy implements GrapeEngine {
grabArgs.inject([:]) { Map m, List g -> g.each { a -> m[a] = (g - a) as Set }; m }
}
+ /** Enables or disables grape resolution. */
boolean enableGrapes = true
+ /** Active Ivy instance used for dependency resolution. */
Ivy ivyInstance
+ /** Ivy settings backing this engine. */
IvySettings settings
+ /** Artifact files downloaded during the last resolution. */
Set<String> downloadedArtifacts = []
+ /** Module revisions resolved during the last resolution. */
Set<String> resolvedDependencies = []
// weak hash map so we don't leak loaders directly
+ /** Dependencies loaded into each class loader. */
final Map<ClassLoader, Set<IvyGrabRecord>> loadedDeps = [] as WeakHashMap
/** Stores the IvyGrabRecord(s) for all dependencies in each grab() call. */
final Set<IvyGrabRecord> grabRecordsForCurrDependencies = [] as LinkedHashSet
+ /**
+ * Creates an Ivy-backed grape engine.
+ */
GrapeIvy() {
Message.setDefaultLogger(new PlatformLoggingMessageLogger())
@@ -110,6 +119,11 @@ class GrapeIvy implements GrapeEngine {
IvyContext.getContext().setIvy(ivyInstance)
}
+ /**
+ * Returns the configured Groovy home directory for grape state.
+ *
+ * @return the Groovy home directory
+ */
File getGroovyRoot() {
String root = System.getProperty('groovy.root')
def groovyRoot
@@ -126,6 +140,11 @@ class GrapeIvy implements GrapeEngine {
groovyRoot
}
+ /**
+ * Returns the root directory used by grape.
+ *
+ * @return the grape root directory
+ */
File getGrapeDir() {
String root = System.getProperty('grape.root')
if (root == null) {
@@ -140,6 +159,11 @@ class GrapeIvy implements GrapeEngine {
grapeRoot
}
+ /**
+ * Returns the cache directory used for downloaded artifacts.
+ *
+ * @return the grape cache directory
+ */
File getGrapeCacheDir() {
File cache = new File(getGrapeDir(), 'grapes')
if (!cache.exists()) {
@@ -150,6 +174,11 @@ class GrapeIvy implements GrapeEngine {
cache
}
+ /**
+ * Returns the local Ivy grape configuration file.
+ *
+ * @return the grape configuration file
+ */
File getLocalGrapeConfig() {
String grapeConfig = System.getProperty('grape.config')
if (grapeConfig) {
@@ -159,6 +188,12 @@ class GrapeIvy implements GrapeEngine {
}
}
+ /**
+ * Chooses the target class loader for a grab operation.
+ *
+ * @param args grab arguments
+ * @return the chosen class loader
+ */
ClassLoader chooseClassLoader(Map args) {
ClassLoader loader = (ClassLoader) args.classLoader
if (!isValidTargetClassLoader(loader)) {
@@ -207,6 +242,12 @@ class GrapeIvy implements GrapeEngine {
|| isValidTargetClassLoaderClass(loaderClass.getSuperclass()))
}
+ /**
+ * Converts dependency coordinates into an Ivy grab record.
+ *
+ * @param dep the dependency map
+ * @return the corresponding grab record
+ */
IvyGrabRecord createGrabRecord(Map dep) {
String module = dep.module ?: dep.artifactId ?: dep.artifact
if (!module) {
@@ -264,17 +305,35 @@ class GrapeIvy implements GrapeEngine {
conf
}
+ /**
+ * Grabs the endorsed module for the current Groovy version.
+ *
+ * @param endorsedModule the endorsed module name
+ */
@Override // TODO deprecate
grab(String endorsedModule) {
grab(group: 'groovy.endorsed', module: endorsedModule, version: GroovySystem.getVersion())
}
+ /**
+ * Grabs a dependency described by a single argument map.
+ *
+ * @param args the grab arguments
+ * @return the grab result or exception when suppressed
+ */
@Override
grab(Map args) {
args.calleeDepth = args.calleeDepth ?: DEFAULT_CALLEE_DEPTH + 1
grab(args, args)
}
+ /**
+ * Grabs one or more dependencies and adds them to the target class loader.
+ *
+ * @param args the shared grab arguments
+ * @param dependencies the dependency descriptors
+ * @return {@code null} on success or the suppressed exception
+ */
@Override
grab(Map args, Map... dependencies) {
ClassLoader loader = null
@@ -323,6 +382,13 @@ class GrapeIvy implements GrapeEngine {
null
}
+ /**
+ * Resolves the supplied grab records with Ivy.
+ *
+ * @param args the resolution arguments
+ * @param grabRecords the dependencies to resolve
+ * @return the Ivy resolve report
+ */
ResolveReport getDependencies(Map args, IvyGrabRecord... grabRecords) {
def cacheManager = ivyInstance.getResolutionCacheManager()
def millis = System.currentTimeMillis()
@@ -421,6 +487,13 @@ class GrapeIvy implements GrapeEngine {
}
}
+ /**
+ * Removes a cached artifact version from the grape cache.
+ *
+ * @param group the artifact group
+ * @param module the artifact module
+ * @param rev the artifact revision
+ */
void uninstallArtifact(String group, String module, String rev) {
// TODO: consider transitive uninstall as an option
Pattern ivyFilePattern = ~/ivy-(.*)\.xml/ // TODO: get pattern from ivy conf
@@ -477,6 +550,11 @@ class GrapeIvy implements GrapeEngine {
}
}
+ /**
+ * Enumerates cached grapes by group, module, and version.
+ *
+ * @return the cached grape coordinates
+ */
@Override
Map<String, Map<String, List<String>>> enumerateGrapes() {
Map<String, Map<String, List<String>>> bunches = [:]
@@ -496,11 +574,26 @@ class GrapeIvy implements GrapeEngine {
bunches
}
+ /**
+ * Resolves dependencies using the implicit target class loader.
+ *
+ * @param args the resolution arguments
+ * @param dependencies the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
@Override
URI[] resolve(Map args, Map... dependencies) {
resolve(args, null, dependencies)
}
+ /**
+ * Resolves dependencies and optionally collects dependency metadata.
+ *
+ * @param args the resolution arguments
+ * @param depsInfo the optional dependency metadata sink
+ * @param dependencies the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
@Override
URI[] resolve(Map args, List depsInfo, Map... dependencies) {
// identify the target classloader early, so we fail before checking repositories
@@ -519,10 +612,27 @@ class GrapeIvy implements GrapeEngine {
resolve(loader, args, depsInfo, dependencies)
}
+ /**
+ * Resolves dependencies for an explicit class loader.
+ *
+ * @param loader the target class loader
+ * @param args the resolution arguments
+ * @param dependencies the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
URI[] resolve(ClassLoader loader, Map args, Map... dependencies) {
resolve(loader, args, null, dependencies)
}
+ /**
+ * Resolves dependencies for an explicit class loader and optional metadata sink.
+ *
+ * @param loader the target class loader
+ * @param args the resolution arguments
+ * @param depsInfo the optional dependency metadata sink
+ * @param dependencies the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
URI[] resolve(ClassLoader loader, Map args, List depsInfo, Map... dependencies) {
// check the kill switch
if (!enableGrapes) {
@@ -575,6 +685,12 @@ class GrapeIvy implements GrapeEngine {
loadedDeps.computeIfAbsent(loader, k -> [] as LinkedHashSet)
}
+ /**
+ * Lists dependencies already loaded into the supplied class loader.
+ *
+ * @param classLoader the class loader to inspect
+ * @return the loaded dependency descriptors
+ */
@Override
Map[] listDependencies(ClassLoader classLoader) {
List<? extends Map> results = loadedDeps[classLoader]?.collect { IvyGrabRecord grabbed ->
@@ -609,6 +725,11 @@ class GrapeIvy implements GrapeEngine {
results as Map[]
}
+ /**
+ * Adds a resolver to the front of the Ivy resolver chain.
+ *
+ * @param args the resolver configuration
+ */
@Override
void addResolver(@NamedParams([
@NamedParam(value='name', type=String, required=true),
@@ -630,10 +751,21 @@ class GrapeIvy implements GrapeEngine {
downloadedArtifacts = []
}
+ /**
+ * Creates an Ivy listener from a progress closure.
+ *
+ * @param c the progress callback
+ * @return the corresponding Ivy listener
+ */
IvyListener makeIvyListener(Closure c) {
[progress: c] as IvyListener
}
+ /**
+ * Sets the Ivy logging verbosity.
+ *
+ * @param level the grape logging level
+ */
@Override
void setLoggingLevel(int level) {
// Map numeric level (from grape -q/-w/-i/-V/-d flags) to JUL level
@@ -663,15 +795,26 @@ class GrapeIvy implements GrapeEngine {
}
}
+/**
+ * Value object describing a grabbed Ivy dependency.
+ */
@CompileStatic
@EqualsAndHashCode
class IvyGrabRecord {
+ /** Ivy module revision coordinates. */
ModuleRevisionId mrid
+ /** Requested Ivy configurations. */
List<String> conf
+ /** Requested extension. */
String ext
+ /** Requested artifact type. */
String type
+ /** Requested classifier. */
String classifier
+ /** Whether this dependency is forced. */
boolean force
+ /** Whether this dependency may change over time. */
boolean changing
+ /** Whether transitive dependencies should be resolved. */
boolean transitive
}
diff --git a/subprojects/groovy-grape-ivy/src/main/java/groovy/grape/ivy/PlatformLoggingMessageLogger.java b/subprojects/groovy-grape-ivy/src/main/java/groovy/grape/ivy/PlatformLoggingMessageLogger.java
index 256deb611a..f9d5d8c6fe 100644
--- a/subprojects/groovy-grape-ivy/src/main/java/groovy/grape/ivy/PlatformLoggingMessageLogger.java
+++ b/subprojects/groovy-grape-ivy/src/main/java/groovy/grape/ivy/PlatformLoggingMessageLogger.java
@@ -48,6 +48,9 @@ class PlatformLoggingMessageLogger extends AbstractMessageLogger {
private static final String LOGGER_NAME = "groovy.grape.ivy";
private static final System.Logger LOGGER = System.getLogger(LOGGER_NAME);
+ /**
+ * Creates a message logger configured with a warning default level.
+ */
PlatformLoggingMessageLogger() {
// Default to WARNING to match the previous behaviour (DefaultMessageLogger
// at level -1 suppressed everything). Users can raise verbosity via
@@ -58,21 +61,41 @@ class PlatformLoggingMessageLogger extends AbstractMessageLogger {
}
}
+ /**
+ * Logs an Ivy message through platform logging.
+ *
+ * @param msg the message to log
+ * @param level the Ivy message level
+ */
@Override
public void log(String msg, int level) {
LOGGER.log(toSystemLevel(level), msg);
}
+ /**
+ * Logs a raw Ivy message through platform logging.
+ *
+ * @param msg the message to log
+ * @param level the Ivy message level
+ */
@Override
public void rawlog(String msg, int level) {
LOGGER.log(toSystemLevel(level), msg);
}
+ /**
+ * Ignores Ivy progress updates.
+ */
@Override
protected void doProgress() {
// no-op — progress dots are not useful in structured logging
}
+ /**
+ * Ends a progress section, logging the final message when present.
+ *
+ * @param msg the trailing progress message
+ */
@Override
protected void doEndProgress(String msg) {
if (msg != null && !msg.isEmpty()) {
diff --git a/subprojects/groovy-grape-maven/src/main/groovy/groovy/grape/maven/GrapeMaven.groovy b/subprojects/groovy-grape-maven/src/main/groovy/groovy/grape/maven/GrapeMaven.groovy
index 25ed449ca3..d7a4a9a2b9 100644
--- a/subprojects/groovy-grape-maven/src/main/groovy/groovy/grape/maven/GrapeMaven.groovy
+++ b/subprojects/groovy-grape-maven/src/main/groovy/groovy/grape/maven/GrapeMaven.groovy
@@ -99,15 +99,24 @@ class GrapeMaven implements GrapeEngine {
}
// weak hash map so we don't leak loaders directly
+ /** Dependencies loaded into each class loader. */
final Map<ClassLoader, Set<MavenGrabRecord>> loadedDeps = [] as WeakHashMap
/** Stores the MavenGrabRecord(s) for all dependencies in each grab() call. */
final Set<MavenGrabRecord> grabRecordsForCurrDependencies = [] as LinkedHashSet
+ /** Enables or disables grape resolution. */
boolean enableGrapes = true
+ /** Progress listeners notified during dependency resolution. */
final List<Closure> progressListeners = new CopyOnWriteArrayList<>()
+ /** Configured remote repositories in lookup order. */
final List<RemoteRepository> repos = [
new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2/").build()
]
+ /**
+ * Adds a progress listener for resolution events.
+ *
+ * @param listener the listener to add
+ */
@CompileDynamic
void addProgressListener(Closure listener) {
if (listener != null) {
@@ -115,6 +124,11 @@ class GrapeMaven implements GrapeEngine {
}
}
+ /**
+ * Removes a previously registered progress listener.
+ *
+ * @param listener the listener to remove
+ */
void removeProgressListener(Closure listener) {
progressListeners.remove(listener)
}
@@ -179,12 +193,25 @@ class GrapeMaven implements GrapeEngine {
grab(group: 'groovy.endorsed', module: endorsedModule, version: GroovySystem.getVersion())
}
+ /**
+ * Grabs a dependency described by a single argument map.
+ *
+ * @param args the grab arguments
+ * @return the grab result or exception when suppressed
+ */
@Override
grab(Map args) {
args.calleeDepth = args.calleeDepth ?: DEFAULT_CALLEE_DEPTH + 1
grab(args, args)
}
+ /**
+ * Grabs one or more dependencies and adds them to the target class loader.
+ *
+ * @param args the shared grab arguments
+ * @param dependencies the dependency descriptors
+ * @return {@code null} on success or the suppressed exception
+ */
@Override
grab(Map args, Map... dependencies) {
ClassLoader loader = null
@@ -234,6 +261,11 @@ class GrapeMaven implements GrapeEngine {
}
+ /**
+ * Enumerates cached grapes by group, module, and version.
+ *
+ * @return the cached grape coordinates
+ */
@Override
@CompileDynamic
Map<String, Map<String, List<String>>> enumerateGrapes() {
@@ -270,6 +302,13 @@ class GrapeMaven implements GrapeEngine {
bunches
}
+ /**
+ * Removes a cached artifact version from the grape cache.
+ *
+ * @param group the artifact group
+ * @param module the artifact module
+ * @param rev the artifact revision
+ */
void uninstallArtifact(String group, String module, String rev) {
String groupPath = group.replace('.' as char, File.separatorChar)
def artifactDir = new File(grapeCacheDir, groupPath + File.separator + module + File.separator + rev)
@@ -278,11 +317,26 @@ class GrapeMaven implements GrapeEngine {
}
}
+ /**
+ * Resolves dependencies using the implicit target class loader.
+ *
+ * @param args the resolution arguments
+ * @param dependencies the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
@Override
URI[] resolve(Map args, Map... dependencies) {
resolve(args, null, dependencies)
}
+ /**
+ * Resolves dependencies and optionally collects dependency metadata.
+ *
+ * @param args the resolution arguments
+ * @param depsInfo the optional dependency metadata sink
+ * @param dependencies the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
@Override
URI[] resolve(Map args, List depsInfo, Map... dependencies) {
// identify the target classloader early, so we fail before checking repositories
@@ -306,10 +360,27 @@ class GrapeMaven implements GrapeEngine {
loadedDeps.computeIfAbsent(loader, k -> [] as LinkedHashSet)
}
+ /**
+ * Resolves dependencies for an explicit class loader.
+ *
+ * @param loader the target class loader
+ * @param args the resolution arguments
+ * @param dependencies the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
URI[] resolve(ClassLoader loader, Map args, Map... dependencies) {
resolve(loader, args, null, dependencies)
}
+ /**
+ * Resolves dependencies for an explicit class loader and optional metadata sink.
+ *
+ * @param loader the target class loader
+ * @param args the resolution arguments
+ * @param depsInfo the optional dependency metadata sink
+ * @param dependencies the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
URI[] resolve(ClassLoader loader, Map args, List depsInfo, Map... dependencies) {
if (!enableGrapes) {
return new URI[0]
@@ -335,6 +406,14 @@ class GrapeMaven implements GrapeEngine {
}
}
+ /**
+ * Resolves the supplied grab records with Maven Resolver.
+ *
+ * @param args the resolution arguments
+ * @param depsInfo the optional dependency metadata sink
+ * @param grabRecords the dependencies to resolve
+ * @return the resolved artifact URIs
+ */
URI[] getDependencies(Map args, List depsInfo, MavenGrabRecord... grabRecords) {
try (RepositorySystem system = new RepositorySystemSupplier().get()) {
def localRepo = new LocalRepository(grapeCacheDir.toPath())
@@ -483,6 +562,12 @@ class GrapeMaven implements GrapeEngine {
return false
}
+ /**
+ * Converts dependency coordinates into a Maven grab record.
+ *
+ * @param dep the dependency map
+ * @return the corresponding grab record
+ */
static MavenGrabRecord createGrabRecord(Map dep) {
String module = dep.module ?: dep.artifactId ?: dep.artifact
if (!module) {
@@ -548,6 +633,12 @@ class GrapeMaven implements GrapeEngine {
(conf as List<String>)
}
+ /**
+ * Lists dependencies already loaded into the supplied class loader.
+ *
+ * @param classLoader the class loader to inspect
+ * @return the loaded dependency descriptors
+ */
@Override
Map[] listDependencies(ClassLoader classLoader) {
List<? extends Map> results = loadedDeps[classLoader]?.collect { MavenGrabRecord grabbed ->
@@ -582,6 +673,11 @@ class GrapeMaven implements GrapeEngine {
results as Map[]
}
+ /**
+ * Adds a repository resolver to the front of the repository list.
+ *
+ * @param args the resolver configuration
+ */
@Override
void addResolver(@NamedParams([
@NamedParam(value = 'name', type = String, required = true),
@@ -598,6 +694,11 @@ class GrapeMaven implements GrapeEngine {
repos.add(0, resolver)
}
+ /**
+ * Updates the logging level used by grape integrations.
+ *
+ * @param level the grape logging level
+ */
@Override
void setLoggingLevel(int level) {
// Maven Resolver uses SLF4J for logging, which is configured externally
@@ -606,6 +707,11 @@ class GrapeMaven implements GrapeEngine {
// Level mapping: 0=quiet/errors, 1=warn, 2=info, 3=verbose, 4=debug
}
+ /**
+ * Returns the configured Groovy home directory for grape state.
+ *
+ * @return the Groovy home directory
+ */
static File getGroovyRoot() {
String root = System.getProperty('groovy.root')
def groovyRoot
@@ -622,6 +728,11 @@ class GrapeMaven implements GrapeEngine {
groovyRoot
}
+ /**
+ * Returns the root directory used by grape.
+ *
+ * @return the grape root directory
+ */
static File getGrapeDir() {
String root = System.getProperty('grape.root')
if (root == null) {
@@ -636,6 +747,11 @@ class GrapeMaven implements GrapeEngine {
grapeRoot
}
+ /**
+ * Returns the cache directory used for downloaded artifacts.
+ *
+ * @return the grape cache directory
+ */
static File getGrapeCacheDir() {
String prefix = System.getProperty('grape.prefix') ?: 'grapesM2'
if (prefix.contains('/') || prefix.contains('\\')) {
@@ -762,6 +878,20 @@ class GrapeMaven implements GrapeEngine {
}
+/**
+ * Value object describing a grabbed Maven dependency.
+ *
+ * @param groupId the dependency group
+ * @param module the dependency module
+ * @param version the dependency version
+ * @param conf the requested configurations or scopes
+ * @param ext the requested extension
+ * @param type the requested artifact type
+ * @param classifier the requested classifier
+ * @param force whether this dependency is forced
+ * @param changing whether this dependency may change over time
+ * @param transitive whether transitive dependencies should be resolved
+ */
record MavenGrabRecord(
String groupId,
String module,
diff --git a/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy b/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy
index 650c6b08f1..72b7544739 100644
--- a/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy
+++ b/subprojects/groovy-groovydoc/src/main/groovy/org/codehaus/groovy/tools/groovydoc/Main.groovy
@@ -64,6 +64,11 @@ class Main {
private static List<String> remainingArgs
private static List<String> exclusions
+ /**
+ * Runs the {@code groovydoc} command-line entry point.
+ *
+ * @param args command-line arguments
+ */
static void main(final String[] args) {
IO io = new IO()
Logger.io = io
diff --git a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTemplateEngine.java b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTemplateEngine.java
index 6b545212e3..61e6c67c9a 100644
--- a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTemplateEngine.java
+++ b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTemplateEngine.java
@@ -86,6 +86,12 @@ public class GroovyDocTemplateEngine {
}
+ /**
+ * Applies the configured class template to the supplied class documentation model.
+ *
+ * @param classDoc class documentation to render
+ * @return rendered class documentation
+ */
String applyClassTemplates(GroovyClassDoc classDoc) {
String templatePath = classTemplatePaths.get(0); // todo (iterate)
String templateWithBindingApplied = "";
@@ -110,6 +116,13 @@ public class GroovyDocTemplateEngine {
return new StringWriter(65536);
}
+ /**
+ * Applies a package template to the supplied package documentation model.
+ *
+ * @param template template path to render
+ * @param packageDoc package documentation to render
+ * @return rendered package documentation
+ */
String applyPackageTemplate(String template, GroovyPackageDoc packageDoc) {
String templateWithBindingApplied = "";
try {
@@ -129,6 +142,13 @@ public class GroovyDocTemplateEngine {
return templateWithBindingApplied;
}
+ /**
+ * Applies a root-document template to the supplied root documentation model.
+ *
+ * @param template template path to render
+ * @param rootDoc root documentation to render
+ * @return rendered root documentation
+ */
String applyRootDocTemplate(String template, GroovyRootDoc rootDoc) {
String templateWithBindingApplied = "";
try {
@@ -148,14 +168,29 @@ public class GroovyDocTemplateEngine {
return templateWithBindingApplied;
}
+ /**
+ * Returns the configured class template paths.
+ *
+ * @return iterator over class template paths
+ */
Iterator<String> classTemplatesIterator() {
return classTemplatePaths.iterator();
}
+ /**
+ * Returns the configured package template paths.
+ *
+ * @return iterator over package template paths
+ */
Iterator<String> packageTemplatesIterator() {
return packageTemplatePaths.iterator();
}
+ /**
+ * Returns the configured top-level documentation template paths.
+ *
+ * @return iterator over documentation template paths
+ */
Iterator<String> docTemplatesIterator() {
return docTemplatePaths.iterator();
}
diff --git a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTool.java b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTool.java
index 671719d369..d79f125867 100644
--- a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTool.java
+++ b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/GroovyDocTool.java
@@ -40,6 +40,9 @@ public class GroovyDocTool {
private final GroovyDocTemplateEngine templateEngine;
private final String[] sourcepaths;
+ /**
+ * Rendering properties shared with the parser and template engine.
+ */
protected Properties properties;
/**
diff --git a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/TagRenderer.java b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/TagRenderer.java
index e03971bda8..95a74fec9a 100644
--- a/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/TagRenderer.java
+++ b/subprojects/groovy-groovydoc/src/main/java/org/codehaus/groovy/tools/groovydoc/TagRenderer.java
@@ -124,11 +124,23 @@ final class TagRenderer {
* tokenizer implementation can drive both.
*/
static final class Config {
+ /** Opening markup used for inline code fragments. */
final String codeOpen;
+ /** Closing markup used for inline code fragments. */
final String codeClose;
+ /** Whether the {@code @literal} inline tag should be recognized. */
final boolean literalEnabled;
+ /** Whether block tags should be collated into grouped sections. */
final boolean collateBlockTags;
+ /**
+ * Creates a rendering configuration for a specific documentation context.
+ *
+ * @param codeOpen opening markup for inline code
+ * @param codeClose closing markup for inline code
+ * @param literalEnabled whether the {@code @literal} inline tag should be recognized
+ * @param collateBlockTags whether block tags should be grouped by type
+ */
Config(String codeOpen, String codeClose, boolean literalEnabled, boolean collateBlockTags) {
this.codeOpen = codeOpen;
this.codeClose = codeClose;
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyCommands.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyCommands.groovy
index c1060278f0..7030a7685e 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyCommands.groovy
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyCommands.groovy
@@ -89,6 +89,14 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
'TOML' : 'groovy.toml.TomlSlurper',
]
+ /**
+ * Creates the Groovy-specific command registry for groovysh.
+ *
+ * @param engine shell execution engine
+ * @param workDir supplier for the current working directory
+ * @param printer terminal printer
+ * @param highlighter syntax highlighter used for previews
+ */
GroovyCommands(GroovyEngine engine, Supplier<Path> workDir, Printer printer, SyntaxHighlighter highlighter) {
this.engine = engine
this.printer = printer
@@ -113,21 +121,44 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
registerCommands(available)
}
+ /**
+ * Returns the short help text registered for the named command.
+ *
+ * @param command command name
+ * @return command summary lines
+ */
@Override
List<String> commandInfo(String command) {
commands[command].v4
}
+ /**
+ * Builds the detailed description for the selected command.
+ *
+ * @param args command arguments whose first element identifies the command
+ * @return command description metadata
+ */
@Override
CmdDesc commandDescription(List<String> args) {
String command = args?[0] ?: ''
commands[command].v3(command)
}
+ /**
+ * Returns the display name for this command registry.
+ *
+ * @return registry name
+ */
String name() {
'Groovy Commands'
}
+ /**
+ * Lists cached grapes or grabs the supplied dependency coordinates.
+ *
+ * @param input parsed command input
+ * @return always {@code null}
+ */
def grab(CommandInput input) {
if (!input.xargs()) {
return null
@@ -183,12 +214,22 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
return null
}
+ /**
+ * Clears the current buffer.
+ *
+ * @param input parsed command input
+ */
void reset(CommandInput input) {
checkArgCount(input, [0, 1])
if (maybePrintHelp(input, '/reset')) return
engine.reset()
}
+ /**
+ * Saves shared state or the current buffer to disk.
+ *
+ * @param input parsed command input
+ */
void save(CommandInput input) {
checkArgCount(input, [0, 1, 2])
if (maybePrintHelp(input, '/save')) return
@@ -206,6 +247,13 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
saveFile(engine, workDir.get().resolve(arg).toFile(), overwrite)
}
+ /**
+ * Writes the current buffer to the target file.
+ *
+ * @param engine shell execution engine
+ * @param file target file
+ * @param overwrite whether existing files may be replaced
+ */
static void saveFile(GroovyEngine engine, File file, boolean overwrite = false) {
if (!file && overwrite) {
throw new IllegalArgumentException('File to overwrite not found: ' + file.path)
@@ -217,6 +265,11 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
println "Saved: " + file.path
}
+ /**
+ * Restores saved state or loads a file into the current buffer.
+ *
+ * @param input parsed command input
+ */
void load(CommandInput input) {
checkArgCount(input, [0, 1, 2])
if (maybePrintHelp(input, '/load')) return
@@ -245,6 +298,12 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
opts[key]
}
+ /**
+ * Opens configured documentation for the supplied object or type.
+ *
+ * @param input parsed command input
+ * @return always {@code null}
+ */
def doc(CommandInput input) {
def usage = new String[]{
"/doc - open document on browser",
@@ -341,6 +400,12 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
}
}
+ /**
+ * Reads content into {@code _} from a file, URL, or literal value.
+ *
+ * @param input parsed command input
+ * @return the parsed value
+ */
def slurpcmd(CommandInput input) {
checkArgCount(input, [0, 1, 2, 3, 4])
if (maybePrintHelp(input, '/slurp')) return
@@ -459,6 +524,13 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
throw new IllegalArgumentException("CSV format requires $GROOVY_CSV_SLURPER or $COMMONS_CSV_FORMAT to be available")
}
+ /**
+ * Creates the parser implementation backing a named slurper format.
+ *
+ * @param format user-facing format name
+ * @param parserName parser class name
+ * @return parser instance
+ */
Object getParser(String format, String parserName) {
if (!ClassUtils.lookFor(parserName)) {
throw new IllegalArgumentException("$format format requires $parserName to be available")
@@ -466,6 +538,13 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
engine.execute("new ${parserName}()")
}
+ /**
+ * Replays file contents through the engine, optionally merging with existing state.
+ *
+ * @param engine shell execution engine
+ * @param file source file to load
+ * @param merge whether existing state should be preserved
+ */
static void loadFile(GroovyEngine engine, File file, boolean merge = false) {
if (!file) {
throw new IllegalArgumentException('File not found: ' + file.path)
@@ -528,6 +607,11 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
}
}
+ /**
+ * Lists or removes import statements tracked by the shell.
+ *
+ * @param input parsed command input
+ */
void importsCommand(CommandInput input) {
checkArgCount(input, [0, 1, 2])
if (maybePrintHelp(input, '/imports')) return
@@ -540,6 +624,11 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
}
}
+ /**
+ * Lists or removes tracked type declarations.
+ *
+ * @param input parsed command input
+ */
void typesCommand(CommandInput input) {
checkArgCount(input, [0, 1, 2])
if (maybePrintHelp(input, '/types')) return
@@ -552,6 +641,11 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
}
}
+ /**
+ * Lists or removes tracked variable declarations.
+ *
+ * @param input parsed command input
+ */
void varsCommand(CommandInput input) {
checkArgCount(input, [0, 1, 2])
if (maybePrintHelp(input, '/vars')) return
@@ -564,6 +658,11 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
}
}
+ /**
+ * Lists or removes tracked method definitions.
+ *
+ * @param input parsed command input
+ */
void methodsCommand(CommandInput input) {
checkArgCount(input, [0, 1, 2])
if (maybePrintHelp(input, '/methods')) return
@@ -576,6 +675,11 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
}
}
+ /**
+ * Launches the Swing Groovy console seeded with the current shell state.
+ *
+ * @param input parsed command input
+ */
void console(CommandInput input) {
checkArgCount(input, [0, 1])
if (maybePrintHelp(input, '/console')) return
@@ -591,6 +695,12 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry {
c.run()
}
+ /**
+ * Displays object details in the terminal or object browser.
+ *
+ * @param input parsed command input
+ * @return always {@code null}
+ */
def inspect(CommandInput input) {
checkArgCount(input, [1, 2])
if (maybePrintHelp(input, '/inspect')) return
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyPosixCommands.java b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyPosixCommands.java
index 57885e5436..84a1360a90 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyPosixCommands.java
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyPosixCommands.java
@@ -451,9 +451,15 @@ public class GroovyPosixCommands {
Map<String, String> colors =
colored ? (colorMap != null ? colorMap : getLsColorMap(DEFAULT_LS_COLORS)) : Collections.emptyMap();
+ /**
+ * Represents one path selected for listing output.
+ */
class PathEntry implements Comparable<PathEntry> {
+ /** Absolute path resolved for the entry. */
final Path abs;
+ /** Path shown to the user, relative to the requested root when possible. */
final Path path;
+ /** File attributes used for sorting and formatting. */
final Map<String, Object> attributes;
/**
@@ -474,6 +480,12 @@ public class GroovyPosixCommands {
this.attributes = readAttributes(abs);
}
+ /**
+ * Orders entries using the active {@code ls} sort options.
+ *
+ * @param o entry to compare against
+ * @return sort order for this entry
+ */
@Override
public int compareTo(PathEntry o) {
int c = doCompare(o);
@@ -501,10 +513,20 @@ public class GroovyPosixCommands {
return path.toString().compareTo(o.path.toString());
}
+ /**
+ * Returns whether this entry should be rendered as a non-directory item.
+ *
+ * @return {@code true} when the entry is not a directory
+ */
boolean isNotDirectory() {
return is("isRegularFile") || is("isSymbolicLink") || is("isOther");
}
+ /**
+ * Returns whether this entry is a directory.
+ *
+ * @return {@code true} when the entry is a directory
+ */
boolean isDirectory() {
return is("isDirectory");
}
@@ -514,6 +536,11 @@ public class GroovyPosixCommands {
return d instanceof Boolean && (Boolean) d;
}
+ /**
+ * Formats the entry name for standard listing output.
+ *
+ * @return formatted entry name
+ */
String display() {
String type;
String suffix;
@@ -544,6 +571,11 @@ public class GroovyPosixCommands {
return applyStyle(path.toString(), colors, type) + (addSuffix ? suffix : "") + link;
}
+ /**
+ * Formats the entry for long-listing output.
+ *
+ * @return formatted long-listing entry
+ */
String longDisplay() {
String username = Objects.toString(attributes.get("owner"), "owner");
String group = Objects.toString(attributes.get("group"), "group");
diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/SystemRegistryImpl.java b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/SystemRegistryImpl.java
index 7473c1ffab..f05cb65785 100644
--- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/SystemRegistryImpl.java
+++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/SystemRegistryImpl.java
@@ -1596,6 +1596,13 @@ public class SystemRegistryImpl implements SystemRegistry {
return out;
}
+ /**
+ * Executes a command line, including pipes, redirection, and console statements.
+ *
+ * @param line command line to execute
+ * @return command result, if any
+ * @throws Exception if command execution fails
+ */
@Override
public Object execute(String line) throws Exception {
if (line.trim().isEmpty() || line.trim().startsWith("#")) {
@@ -1731,6 +1738,11 @@ public class SystemRegistryImpl implements SystemRegistry {
}
}
+ /**
+ * Reports an exception using the configured console-aware tracing strategy.
+ *
+ * @param exception exception to report
+ */
@Override
public void trace(Throwable exception) {
outputStream.close();
@@ -1745,6 +1757,12 @@ public class SystemRegistryImpl implements SystemRegistry {
}
}
+ /**
+ * Reports an exception, optionally printing its full stack trace.
+ *
+ * @param stack whether to print the full stack trace
+ * @param exception exception to report
+ */
@Override
public void trace(boolean stack, Throwable exception) {
if (exception instanceof HelpException) {
@@ -1771,6 +1789,9 @@ public class SystemRegistryImpl implements SystemRegistry {
}
}
+ /**
+ * Persists collected command names before shutdown.
+ */
@Override
public void close() {
names.save();
diff --git a/subprojects/groovy-http-builder/src/main/java/groovy/http/Header.java b/subprojects/groovy-http-builder/src/main/java/groovy/http/Header.java
index 864532df64..c5c4104c5c 100644
--- a/subprojects/groovy-http-builder/src/main/java/groovy/http/Header.java
+++ b/subprojects/groovy-http-builder/src/main/java/groovy/http/Header.java
@@ -37,6 +37,17 @@ import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD})
@Repeatable(Headers.class)
public @interface Header {
+ /**
+ * Returns the header name.
+ *
+ * @return header name
+ */
String name();
+
+ /**
+ * Returns the header value.
+ *
+ * @return header value
+ */
String value();
}
diff --git a/subprojects/groovy-http-builder/src/main/java/groovy/http/Headers.java b/subprojects/groovy-http-builder/src/main/java/groovy/http/Headers.java
index c76a0566e5..5b78b77896 100644
--- a/subprojects/groovy-http-builder/src/main/java/groovy/http/Headers.java
+++ b/subprojects/groovy-http-builder/src/main/java/groovy/http/Headers.java
@@ -31,5 +31,10 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Headers {
+ /**
+ * Returns the repeated {@link Header} declarations.
+ *
+ * @return contained header annotations
+ */
Header[] value();
}
diff --git a/subprojects/groovy-jmx/src/main/java/groovy/jmx/builder/JmxBuilderModelMBean.java b/subprojects/groovy-jmx/src/main/java/groovy/jmx/builder/JmxBuilderModelMBean.java
index 040a4db70d..b31adb1f61 100644
--- a/subprojects/groovy-jmx/src/main/java/groovy/jmx/builder/JmxBuilderModelMBean.java
+++ b/subprojects/groovy-jmx/src/main/java/groovy/jmx/builder/JmxBuilderModelMBean.java
@@ -207,6 +207,11 @@ public class JmxBuilderModelMBean extends RequiredModelMBean implements Notifica
private static final class NumberSequencer {
private static final AtomicLong NUM = new AtomicLong(0);
+ /**
+ * Returns the next notification sequence number.
+ *
+ * @return the next sequence number
+ */
public static long getNextSequence() {
return NUM.incrementAndGet();
}
@@ -236,6 +241,12 @@ public class JmxBuilderModelMBean extends RequiredModelMBean implements Notifica
private AttributeChangedListener() {
}
+ /**
+ * Dispatches an attribute-change notification to the configured callback closure.
+ *
+ * @param notification the attribute-change notification to process
+ * @param handback the listener descriptor containing callback metadata
+ */
@Override
public void handleNotification(Notification notification, Object handback) {
AttributeChangeNotification note = (AttributeChangeNotification) notification;
diff --git a/subprojects/groovy-jmx/src/main/java/groovy/jmx/builder/JmxEventEmitter.java b/subprojects/groovy-jmx/src/main/java/groovy/jmx/builder/JmxEventEmitter.java
index 5f2f494828..1177632162 100644
--- a/subprojects/groovy-jmx/src/main/java/groovy/jmx/builder/JmxEventEmitter.java
+++ b/subprojects/groovy-jmx/src/main/java/groovy/jmx/builder/JmxEventEmitter.java
@@ -102,6 +102,11 @@ public class JmxEventEmitter extends NotificationBroadcasterSupport implements J
private static final class NumberSequencer {
private static final AtomicLong NUM = new AtomicLong(0);
+ /**
+ * Returns the next notification sequence number.
+ *
+ * @return the next sequence number
+ */
public static long getNextSequence() {
return NUM.incrementAndGet();
}
diff --git a/subprojects/groovy-jsr223/src/main/java/org/codehaus/groovy/jsr223/GroovyScriptEngineImpl.java b/subprojects/groovy-jsr223/src/main/java/org/codehaus/groovy/jsr223/GroovyScriptEngineImpl.java
index 9d5d167eef..2d3cf4fed9 100644
--- a/subprojects/groovy-jsr223/src/main/java/org/codehaus/groovy/jsr223/GroovyScriptEngineImpl.java
+++ b/subprojects/groovy-jsr223/src/main/java/org/codehaus/groovy/jsr223/GroovyScriptEngineImpl.java
@@ -333,6 +333,12 @@ public class GroovyScriptEngineImpl extends AbstractScriptEngine implements Comp
* will be done in the current ScriptContext instance.
*/
Binding binding = new Binding(ctx.getBindings(ScriptContext.ENGINE_SCOPE)) {
+ /**
+ * Resolves a script variable from the current JSR-223 context.
+ *
+ * @param name the variable name to resolve
+ * @return the resolved value
+ */
@Override
public Object getVariable(String name) {
synchronized (ctx) {
@@ -357,6 +363,12 @@ public class GroovyScriptEngineImpl extends AbstractScriptEngine implements Comp
throw new MissingPropertyException(name, getClass());
}
+ /**
+ * Stores a script variable back into the current JSR-223 context.
+ *
+ * @param name the variable name to update
+ * @param value the value to store
+ */
@Override
public void setVariable(String name, Object value) {
synchronized (ctx) {
@@ -388,11 +400,19 @@ public class GroovyScriptEngineImpl extends AbstractScriptEngine implements Comp
MetaClass oldMetaClass = scriptObject.getMetaClass();
/*
- * We override the MetaClass of this script object so that we can
- * forward calls to global closures (of previous or future "eval" calls)
- * This gives the illusion of working on the same "global" scope.
- */
+ * We override the MetaClass of this script object so that we can
+ * forward calls to global closures (of previous or future "eval" calls)
+ * This gives the illusion of working on the same "global" scope.
+ */
scriptObject.setMetaClass(new DelegatingMetaClass(oldMetaClass) {
+ /**
+ * Normalizes Groovy call arguments before delegating to the array-based overload.
+ *
+ * @param object the invocation receiver
+ * @param name the method name
+ * @param args the original Groovy argument payload
+ * @return the invocation result
+ */
@Override
public Object invokeMethod(Object object, String name, Object args) {
if (args == null) {
@@ -408,6 +428,14 @@ public class GroovyScriptEngineImpl extends AbstractScriptEngine implements Comp
}
}
+ /**
+ * Invokes an instance method and falls back to a cached global closure when needed.
+ *
+ * @param object the invocation receiver
+ * @param name the method name
+ * @param args the invocation arguments
+ * @return the invocation result
+ */
@Override
public Object invokeMethod(Object object, String name, Object[] args) {
try {
@@ -417,6 +445,14 @@ public class GroovyScriptEngineImpl extends AbstractScriptEngine implements Comp
}
}
+ /**
+ * Invokes a static method and falls back to a cached global closure when needed.
+ *
+ * @param object the invocation receiver
+ * @param name the method name
+ * @param args the invocation arguments
+ * @return the invocation result
+ */
@Override
public Object invokeStaticMethod(Object object, String name, Object[] args) {
try {
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTFinder.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTFinder.java
index a3eb1013be..6b8d83ba53 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTFinder.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTFinder.java
@@ -101,6 +101,11 @@ class ASTFinder extends ContextualClassCodeVisitor {
this.initial = initial;
}
+ /**
+ * Returns no source unit because pattern finding is source-independent.
+ *
+ * @return {@code null}
+ */
@Override
protected SourceUnit getSourceUnit() {
return null;
@@ -121,348 +126,406 @@ class ASTFinder extends ContextualClassCodeVisitor {
}
}
+ /** Visits a class node and records it when it matches the pattern. */
@Override
public void visitClass(final ClassNode node) {
super.visitClass(node);
tryFind(ClassNode.class, node);
}
+ /** Visits a package node and records it when it matches the pattern. */
@Override
public void visitPackage(final PackageNode node) {
super.visitPackage(node);
tryFind(PackageNode.class, node);
}
+ /** Visits module imports and records them when they match the pattern. */
@Override
public void visitImports(final ModuleNode node) {
super.visitImports(node);
tryFind(ModuleNode.class, node);
}
+ /** Visits a declaration expression and records it when it matches the pattern. */
@Override
public void visitDeclarationExpression(final DeclarationExpression expression) {
super.visitDeclarationExpression(expression);
tryFind(DeclarationExpression.class, expression);
}
+ /** Visits a constructor or method and records it when it matches the pattern. */
@Override
protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
super.visitConstructorOrMethod(node, isConstructor);
tryFind(MethodNode.class, node);
}
+ /** Visits a field node and records it when it matches the pattern. */
@Override
public void visitField(final FieldNode node) {
super.visitField(node);
tryFind(FieldNode.class, node);
}
+ /** Visits a property node and records it when it matches the pattern. */
@Override
public void visitProperty(final PropertyNode node) {
super.visitProperty(node);
tryFind(PropertyNode.class, node);
}
+ /** Visits an assert statement and records it when it matches the pattern. */
@Override
public void visitAssertStatement(final AssertStatement statement) {
super.visitAssertStatement(statement);
tryFind(AssertStatement.class, statement);
}
+ /** Visits a break statement and records it when it matches the pattern. */
@Override
public void visitBreakStatement(final BreakStatement statement) {
super.visitBreakStatement(statement);
tryFind(BreakStatement.class, statement);
}
+ /** Visits a case statement and records it when it matches the pattern. */
@Override
public void visitCaseStatement(final CaseStatement statement) {
super.visitCaseStatement(statement);
tryFind(CaseStatement.class, statement);
}
+ /** Visits a catch statement and records it when it matches the pattern. */
@Override
public void visitCatchStatement(final CatchStatement statement) {
super.visitCatchStatement(statement);
tryFind(CatchStatement.class, statement);
}
+ /** Visits a continue statement and records it when it matches the pattern. */
@Override
public void visitContinueStatement(final ContinueStatement statement) {
super.visitContinueStatement(statement);
tryFind(ContinueStatement.class, statement);
}
+ /** Visits a do-while loop and records it when it matches the pattern. */
@Override
public void visitDoWhileLoop(final DoWhileStatement loop) {
super.visitDoWhileLoop(loop);
tryFind(DoWhileStatement.class, loop);
}
+ /** Visits an expression statement and records it when it matches the pattern. */
@Override
public void visitExpressionStatement(final ExpressionStatement statement) {
super.visitExpressionStatement(statement);
tryFind(ExpressionStatement.class, statement);
}
+ /** Visits a for loop and records it when it matches the pattern. */
@Override
public void visitForLoop(final ForStatement forLoop) {
super.visitForLoop(forLoop);
tryFind(ForStatement.class, forLoop);
}
+ /** Visits an if/else statement and records it when it matches the pattern. */
@Override
public void visitIfElse(final IfStatement ifElse) {
super.visitIfElse(ifElse);
tryFind(IfStatement.class, ifElse);
}
+ /** Visits a return statement and records it when it matches the pattern. */
@Override
public void visitReturnStatement(final ReturnStatement statement) {
super.visitReturnStatement(statement);
tryFind(ReturnStatement.class, statement);
}
+ /** Visits a switch statement and records it when it matches the pattern. */
@Override
public void visitSwitch(final SwitchStatement statement) {
super.visitSwitch(statement);
tryFind(SwitchStatement.class, statement);
}
+ /** Visits a synchronized statement and records it when it matches the pattern. */
@Override
public void visitSynchronizedStatement(final SynchronizedStatement statement) {
super.visitSynchronizedStatement(statement);
tryFind(SynchronizedStatement.class, statement);
}
+ /** Visits a throw statement and records it when it matches the pattern. */
@Override
public void visitThrowStatement(final ThrowStatement statement) {
super.visitThrowStatement(statement);
tryFind(ThrowStatement.class, statement);
}
+ /** Visits a try/catch/finally statement and records it when it matches the pattern. */
@Override
public void visitTryCatchFinally(final TryCatchStatement statement) {
super.visitTryCatchFinally(statement);
tryFind(TryCatchStatement.class, statement);
}
+ /** Visits a while loop and records it when it matches the pattern. */
@Override
public void visitWhileLoop(final WhileStatement loop) {
super.visitWhileLoop(loop);
tryFind(WhileStatement.class, loop);
}
+ /** Visits a block statement and records it when it matches the pattern. */
@Override
public void visitBlockStatement(final BlockStatement block) {
super.visitBlockStatement(block);
tryFind(BlockStatement.class, block);
}
+ /** Visits an empty statement and records it when it matches the pattern. */
@Override
public void visitEmptyStatement(final EmptyStatement statement) {
super.visitEmptyStatement(statement);
tryFind(EmptyStatement.class, statement);
}
+ /** Visits a method call expression and records it when it matches the pattern. */
@Override
public void visitMethodCallExpression(final MethodCallExpression call) {
super.visitMethodCallExpression(call);
tryFind(MethodCallExpression.class, call);
}
+ /** Visits a static method call expression and records it when it matches the pattern. */
@Override
public void visitStaticMethodCallExpression(final StaticMethodCallExpression call) {
super.visitStaticMethodCallExpression(call);
tryFind(StaticMethodCallExpression.class, call);
}
+ /** Visits a constructor call expression and records it when it matches the pattern. */
@Override
public void visitConstructorCallExpression(final ConstructorCallExpression call) {
super.visitConstructorCallExpression(call);
tryFind(ConstructorCallExpression.class, call);
}
+ /** Visits a binary expression and records it when it matches the pattern. */
@Override
public void visitBinaryExpression(final BinaryExpression expression) {
super.visitBinaryExpression(expression);
tryFind(BinaryExpression.class, expression);
}
+ /** Visits a ternary expression and records it when it matches the pattern. */
@Override
public void visitTernaryExpression(final TernaryExpression expression) {
super.visitTernaryExpression(expression);
tryFind(TernaryExpression.class, expression);
}
+ /** Visits an Elvis expression and records it when it matches the pattern. */
@Override
public void visitShortTernaryExpression(final ElvisOperatorExpression expression) {
super.visitShortTernaryExpression(expression);
tryFind(ElvisOperatorExpression.class, expression);
}
+ /** Visits a postfix expression and records it when it matches the pattern. */
@Override
public void visitPostfixExpression(final PostfixExpression expression) {
super.visitPostfixExpression(expression);
tryFind(PostfixExpression.class, expression);
}
+ /** Visits a prefix expression and records it when it matches the pattern. */
@Override
public void visitPrefixExpression(final PrefixExpression expression) {
super.visitPrefixExpression(expression);
tryFind(PrefixExpression.class, expression);
}
+ /** Visits a boolean expression and records it when it matches the pattern. */
@Override
public void visitBooleanExpression(final BooleanExpression expression) {
super.visitBooleanExpression(expression);
tryFind(BooleanExpression.class, expression);
}
+ /** Visits a not expression and records it when it matches the pattern. */
@Override
public void visitNotExpression(final NotExpression expression) {
super.visitNotExpression(expression);
tryFind(NotExpression.class, expression);
}
+ /** Visits a closure expression and records it when it matches the pattern. */
@Override
public void visitClosureExpression(final ClosureExpression expression) {
super.visitClosureExpression(expression);
tryFind(ClosureExpression.class, expression);
}
+ /** Visits a tuple expression and records it when it matches the pattern. */
@Override
public void visitTupleExpression(final TupleExpression expression) {
super.visitTupleExpression(expression);
tryFind(TupleExpression.class, expression);
}
+ /** Visits a list expression and records it when it matches the pattern. */
@Override
public void visitListExpression(final ListExpression expression) {
super.visitListExpression(expression);
tryFind(ListExpression.class, expression);
}
+ /** Visits an array expression and records it when it matches the pattern. */
@Override
public void visitArrayExpression(final ArrayExpression expression) {
super.visitArrayExpression(expression);
tryFind(ArrayExpression.class, expression);
}
+ /** Visits a map expression and records it when it matches the pattern. */
@Override
public void visitMapExpression(final MapExpression expression) {
super.visitMapExpression(expression);
tryFind(MapExpression.class, expression);
}
+ /** Visits a map entry expression and records it when it matches the pattern. */
@Override
public void visitMapEntryExpression(final MapEntryExpression expression) {
super.visitMapEntryExpression(expression);
tryFind(MapEntryExpression.class, expression);
}
+ /** Visits a range expression and records it when it matches the pattern. */
@Override
public void visitRangeExpression(final RangeExpression expression) {
super.visitRangeExpression(expression);
tryFind(RangeExpression.class, expression);
}
+ /** Visits a spread expression and records it when it matches the pattern. */
@Override
public void visitSpreadExpression(final SpreadExpression expression) {
super.visitSpreadExpression(expression);
tryFind(SpreadExpression.class, expression);
}
+ /** Visits a spread-map expression and records it when it matches the pattern. */
@Override
public void visitSpreadMapExpression(final SpreadMapExpression expression) {
super.visitSpreadMapExpression(expression);
tryFind(SpreadMapExpression.class, expression);
}
+ /** Visits a method-pointer expression and records it when it matches the pattern. */
@Override
public void visitMethodPointerExpression(final MethodPointerExpression expression) {
super.visitMethodPointerExpression(expression);
tryFind(MethodPointerExpression.class, expression);
}
+ /** Visits a unary-minus expression and records it when it matches the pattern. */
@Override
public void visitUnaryMinusExpression(final UnaryMinusExpression expression) {
super.visitUnaryMinusExpression(expression);
tryFind(UnaryMinusExpression.class, expression);
}
+ /** Visits a unary-plus expression and records it when it matches the pattern. */
@Override
public void visitUnaryPlusExpression(final UnaryPlusExpression expression) {
super.visitUnaryPlusExpression(expression);
tryFind(UnaryPlusExpression.class, expression);
}
+ /** Visits a bitwise-negation expression and records it when it matches the pattern. */
@Override
public void visitBitwiseNegationExpression(final BitwiseNegationExpression expression) {
super.visitBitwiseNegationExpression(expression);
tryFind(BitwiseNegationExpression.class, expression);
}
+ /** Visits a cast expression and records it when it matches the pattern. */
@Override
public void visitCastExpression(final CastExpression expression) {
super.visitCastExpression(expression);
tryFind(CastExpression.class, expression);
}
+ /** Visits a constant expression and records it when it matches the pattern. */
@Override
public void visitConstantExpression(final ConstantExpression expression) {
super.visitConstantExpression(expression);
tryFind(ConstantExpression.class, expression);
}
+ /** Visits a class expression and records it when it matches the pattern. */
@Override
public void visitClassExpression(final ClassExpression expression) {
super.visitClassExpression(expression);
tryFind(ClassExpression.class, expression);
}
+ /** Visits a variable expression and records it when it matches the pattern. */
@Override
public void visitVariableExpression(final VariableExpression expression) {
super.visitVariableExpression(expression);
tryFind(VariableExpression.class, expression);
}
+ /** Visits a property expression and records it when it matches the pattern. */
@Override
public void visitPropertyExpression(final PropertyExpression expression) {
super.visitPropertyExpression(expression);
tryFind(PropertyExpression.class, expression);
}
+ /** Visits an attribute expression and records it when it matches the pattern. */
@Override
public void visitAttributeExpression(final AttributeExpression expression) {
super.visitAttributeExpression(expression);
tryFind(AttributeExpression.class, expression);
}
+ /** Visits a field expression and records it when it matches the pattern. */
@Override
public void visitFieldExpression(final FieldExpression expression) {
super.visitFieldExpression(expression);
tryFind(FieldExpression.class, expression);
}
+ /** Visits a GString expression and records it when it matches the pattern. */
@Override
public void visitGStringExpression(final GStringExpression expression) {
super.visitGStringExpression(expression);
tryFind(GStringExpression.class, expression);
}
+ /** Visits an argument-list expression and records it when it matches the pattern. */
@Override
public void visitArgumentlistExpression(final ArgumentListExpression ale) {
super.visitArgumentlistExpression(ale);
tryFind(ArgumentListExpression.class, ale);
}
+ /** Visits a closure-list expression and records it when it matches the pattern. */
@Override
public void visitClosureListExpression(final ClosureListExpression cle) {
super.visitClosureListExpression(cle);
tryFind(ClosureListExpression.class, cle);
}
+ /** Visits a bytecode expression and records it when it matches the pattern. */
@Override
public void visitBytecodeExpression(final BytecodeExpression cle) {
super.visitBytecodeExpression(cle);
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
index 39d178c466..c6b85acb90 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
@@ -92,6 +92,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
private ASTMatcher() {
}
+ /** Returns no source unit because AST matching is source-independent. */
@Override
protected SourceUnit getSourceUnit() {
}
@@ -226,6 +227,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a class node against the current candidate. */
@Override
void visitClass(ClassNode node) {
doWithNode(node, current) {
@@ -297,6 +299,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches object initializer statements for the current class candidate. */
@Override
protected void visitObjectInitializerStatements(ClassNode node) {
doWithNode(node, current) {
@@ -314,6 +317,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a package node against the current candidate. */
@Override
void visitPackage(PackageNode node) {
if (node) {
@@ -324,6 +328,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches module imports against the current candidate. */
@Override
void visitImports(ModuleNode node) {
if (node) {
@@ -382,6 +387,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches annotations on the current annotated node. */
@Override
void visitAnnotations(AnnotatedNode node) {
doWithNode(node, current) {
@@ -418,6 +424,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a class code container against the current candidate. */
@Override
protected void visitClassCodeContainer(Statement code) {
doWithNode(code, current) {
@@ -427,6 +434,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a declaration expression against the current candidate. */
@Override @CompileDynamic
void visitDeclarationExpression(DeclarationExpression expression) {
doWithNode(expression, current) {
@@ -434,6 +442,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a constructor or method node against the current candidate. */
@Override
protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
doWithNode(node, current) {
@@ -456,6 +465,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a field node against the current candidate. */
@Override
void visitField(FieldNode node) {
doWithNode(node, current) {
@@ -481,6 +491,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a property node against the current candidate. */
@Override
void visitProperty(PropertyNode node) {
doWithNode(node, current) {
@@ -515,6 +526,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches an expression statement against the current candidate. */
@Override
void visitExpressionStatement(ExpressionStatement statement) {
doWithNode(statement.expression, ((ExpressionStatement) current).expression) {
@@ -523,6 +535,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a block statement against the current candidate. */
@Override
void visitBlockStatement(BlockStatement block) {
doWithNode(block, current) {
@@ -540,6 +553,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a method call expression against the current candidate. */
@Override
void visitMethodCallExpression(MethodCallExpression call) {
doWithNode(call, current) {
@@ -560,6 +574,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a constructor call expression against the current candidate. */
@Override
void visitConstructorCallExpression(ConstructorCallExpression call) {
doWithNode(call, current) {
@@ -571,6 +586,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a binary expression against the current candidate. */
@Override
void visitBinaryExpression(BinaryExpression expression) {
doWithNode(expression, current) {
@@ -602,6 +618,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a ternary expression against the current candidate. */
@Override
void visitTernaryExpression(TernaryExpression expression) {
doWithNode(expression, current) {
@@ -620,6 +637,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a postfix expression against the current candidate. */
@Override
void visitPostfixExpression(PostfixExpression expression) {
doWithNode(expression, current) {
@@ -632,6 +650,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a prefix expression against the current candidate. */
@Override
void visitPrefixExpression(PrefixExpression expression) {
doWithNode(expression, current) {
@@ -644,6 +663,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a boolean expression against the current candidate. */
@Override
void visitBooleanExpression(BooleanExpression expression) {
doWithNode(expression, current) {
@@ -653,6 +673,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a not expression against the current candidate. */
@Override
void visitNotExpression(NotExpression expression) {
doWithNode(expression, current) {
@@ -664,6 +685,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a closure expression against the current candidate. */
@Override
void visitClosureExpression(ClosureExpression expression) {
doWithNode(expression, current) {
@@ -698,6 +720,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a tuple expression against the current candidate. */
@Override
void visitTupleExpression(TupleExpression expression) {
doWithNode(expression, current) {
@@ -707,6 +730,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a list expression against the current candidate. */
@Override
void visitListExpression(ListExpression expression) {
doWithNode(expression, current) {
@@ -717,6 +741,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches an array expression against the current candidate. */
@Override
void visitArrayExpression(ArrayExpression expression) {
doWithNode(expression, current) {
@@ -735,6 +760,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a map expression against the current candidate. */
@Override
void visitMapExpression(MapExpression expression) {
doWithNode(expression, current) {
@@ -746,6 +772,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a map-entry expression against the current candidate. */
@Override
void visitMapEntryExpression(MapEntryExpression expression) {
doWithNode(expression, current) {
@@ -763,6 +790,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a range expression against the current candidate. */
@Override
void visitRangeExpression(RangeExpression expression) {
doWithNode(expression, current) {
@@ -780,6 +808,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a spread expression against the current candidate. */
@Override
void visitSpreadExpression(SpreadExpression expression) {
doWithNode(expression, current) {
@@ -790,6 +819,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a method-pointer expression against the current candidate. */
@Override
void visitMethodPointerExpression(MethodPointerExpression expression) {
doWithNode(expression, current) {
@@ -807,6 +837,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a unary-minus expression against the current candidate. */
@Override
void visitUnaryMinusExpression(UnaryMinusExpression expression) {
doWithNode(expression, current) {
@@ -817,6 +848,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a unary-plus expression against the current candidate. */
@Override
void visitUnaryPlusExpression(UnaryPlusExpression expression) {
doWithNode(expression, current) {
@@ -827,6 +859,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a bitwise-negation expression against the current candidate. */
@Override
void visitBitwiseNegationExpression(BitwiseNegationExpression expression) {
doWithNode(expression, current) {
@@ -837,6 +870,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a cast expression against the current candidate. */
@Override
void visitCastExpression(CastExpression expression) {
doWithNode(expression, current) {
@@ -848,6 +882,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a constant expression against the current candidate. */
@Override @CompileDynamic
void visitConstantExpression(ConstantExpression expression) {
doWithNode(expression, current) {
@@ -857,6 +892,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a class expression against the current candidate. */
@Override @CompileDynamic
void visitClassExpression(ClassExpression expression) {
doWithNode(expression, current) {
@@ -866,6 +902,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a variable expression against the current candidate. */
@Override
void visitVariableExpression(VariableExpression expression) {
doWithNode(expression, current) {
@@ -875,6 +912,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a property expression against the current candidate. */
@Override
void visitPropertyExpression(PropertyExpression expression) {
doWithNode(expression, current) {
@@ -892,6 +930,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches an attribute expression against the current candidate. */
@Override
void visitAttributeExpression(AttributeExpression expression) {
doWithNode(expression, current) {
@@ -909,6 +948,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a GString expression against the current candidate. */
@Override
void visitGStringExpression(GStringExpression expression) {
doWithNode(expression, current) {
@@ -926,6 +966,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a list of expressions against the current candidate list. */
@Override
void visitListOfExpressions(List<? extends Expression> list) {
if (list == null) return
@@ -943,6 +984,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a closure-list expression against the current candidate. */
@Override
void visitClosureListExpression(ClosureListExpression cle) {
doWithNode(cle, current) {
@@ -953,6 +995,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches an if/else statement against the current candidate. */
@Override
void visitIfElse(IfStatement ifElse) {
doWithNode(ifElse, current) {
@@ -974,6 +1017,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a for loop against the current candidate. */
@Override
void visitForLoop(ForStatement forLoop) {
doWithNode(forLoop, current) {
@@ -990,6 +1034,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
}
}
+ /** Matches a while loop against the current candidate. */
@Override
void visitWhileLoop(WhileStatement loop) {
doWithNode(loop, current) {
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ContextualClassCodeVisitor.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ContextualClassCodeVisitor.java
index 06ed8ab493..7d9601e656 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ContextualClassCodeVisitor.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ContextualClassCodeVisitor.java
@@ -148,11 +148,22 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
ASTNode parentNode = treeContext.parent!=null?treeContext.parent.node:null;
if (treeContext.node instanceof Expression && parentNode !=null) {
ClassCodeExpressionTransformer trn = new ClassCodeExpressionTransformer() {
+ /**
+ * Returns no source unit for deferred replacement.
+ *
+ * @return {@code null}
+ */
@Override
protected SourceUnit getSourceUnit() {
return null;
}
+ /**
+ * Replaces the current expression when a replacement was registered.
+ *
+ * @param exp the expression to transform
+ * @return the replacement or the transformed expression
+ */
@Override
public Expression transform(final Expression exp) {
if (exp==treeContext.node) {
@@ -183,6 +194,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
// ----------------------- override visit methods to provide contextual information ---------------------------
+ /** Visits a class node while tracking traversal context. */
@Override
public void visitClass(final ClassNode node) {
pushContext(node);
@@ -190,6 +202,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a package node while tracking traversal context. */
@Override
public void visitPackage(final PackageNode node) {
if (node!=null) {
@@ -201,6 +214,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
}
}
+ /** Visits module imports while tracking traversal context. */
@Override
public void visitImports(final ModuleNode node) {
pushContext(node);
@@ -208,6 +222,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a constructor or method while tracking traversal context. */
@Override
protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
pushContext(node);
@@ -215,6 +230,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a field node while tracking traversal context. */
@Override
public void visitField(final FieldNode node) {
pushContext(node);
@@ -222,6 +238,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a property node while tracking traversal context. */
@Override
public void visitProperty(final PropertyNode node) {
pushContext(node);
@@ -229,6 +246,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a method call expression while tracking traversal context. */
@Override
public void visitMethodCallExpression(final MethodCallExpression call) {
pushContext(call);
@@ -236,6 +254,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a static method call expression while tracking traversal context. */
@Override
public void visitStaticMethodCallExpression(final StaticMethodCallExpression call) {
pushContext(call);
@@ -243,6 +262,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a constructor call expression while tracking traversal context. */
@Override
public void visitConstructorCallExpression(final ConstructorCallExpression call) {
pushContext(call);
@@ -250,6 +270,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a binary expression while tracking traversal context. */
@Override
public void visitBinaryExpression(final BinaryExpression expression) {
pushContext(expression);
@@ -257,6 +278,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a ternary expression while tracking traversal context. */
@Override
public void visitTernaryExpression(final TernaryExpression expression) {
pushContext(expression);
@@ -264,6 +286,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits an Elvis expression while tracking traversal context. */
@Override
public void visitShortTernaryExpression(final ElvisOperatorExpression expression) {
pushContext(expression);
@@ -271,6 +294,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a postfix expression while tracking traversal context. */
@Override
public void visitPostfixExpression(final PostfixExpression expression) {
pushContext(expression);
@@ -278,6 +302,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a prefix expression while tracking traversal context. */
@Override
public void visitPrefixExpression(final PrefixExpression expression) {
pushContext(expression);
@@ -285,6 +310,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a boolean expression while tracking traversal context. */
@Override
public void visitBooleanExpression(final BooleanExpression expression) {
pushContext(expression);
@@ -292,6 +318,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a not expression while tracking traversal context. */
@Override
public void visitNotExpression(final NotExpression expression) {
pushContext(expression);
@@ -299,6 +326,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a closure expression while tracking traversal context. */
@Override
public void visitClosureExpression(final ClosureExpression expression) {
pushContext(expression);
@@ -306,6 +334,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a tuple expression while tracking traversal context. */
@Override
public void visitTupleExpression(final TupleExpression expression) {
pushContext(expression);
@@ -313,6 +342,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a list expression while tracking traversal context. */
@Override
public void visitListExpression(final ListExpression expression) {
pushContext(expression);
@@ -320,6 +350,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits an array expression while tracking traversal context. */
@Override
public void visitArrayExpression(final ArrayExpression expression) {
pushContext(expression);
@@ -327,6 +358,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a map expression while tracking traversal context. */
@Override
public void visitMapExpression(final MapExpression expression) {
pushContext(expression);
@@ -334,6 +366,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a map-entry expression while tracking traversal context. */
@Override
public void visitMapEntryExpression(final MapEntryExpression expression) {
pushContext(expression);
@@ -341,6 +374,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a range expression while tracking traversal context. */
@Override
public void visitRangeExpression(final RangeExpression expression) {
pushContext(expression);
@@ -348,6 +382,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a spread expression while tracking traversal context. */
@Override
public void visitSpreadExpression(final SpreadExpression expression) {
pushContext(expression);
@@ -355,6 +390,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a spread-map expression while tracking traversal context. */
@Override
public void visitSpreadMapExpression(final SpreadMapExpression expression) {
pushContext(expression);
@@ -362,6 +398,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a method-pointer expression while tracking traversal context. */
@Override
public void visitMethodPointerExpression(final MethodPointerExpression expression) {
pushContext(expression);
@@ -369,6 +406,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a unary-minus expression while tracking traversal context. */
@Override
public void visitUnaryMinusExpression(final UnaryMinusExpression expression) {
pushContext(expression);
@@ -376,6 +414,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a unary-plus expression while tracking traversal context. */
@Override
public void visitUnaryPlusExpression(final UnaryPlusExpression expression) {
pushContext(expression);
@@ -383,6 +422,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a bitwise-negation expression while tracking traversal context. */
@Override
public void visitBitwiseNegationExpression(final BitwiseNegationExpression expression) {
pushContext(expression);
@@ -390,6 +430,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a cast expression while tracking traversal context. */
@Override
public void visitCastExpression(final CastExpression expression) {
pushContext(expression);
@@ -397,6 +438,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a constant expression while tracking traversal context. */
@Override
public void visitConstantExpression(final ConstantExpression expression) {
pushContext(expression);
@@ -404,6 +446,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a class expression while tracking traversal context. */
@Override
public void visitClassExpression(final ClassExpression expression) {
pushContext(expression);
@@ -411,6 +454,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a variable expression while tracking traversal context. */
@Override
public void visitVariableExpression(final VariableExpression expression) {
pushContext(expression);
@@ -418,6 +462,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a property expression while tracking traversal context. */
@Override
public void visitPropertyExpression(final PropertyExpression expression) {
pushContext(expression);
@@ -425,6 +470,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits an attribute expression while tracking traversal context. */
@Override
public void visitAttributeExpression(final AttributeExpression expression) {
pushContext(expression);
@@ -432,6 +478,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a field expression while tracking traversal context. */
@Override
public void visitFieldExpression(final FieldExpression expression) {
pushContext(expression);
@@ -439,6 +486,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a GString expression while tracking traversal context. */
@Override
public void visitGStringExpression(final GStringExpression expression) {
pushContext(expression);
@@ -446,6 +494,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a closure-list expression while tracking traversal context. */
@Override
public void visitClosureListExpression(final ClosureListExpression cle) {
pushContext(cle);
@@ -453,6 +502,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a bytecode expression while tracking traversal context. */
@Override
public void visitBytecodeExpression(final BytecodeExpression cle) {
pushContext(cle);
@@ -460,6 +510,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits an assert statement while tracking traversal context. */
@Override
public void visitAssertStatement(final AssertStatement statement) {
pushContext(statement);
@@ -467,6 +518,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a block statement while tracking traversal context. */
@Override
public void visitBlockStatement(final BlockStatement block) {
pushContext(block);
@@ -474,6 +526,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a break statement while tracking traversal context. */
@Override
public void visitBreakStatement(final BreakStatement statement) {
pushContext(statement);
@@ -481,6 +534,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a case statement while tracking traversal context. */
@Override
public void visitCaseStatement(final CaseStatement statement) {
pushContext(statement);
@@ -488,6 +542,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a catch statement while tracking traversal context. */
@Override
public void visitCatchStatement(final CatchStatement statement) {
pushContext(statement);
@@ -495,6 +550,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a continue statement while tracking traversal context. */
@Override
public void visitContinueStatement(final ContinueStatement statement) {
pushContext(statement);
@@ -502,6 +558,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a do-while loop while tracking traversal context. */
@Override
public void visitDoWhileLoop(final DoWhileStatement loop) {
pushContext(loop);
@@ -509,6 +566,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits an expression statement while tracking traversal context. */
@Override
public void visitExpressionStatement(final ExpressionStatement statement) {
pushContext(statement);
@@ -516,6 +574,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a for loop while tracking traversal context. */
@Override
public void visitForLoop(final ForStatement forLoop) {
pushContext(forLoop);
@@ -523,6 +582,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits an if/else statement while tracking traversal context. */
@Override
public void visitIfElse(final IfStatement ifElse) {
pushContext(ifElse);
@@ -530,6 +590,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a return statement while tracking traversal context. */
@Override
public void visitReturnStatement(final ReturnStatement statement) {
pushContext(statement);
@@ -537,6 +598,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a switch statement while tracking traversal context. */
@Override
public void visitSwitch(final SwitchStatement statement) {
pushContext(statement);
@@ -544,6 +606,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a synchronized statement while tracking traversal context. */
@Override
public void visitSynchronizedStatement(final SynchronizedStatement statement) {
pushContext(statement);
@@ -551,6 +614,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a throw statement while tracking traversal context. */
@Override
public void visitThrowStatement(final ThrowStatement statement) {
pushContext(statement);
@@ -558,6 +622,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a try/catch/finally statement while tracking traversal context. */
@Override
public void visitTryCatchFinally(final TryCatchStatement statement) {
pushContext(statement);
@@ -565,6 +630,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits a while loop while tracking traversal context. */
@Override
public void visitWhileLoop(final WhileStatement loop) {
pushContext(loop);
@@ -572,6 +638,7 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
popContext();
}
+ /** Visits an empty statement while tracking traversal context. */
@Override
public void visitEmptyStatement(final EmptyStatement statement) {
pushContext(statement);
@@ -693,6 +760,12 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
this.astNodeClass = astNodeClass;
}
+ /**
+ * Checks whether the node class exactly matches the configured class.
+ *
+ * @param node the node to test
+ * @return {@code true} when the node class matches
+ */
@Override
public boolean matches(final ASTNode node) {
return astNodeClass ==node.getClass();
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/MatcherUtils.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/MatcherUtils.java
index 6912d18f41..f1a3a19671 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/MatcherUtils.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/MatcherUtils.java
@@ -20,6 +20,9 @@ package org.codehaus.groovy.macro.matcher;
import groovy.lang.Closure;
+/**
+ * Utility methods shared by AST matcher support classes.
+ */
class MatcherUtils {
/**
* Clones a closure and sets its delegate for matcher evaluation.
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/TreeContext.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/TreeContext.java
index 05bef4364a..48492d788b 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/TreeContext.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/TreeContext.java
@@ -40,20 +40,35 @@ public class TreeContext {
private enum TreeContextKey {
expression_replacement
}
+ /** Parent traversal context. */
final TreeContext parent;
+ /** AST node represented by this context. */
final ASTNode node;
+ /** Child contexts created from this context. */
final List<TreeContext> siblings = new LinkedList<>();
+ /** Actions invoked when this context is popped. */
final List<TreeContextAction> onPopHandlers = new LinkedList<>();
+ /** User data stored against this context. */
final Map<Object, List<Object>> userdata = MapWithDefault.newInstance(
new HashMap<Object, List<Object>>(),
new Closure<List<Object>>(this) {
private static final long serialVersionUID = -4694773031569936343L;
+
+ /**
+ * Creates the default list for a user-data key.
+ *
+ * @param key the user-data key
+ * @return a new mutable value list
+ */
public Object doCall(Object key) {
return new LinkedList<Object>();
}
}
);
+ /**
+ * Creates a traversal context for the supplied node.
+ */
TreeContext(final TreeContext parent, final ASTNode node) {
this.parent = parent;
this.node = node;
@@ -210,6 +225,11 @@ public class TreeContext {
return null;
}
+ /**
+ * Returns a string form containing the current node and its parent path.
+ *
+ * @return the context description
+ */
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TreeContext{");
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/internal/MatchingConstraintsBuilder.groovy b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/internal/MatchingConstraintsBuilder.groovy
index 545db2e890..1816245f38 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/internal/MatchingConstraintsBuilder.groovy
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/internal/MatchingConstraintsBuilder.groovy
@@ -118,6 +118,7 @@ class MatchingConstraintsBuilder {
def clone = (Closure<Boolean>) predicate.clone()
clone.resolveStrategy = Closure.DELEGATE_FIRST
tokenPredicate = new ConstraintPredicate<Token>() {
+ /** Evaluates the configured token predicate closure. */
@Override
boolean apply(final Token a) {
clone.delegate = a
@@ -137,6 +138,7 @@ class MatchingConstraintsBuilder {
def clone = (Closure<Boolean>) predicate.clone()
clone.resolveStrategy = Closure.DELEGATE_FIRST
eventually = new ConstraintPredicate<TreeContext>() {
+ /** Evaluates the configured tree-context predicate closure. */
@Override
boolean apply(final TreeContext a) {
clone.delegate = a
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/methods/MacroGroovyMethods.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/methods/MacroGroovyMethods.java
index 0460b4c87b..0de9dd2106 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/methods/MacroGroovyMethods.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/methods/MacroGroovyMethods.java
@@ -219,11 +219,21 @@ public class MacroGroovyMethods {
final ListExpression listExpression = new ListExpression();
ClassCodeVisitorSupport visitor = new ClassCodeVisitorSupport() {
+ /**
+ * Returns no source unit because this visitor only collects substitutions.
+ *
+ * @return {@code null}
+ */
@Override
protected SourceUnit getSourceUnit() {
return null;
}
+ /**
+ * Visits the class and its inner classes to collect substitutions.
+ *
+ * @param node the class node to inspect
+ */
@Override
public void visitClass(final ClassNode node) {
super.visitClass(node);
@@ -234,6 +244,11 @@ public class MacroGroovyMethods {
}
}
+ /**
+ * Collects substitution closures referenced through {@code $v} calls.
+ *
+ * @param call the method call to inspect
+ */
@Override
public void visitMethodCallExpression(MethodCallExpression call) {
super.visitMethodCallExpression(call);
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java
index 02a1ebddd7..ed84ca97c5 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroBuilder.java
@@ -46,6 +46,7 @@ import static org.codehaus.groovy.macro.methods.MacroGroovyMethods.DOLLAR_VALUE;
@Incubating
public enum MacroBuilder {
+ /** Shared macro builder instance. */
INSTANCE;
/**
@@ -137,6 +138,12 @@ public enum MacroBuilder {
private static void performSubstitutions(final List<Closure<Expression>> context, final ASTNode astNode) {
final Iterator<Closure<Expression>> iterator = context.iterator();
ClassCodeExpressionTransformer trn = new ClassCodeExpressionTransformer() {
+ /**
+ * Replaces {@code $v} calls with the next substitution expression.
+ *
+ * @param expression the expression to transform
+ * @return the transformed expression
+ */
@Override
public Expression transform(Expression expression) {
if (!(expression instanceof MethodCallExpression call)) {
@@ -150,6 +157,11 @@ public enum MacroBuilder {
return iterator.next().call();
}
+ /**
+ * Returns no source unit when applying runtime substitutions.
+ *
+ * @return {@code null}
+ */
@Override
protected SourceUnit getSourceUnit() {
// Could be null if there are no errors
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java
index 5ef79e622b..f6000b3adb 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/runtime/MacroStub.java
@@ -24,6 +24,7 @@ package org.codehaus.groovy.macro.runtime;
* @since 2.5.0
*/
public enum MacroStub {
+ /** Shared macro stub instance. */
INSTANCE;
/**
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java
index a95806d7df..06b802b1ec 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroCallTransformingVisitor.java
@@ -77,6 +77,11 @@ class MacroCallTransformingVisitor extends ClassCodeVisitorSupport {
this.classLoader = unit.getTransformLoader();
}
+ /**
+ * Returns the source unit currently being rewritten.
+ *
+ * @return the active source unit
+ */
@Override
protected SourceUnit getSourceUnit() {
return sourceUnit;
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java
index 9fb9678701..df98750f8e 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroClassTransformation.java
@@ -81,11 +81,22 @@ public class MacroClassTransformation extends MethodCallTransformation {
this.sourceUnit = sourceUnit;
}
+ /**
+ * Returns the source unit being transformed.
+ *
+ * @return the active source unit
+ */
@Override
protected SourceUnit getSourceUnit() {
return sourceUnit;
}
+ /**
+ * Rewrites anonymous macro-class constructor calls to macro invocations.
+ *
+ * @param exp the expression to transform
+ * @return the transformed expression
+ */
@Override
public Expression transform(final Expression exp) {
if (exp instanceof ConstructorCallExpression) {
@@ -107,6 +118,11 @@ public class MacroClassTransformation extends MethodCallTransformation {
this.sourceUnit = sourceUnit;
}
+ /**
+ * Rewrites anonymous macro-class constructor calls before visiting nested expressions.
+ *
+ * @param call the constructor call to inspect
+ */
@Override
public void visitConstructorCallExpression(final ConstructorCallExpression call) {
ClassNode type = call.getType();
diff --git a/subprojects/groovy-sql/src/main/java/groovy/sql/CallResultSet.java b/subprojects/groovy-sql/src/main/java/groovy/sql/CallResultSet.java
index 52844e710a..cfe2a0f272 100644
--- a/subprojects/groovy-sql/src/main/java/groovy/sql/CallResultSet.java
+++ b/subprojects/groovy-sql/src/main/java/groovy/sql/CallResultSet.java
@@ -26,9 +26,21 @@ import java.sql.SQLException;
* Represents a ResultSet retrieved as a callable statement out parameter.
*/
class CallResultSet extends GroovyResultSetExtension {
+ /**
+ * The zero-based out-parameter index.
+ */
int indx;
+ /**
+ * The callable statement that owns the out parameter.
+ */
CallableStatement call;
+ /**
+ * The lazily materialized result set for the out parameter.
+ */
ResultSet resultSet;
+ /**
+ * Indicates whether the out parameter still needs to be read from the callable statement.
+ */
boolean firstCall = true;
/**
diff --git a/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java b/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
index c54cb4d0fc..e65551be88 100644
--- a/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
+++ b/subprojects/groovy-sql/src/main/java/groovy/sql/Sql.java
@@ -5256,12 +5256,26 @@ public class Sql implements AutoCloseable {
}
}
+ /**
+ * Base command object for query operations that manage statement and connection lifecycle.
+ */
protected abstract class AbstractQueryCommand {
+ /**
+ * The SQL text executed by this command.
+ */
protected final String sql;
+ /**
+ * The statement created while running the command.
+ */
protected Statement statement;
private Connection connection;
private int maxRows = 0;
+ /**
+ * Creates a query command for the supplied SQL text.
+ *
+ * @param sql the SQL statement to execute
+ */
protected AbstractQueryCommand(String sql) {
// Don't create statement in subclass constructors to avoid throw in constructors
this.sql = sql;
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/AbstractButtonProperties.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/AbstractButtonProperties.java
index 3a7d2a5f98..3f6a3b13a5 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/AbstractButtonProperties.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/AbstractButtonProperties.java
@@ -69,6 +69,9 @@ class AbstractButtonSelectedBinding extends AbstractSyntheticBinding implements
super(source, target, AbstractButton.class, "selected");
}
+ /**
+ * Starts listening to the bound button and its current model.
+ */
@Override
public synchronized void syntheticBind() {
boundButton = (AbstractButton) ((PropertyBinding) sourceBinding).getBean();
@@ -76,6 +79,9 @@ class AbstractButtonSelectedBinding extends AbstractSyntheticBinding implements
boundButton.getModel().addItemListener(this);
}
+ /**
+ * Stops listening to the bound button and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundButton.removePropertyChangeListener("model", this);
@@ -83,6 +89,11 @@ class AbstractButtonSelectedBinding extends AbstractSyntheticBinding implements
boundButton = null;
}
+ /**
+ * Refreshes the binding after the button model changes and reattaches listeners.
+ *
+ * @param event the model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
@@ -90,6 +101,11 @@ class AbstractButtonSelectedBinding extends AbstractSyntheticBinding implements
((ButtonModel)event.getNewValue()).addItemListener(this);
}
+ /**
+ * Refreshes the binding after the button selection state changes.
+ *
+ * @param e the item event describing the selection change
+ */
@Override
public void itemStateChanged(ItemEvent e) {
update();
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/AbstractSyntheticBinding.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/AbstractSyntheticBinding.java
index 8797a05f6f..2ce76e3b02 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/AbstractSyntheticBinding.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/AbstractSyntheticBinding.java
@@ -57,6 +57,9 @@ public abstract class AbstractSyntheticBinding extends AbstractFullBinding {
setTargetBinding(target);
}
+ /**
+ * Installs the synthetic listeners if this binding is not already active.
+ */
@Override
public void bind() {
if (!bound) {
@@ -74,6 +77,9 @@ public abstract class AbstractSyntheticBinding extends AbstractFullBinding {
}
}
+ /**
+ * Removes the synthetic listeners if this binding is currently active.
+ */
@Override
public void unbind() {
if (bound) {
@@ -92,6 +98,9 @@ public abstract class AbstractSyntheticBinding extends AbstractFullBinding {
*/
protected abstract void syntheticUnbind();
+ /**
+ * Reinstalls the synthetic listeners when the binding is already active.
+ */
@Override
public void rebind() {
if (bound) {
@@ -100,6 +109,11 @@ public abstract class AbstractSyntheticBinding extends AbstractFullBinding {
}
}
+ /**
+ * Validates and stores the source binding for this synthetic property.
+ *
+ * @param source the source binding to validate
+ */
@Override
public void setSourceBinding(SourceBinding source) {
if (!(source instanceof PropertyBinding)) {
@@ -116,6 +130,11 @@ public abstract class AbstractSyntheticBinding extends AbstractFullBinding {
super.setSourceBinding(source);
}
+ /**
+ * Stores the target binding that receives propagated updates.
+ *
+ * @param target the target binding
+ */
@Override
public void setTargetBinding(TargetBinding target) {
super.setTargetBinding(target);
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JComboBoxProperties.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JComboBoxProperties.java
index 3193e72a29..3a1026839e 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JComboBoxProperties.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JComboBoxProperties.java
@@ -83,6 +83,9 @@ class JComboBoxSelectedElementBinding extends AbstractSyntheticBinding implement
super(source, target, JComboBox.class, propertyName);
}
+ /**
+ * Starts listening to the bound combo box and its model.
+ */
@Override
public synchronized void syntheticBind() {
boundComboBox = (JComboBox) ((PropertyBinding)sourceBinding).getBean();
@@ -90,6 +93,9 @@ class JComboBoxSelectedElementBinding extends AbstractSyntheticBinding implement
boundComboBox.addItemListener(this);
}
+ /**
+ * Stops listening to the bound combo box and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundComboBox.removePropertyChangeListener("model", this);
@@ -97,16 +103,31 @@ class JComboBoxSelectedElementBinding extends AbstractSyntheticBinding implement
boundComboBox = null;
}
+ /**
+ * Stores the target binding that receives selected-item updates.
+ *
+ * @param target the target binding
+ */
@Override
public void setTargetBinding(TargetBinding target) {
super.setTargetBinding(target);
}
+ /**
+ * Refreshes the binding after a combo-box model change.
+ *
+ * @param event the model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
}
+ /**
+ * Refreshes the binding after a combo-box selection change.
+ *
+ * @param e the item event describing the selection change
+ */
@Override
public void itemStateChanged(ItemEvent e) {
update();
@@ -134,6 +155,9 @@ class JComboBoxSelectedIndexBinding extends AbstractSyntheticBinding implements
super(source, target, JComboBox.class, "selectedIndex");
}
+ /**
+ * Starts listening to the bound combo box and its model.
+ */
@Override
public synchronized void syntheticBind() {
boundComboBox = (JComboBox) ((PropertyBinding)sourceBinding).getBean();
@@ -141,6 +165,9 @@ class JComboBoxSelectedIndexBinding extends AbstractSyntheticBinding implements
boundComboBox.addItemListener(this);
}
+ /**
+ * Stops listening to the bound combo box and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundComboBox.removePropertyChangeListener("model", this);
@@ -148,16 +175,31 @@ class JComboBoxSelectedIndexBinding extends AbstractSyntheticBinding implements
boundComboBox = null;
}
+ /**
+ * Stores the target binding that receives selected-index updates.
+ *
+ * @param target the target binding
+ */
@Override
public void setTargetBinding(TargetBinding target) {
super.setTargetBinding(target);
}
+ /**
+ * Refreshes the binding after a combo-box model change.
+ *
+ * @param event the model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
}
+ /**
+ * Refreshes the binding after a combo-box selection change.
+ *
+ * @param e the item event describing the selection change
+ */
@Override
public void itemStateChanged(ItemEvent e) {
update();
@@ -185,6 +227,9 @@ class JComboBoxElementsBinding extends AbstractSyntheticBinding implements ListD
super(propertyBinding, target, JComboBox.class, "elements");
}
+ /**
+ * Starts listening to the bound combo-box model.
+ */
@Override
protected void syntheticBind() {
boundComboBox = (JComboBox) ((PropertyBinding)sourceBinding).getBean();
@@ -192,12 +237,20 @@ class JComboBoxElementsBinding extends AbstractSyntheticBinding implements ListD
boundComboBox.getModel().addListDataListener(this);
}
+ /**
+ * Stops listening to the bound combo-box model.
+ */
@Override
protected void syntheticUnbind() {
boundComboBox.removePropertyChangeListener("model", this);
boundComboBox.getModel().removeListDataListener(this);
}
+ /**
+ * Refreshes the binding after the combo-box model instance changes.
+ *
+ * @param event the model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
@@ -205,16 +258,31 @@ class JComboBoxElementsBinding extends AbstractSyntheticBinding implements ListD
((ComboBoxModel) event.getNewValue()).addListDataListener(this);
}
+ /**
+ * Refreshes the binding after items are inserted into the model.
+ *
+ * @param e the list-data event
+ */
@Override
public void intervalAdded(ListDataEvent e) {
update();
}
+ /**
+ * Refreshes the binding after items are removed from the model.
+ *
+ * @param e the list-data event
+ */
@Override
public void intervalRemoved(ListDataEvent e) {
update();
}
+ /**
+ * Refreshes the binding after existing items in the model change.
+ *
+ * @param e the list-data event
+ */
@Override
public void contentsChanged(ListDataEvent e) {
update();
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JComponentProperties.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JComponentProperties.java
index 0df1a04809..10a8a82cd8 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JComponentProperties.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JComponentProperties.java
@@ -129,6 +129,9 @@ abstract class AbstractJComponentBinding extends AbstractSyntheticBinding implem
source.setNonChangeCheck(true);
}
+ /**
+ * Starts listening to the bound component and the backing Swing property.
+ */
@Override
public synchronized void syntheticBind() {
boundComponent = (JComponent) ((PropertyBinding)sourceBinding).getBean();
@@ -136,6 +139,9 @@ abstract class AbstractJComponentBinding extends AbstractSyntheticBinding implem
boundComponent.addComponentListener(this);
}
+ /**
+ * Stops listening to the bound component and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundComponent.removePropertyChangeListener(propertyName, this);
@@ -143,6 +149,11 @@ abstract class AbstractJComponentBinding extends AbstractSyntheticBinding implem
boundComponent = null;
}
+ /**
+ * Refreshes the binding after the observed component property changes.
+ *
+ * @param event the property change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JScrollBarProperties.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JScrollBarProperties.java
index 0342d9e87f..2526ddac8e 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JScrollBarProperties.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JScrollBarProperties.java
@@ -70,6 +70,9 @@ class JScrollBarValueBinding extends AbstractSyntheticBinding implements Propert
super(source, target, JScrollBar.class, "value");
}
+ /**
+ * Starts listening to the bound scroll bar and its model.
+ */
@Override
public synchronized void syntheticBind() {
boundScrollBar = (JScrollBar) ((PropertyBinding)sourceBinding).getBean();
@@ -77,6 +80,9 @@ class JScrollBarValueBinding extends AbstractSyntheticBinding implements Propert
boundScrollBar.getModel().addChangeListener(this);
}
+ /**
+ * Stops listening to the bound scroll bar and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundScrollBar.removePropertyChangeListener("model", this);
@@ -84,11 +90,21 @@ class JScrollBarValueBinding extends AbstractSyntheticBinding implements Propert
boundScrollBar = null;
}
+ /**
+ * Stores the target binding that receives scroll-bar value updates.
+ *
+ * @param target the target binding
+ */
@Override
public void setTargetBinding(TargetBinding target) {
super.setTargetBinding(target);
}
+ /**
+ * Refreshes the binding after the scroll-bar model instance changes.
+ *
+ * @param event the model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
@@ -96,6 +112,11 @@ class JScrollBarValueBinding extends AbstractSyntheticBinding implements Propert
((BoundedRangeModel) event.getNewValue()).addChangeListener(this);
}
+ /**
+ * Refreshes the binding after the scroll-bar value changes.
+ *
+ * @param e the change event
+ */
@Override
public void stateChanged(ChangeEvent e) {
update();
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JSliderProperties.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JSliderProperties.java
index d029d887b1..99c7380629 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JSliderProperties.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JSliderProperties.java
@@ -70,6 +70,9 @@ class JSliderValueBinding extends AbstractSyntheticBinding implements PropertyCh
super(source, target, JSlider.class, "value");
}
+ /**
+ * Starts listening to the bound slider and its model.
+ */
@Override
public synchronized void syntheticBind() {
boundSlider = (JSlider) ((PropertyBinding)sourceBinding).getBean();
@@ -77,6 +80,9 @@ class JSliderValueBinding extends AbstractSyntheticBinding implements PropertyCh
boundSlider.getModel().addChangeListener(this);
}
+ /**
+ * Stops listening to the bound slider and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundSlider.removePropertyChangeListener("model", this);
@@ -84,6 +90,11 @@ class JSliderValueBinding extends AbstractSyntheticBinding implements PropertyCh
boundSlider = null;
}
+ /**
+ * Refreshes the binding after the slider model instance changes.
+ *
+ * @param event the model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
@@ -91,6 +102,11 @@ class JSliderValueBinding extends AbstractSyntheticBinding implements PropertyCh
((BoundedRangeModel) event.getNewValue()).addChangeListener(this);
}
+ /**
+ * Refreshes the binding after the slider value changes.
+ *
+ * @param e the change event
+ */
@Override
public void stateChanged(ChangeEvent e) {
update();
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JSpinnerProperties.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JSpinnerProperties.java
index 90f25583fd..d3a016332b 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JSpinnerProperties.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JSpinnerProperties.java
@@ -69,6 +69,9 @@ class JSpinnerValueBinding extends AbstractSyntheticBinding implements PropertyC
super(source, target, JSpinner.class, "value");
}
+ /**
+ * Starts listening to the bound spinner and its model.
+ */
@Override
public synchronized void syntheticBind() {
boundSlider = (JSpinner) ((PropertyBinding)sourceBinding).getBean();
@@ -76,6 +79,9 @@ class JSpinnerValueBinding extends AbstractSyntheticBinding implements PropertyC
boundSlider.getModel().addChangeListener(this);
}
+ /**
+ * Stops listening to the bound spinner and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundSlider.removePropertyChangeListener("model", this);
@@ -83,6 +89,11 @@ class JSpinnerValueBinding extends AbstractSyntheticBinding implements PropertyC
boundSlider = null;
}
+ /**
+ * Refreshes the binding after the spinner model instance changes.
+ *
+ * @param event the model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
@@ -90,6 +101,11 @@ class JSpinnerValueBinding extends AbstractSyntheticBinding implements PropertyC
((SpinnerModel) event.getNewValue()).addChangeListener(this);
}
+ /**
+ * Refreshes the binding after the spinner value changes.
+ *
+ * @param e the change event
+ */
@Override
public void stateChanged(ChangeEvent e) {
update();
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JTableProperties.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JTableProperties.java
index d3857f99e0..5a34b6cb1f 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JTableProperties.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JTableProperties.java
@@ -73,6 +73,9 @@ class JTableElementsBinding extends AbstractSyntheticBinding implements TableMod
super(propertyBinding, target, JTable.class, "elements");
}
+ /**
+ * Starts listening to the bound table model.
+ */
@Override
protected void syntheticBind() {
boundTable = (JTable) ((PropertyBinding)sourceBinding).getBean();
@@ -80,17 +83,30 @@ class JTableElementsBinding extends AbstractSyntheticBinding implements TableMod
boundTable.getModel().addTableModelListener(this);
}
+ /**
+ * Stops listening to the bound table model.
+ */
@Override
protected void syntheticUnbind() {
boundTable.removePropertyChangeListener("model", this);
boundTable.getModel().removeTableModelListener(this);
}
+ /**
+ * Refreshes the binding after the table model contents change.
+ *
+ * @param e the table-model event
+ */
@Override
public void tableChanged(TableModelEvent e) {
update();
}
+ /**
+ * Refreshes the binding after the table model instance changes.
+ *
+ * @param event the model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
@@ -119,6 +135,9 @@ class JTableSelectedElementBinding extends AbstractSyntheticBinding implements P
super(source, target, JTable.class, propertyName);
}
+ /**
+ * Starts listening to the bound table selection model.
+ */
@Override
public synchronized void syntheticBind() {
boundTable = (JTable) ((PropertyBinding)sourceBinding).getBean();
@@ -126,6 +145,9 @@ class JTableSelectedElementBinding extends AbstractSyntheticBinding implements P
boundTable.getSelectionModel().addListSelectionListener(this);
}
+ /**
+ * Stops listening to the bound table selection model and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundTable.removePropertyChangeListener("selectionModel", this);
@@ -133,6 +155,11 @@ class JTableSelectedElementBinding extends AbstractSyntheticBinding implements P
boundTable = null;
}
+ /**
+ * Refreshes the binding after the table selection model instance changes.
+ *
+ * @param event the selection-model change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
@@ -140,6 +167,11 @@ class JTableSelectedElementBinding extends AbstractSyntheticBinding implements P
((ListSelectionModel) event.getNewValue()).addListSelectionListener(this);
}
+ /**
+ * Refreshes the binding after the table selection changes.
+ *
+ * @param e the selection event
+ */
@Override
public void valueChanged(ListSelectionEvent e) {
update();
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JTextComponentProperties.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JTextComponentProperties.java
index bd0ab9ee32..5946744467 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JTextComponentProperties.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/binding/JTextComponentProperties.java
@@ -72,6 +72,9 @@ class JTextComponentTextBinding extends AbstractSyntheticBinding implements Prop
source.setNonChangeCheck(true);
}
+ /**
+ * Starts listening to the bound text component and its document.
+ */
@Override
public synchronized void syntheticBind() {
boundTextComponent = (JTextComponent) ((PropertyBinding)sourceBinding).getBean();
@@ -79,6 +82,9 @@ class JTextComponentTextBinding extends AbstractSyntheticBinding implements Prop
boundTextComponent.getDocument().addDocumentListener(this);
}
+ /**
+ * Stops listening to the bound text component and clears the cached reference.
+ */
@Override
public synchronized void syntheticUnbind() {
boundTextComponent.removePropertyChangeListener("document", this);
@@ -86,6 +92,11 @@ class JTextComponentTextBinding extends AbstractSyntheticBinding implements Prop
boundTextComponent = null;
}
+ /**
+ * Refreshes the binding after the document instance changes.
+ *
+ * @param event the document change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
update();
@@ -93,16 +104,31 @@ class JTextComponentTextBinding extends AbstractSyntheticBinding implements Prop
((Document)event.getNewValue()).addDocumentListener(this);
}
+ /**
+ * Refreshes the binding after document attributes change.
+ *
+ * @param event the document event
+ */
@Override
public void changedUpdate(DocumentEvent event) {
update();
}
+ /**
+ * Refreshes the binding after text is inserted.
+ *
+ * @param event the document event
+ */
@Override
public void insertUpdate(DocumentEvent event) {
update();
}
+ /**
+ * Refreshes the binding after text is removed.
+ *
+ * @param event the document event
+ */
@Override
public void removeUpdate(DocumentEvent event) {
update();
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/ClosureRenderer.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/ClosureRenderer.java
index 2873277cda..9680e11e4d 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/ClosureRenderer.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/ClosureRenderer.java
@@ -106,6 +106,16 @@ public class ClosureRenderer implements ListCellRenderer, TableCellRenderer, Tre
}
+ /**
+ * Prepares list-rendering state and delegates component creation to {@link #render()}.
+ *
+ * @param list the list being rendered
+ * @param value the current cell value
+ * @param index the list index being rendered
+ * @param isSelected whether the cell is selected
+ * @param cellHasFocus whether the cell has focus
+ * @return the renderer component
+ */
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
this.list = list;
@@ -122,6 +132,17 @@ public class ClosureRenderer implements ListCellRenderer, TableCellRenderer, Tre
return render();
}
+ /**
+ * Prepares table-rendering state and delegates component creation to {@link #render()}.
+ *
+ * @param table the table being rendered
+ * @param value the current cell value
+ * @param isSelected whether the cell is selected
+ * @param hasFocus whether the cell has focus
+ * @param row the model row being rendered
+ * @param column the model column being rendered
+ * @return the renderer component
+ */
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
this.list = null;
@@ -138,6 +159,18 @@ public class ClosureRenderer implements ListCellRenderer, TableCellRenderer, Tre
return render();
}
+ /**
+ * Prepares tree-rendering state and delegates component creation to {@link #render()}.
+ *
+ * @param tree the tree being rendered
+ * @param value the current node value
+ * @param selected whether the row is selected
+ * @param expanded whether the node is expanded
+ * @param leaf whether the node is a leaf
+ * @param row the tree row being rendered
+ * @param hasFocus whether the row has focus
+ * @return the renderer component
+ */
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
this.list = null;
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/DefaultAction.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/DefaultAction.java
index 49e65652e4..56ba401c26 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/DefaultAction.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/DefaultAction.java
@@ -30,6 +30,11 @@ public class DefaultAction extends AbstractAction {
private Closure closure;
+ /**
+ * Invokes the configured closure in response to the action event.
+ *
+ * @param event the Swing action event
+ */
@Override
public void actionPerformed(ActionEvent event) {
if (closure == null) {
diff --git a/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/ListWrapperListModel.java b/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/ListWrapperListModel.java
index b7bc377a34..775dca7db0 100644
--- a/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/ListWrapperListModel.java
+++ b/subprojects/groovy-swing/src/main/groovy/groovy/swing/impl/ListWrapperListModel.java
@@ -49,11 +49,22 @@ public class ListWrapperListModel<E> extends AbstractListModel {
return delegate;
}
+ /**
+ * Returns the number of elements currently exposed by the backing list.
+ *
+ * @return the current model size
+ */
@Override
public int getSize() {
return delegate.size();
}
+ /**
+ * Returns the element at the supplied index from the backing list.
+ *
+ * @param i the requested element index
+ * @return the element at {@code i}
+ */
@Override
public Object getElementAt(int i) {
return delegate.get(i);
diff --git a/subprojects/groovy-swing/src/main/java/groovy/swing/model/ClosureModel.java b/subprojects/groovy-swing/src/main/java/groovy/swing/model/ClosureModel.java
index 1aedde5bef..50f4005725 100644
--- a/subprojects/groovy-swing/src/main/java/groovy/swing/model/ClosureModel.java
+++ b/subprojects/groovy-swing/src/main/java/groovy/swing/model/ClosureModel.java
@@ -68,6 +68,11 @@ public class ClosureModel implements ValueModel, NestedValueModel {
this.type = type;
}
+ /**
+ * Returns the model that supplies the source object consumed by the closures.
+ *
+ * @return the nested source model
+ */
@Override
public ValueModel getSourceModel() {
return sourceModel;
diff --git a/subprojects/groovy-swing/src/main/java/groovy/swing/model/DefaultTableColumn.java b/subprojects/groovy-swing/src/main/java/groovy/swing/model/DefaultTableColumn.java
index 539dbcb11b..5b1f84a2d1 100644
--- a/subprojects/groovy-swing/src/main/java/groovy/swing/model/DefaultTableColumn.java
+++ b/subprojects/groovy-swing/src/main/java/groovy/swing/model/DefaultTableColumn.java
@@ -59,6 +59,11 @@ public class DefaultTableColumn extends TableColumn {
setIdentifier(identifier);
}
+ /**
+ * Returns a debug-friendly description of this column and its backing value model.
+ *
+ * @return the column description
+ */
@Override
public String toString() {
return super.toString() + "[header:" + getHeaderValue() + " valueModel:" + valueModel + "]";
diff --git a/subprojects/groovy-swing/src/main/java/groovy/swing/model/DefaultTableModel.java b/subprojects/groovy-swing/src/main/java/groovy/swing/model/DefaultTableModel.java
index dacadffa05..d798cc6ad7 100644
--- a/subprojects/groovy-swing/src/main/java/groovy/swing/model/DefaultTableModel.java
+++ b/subprojects/groovy-swing/src/main/java/groovy/swing/model/DefaultTableModel.java
@@ -135,16 +135,32 @@ public class DefaultTableModel extends AbstractTableModel {
columnModel.removeColumn(column);
}
+ /**
+ * Returns the number of rows currently exposed by the rows model.
+ *
+ * @return the current row count
+ */
@Override
public int getRowCount() {
return getRows().size();
}
+ /**
+ * Returns the number of configured columns.
+ *
+ * @return the current column count
+ */
@Override
public int getColumnCount() {
return columnModel.getColumnCount();
}
+ /**
+ * Returns the header text for the supplied column.
+ *
+ * @param columnIndex the column index
+ * @return the column header text, or {@code null} when unavailable
+ */
@Override
public String getColumnName(int columnIndex) {
String answer = null;
@@ -158,17 +174,37 @@ public class DefaultTableModel extends AbstractTableModel {
return answer;
}
+ /**
+ * Returns the declared value type for the supplied column.
+ *
+ * @param columnIndex the column index
+ * @return the column value type
+ */
@SuppressWarnings("rawtypes")
@Override
public Class getColumnClass(int columnIndex) {
return getColumnModel(columnIndex).getType();
}
+ /**
+ * Indicates whether the supplied cell can be edited through its column model.
+ *
+ * @param rowIndex the row index
+ * @param columnIndex the column index
+ * @return {@code true} when the column model is editable
+ */
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return getColumnModel(columnIndex).isEditable();
}
+ /**
+ * Reads the value for the supplied row and column.
+ *
+ * @param rowIndex the row index
+ * @param columnIndex the column index
+ * @return the cell value, or {@code null} when the coordinates are invalid
+ */
@SuppressWarnings("rawtypes")
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
@@ -189,6 +225,13 @@ public class DefaultTableModel extends AbstractTableModel {
return column.getValue(row, rowIndex, columnIndex);
}
+ /**
+ * Writes a value to the supplied row and column when both coordinates are valid.
+ *
+ * @param value the new cell value
+ * @param rowIndex the row index
+ * @param columnIndex the column index
+ */
@SuppressWarnings("rawtypes")
@Override
public void setValueAt(Object value, int rowIndex, int columnIndex) {
@@ -237,22 +280,33 @@ public class DefaultTableModel extends AbstractTableModel {
* Column model implementation that keeps model indexes aligned with the current column order.
*/
protected static class MyTableColumnModel extends DefaultTableColumnModel {
- @SuppressWarnings("rawtypes")
/**
* Returns the live list of table columns.
*
* @return the backing column list
*/
+ @SuppressWarnings("rawtypes")
public List getColumnList() {
return tableColumns;
}
+ /**
+ * Removes a column and then renumbers the remaining model indexes.
+ *
+ * @param column the column to remove
+ */
@Override
public void removeColumn(TableColumn column) {
super.removeColumn(column);
renumberTableColumns();
}
+ /**
+ * Moves a column and then renumbers the model indexes to match the new order.
+ *
+ * @param columnIndex the source column index
+ * @param newIndex the destination column index
+ */
@Override
public void moveColumn(int columnIndex, int newIndex) {
super.moveColumn(columnIndex, newIndex);
diff --git a/subprojects/groovy-swing/src/main/java/groovy/swing/model/PropertyModel.java b/subprojects/groovy-swing/src/main/java/groovy/swing/model/PropertyModel.java
index e980e16626..2ec52e8844 100644
--- a/subprojects/groovy-swing/src/main/java/groovy/swing/model/PropertyModel.java
+++ b/subprojects/groovy-swing/src/main/java/groovy/swing/model/PropertyModel.java
@@ -79,6 +79,11 @@ public class PropertyModel implements ValueModel, NestedValueModel {
return property;
}
+ /**
+ * Returns the model that supplies the owning object for the bound property.
+ *
+ * @return the nested source model
+ */
@Override
public ValueModel getSourceModel() {
return sourceModel;
diff --git a/subprojects/groovy-swing/src/main/java/groovy/swing/model/ValueHolder.java b/subprojects/groovy-swing/src/main/java/groovy/swing/model/ValueHolder.java
index 3f1af4c4a5..3266099be5 100644
--- a/subprojects/groovy-swing/src/main/java/groovy/swing/model/ValueHolder.java
+++ b/subprojects/groovy-swing/src/main/java/groovy/swing/model/ValueHolder.java
@@ -78,6 +78,11 @@ public class ValueHolder implements ValueModel {
}
+ /**
+ * Returns the current stored value.
+ *
+ * @return the current value
+ */
@Override
public Object getValue() {
return value;
@@ -97,11 +102,21 @@ public class ValueHolder implements ValueModel {
}
}
+ /**
+ * Returns the declared value type for this holder.
+ *
+ * @return the holder type
+ */
@Override
public Class getType() {
return type;
}
+ /**
+ * Indicates whether callers should treat this holder as writable.
+ *
+ * @return {@code true} when the holder is editable
+ */
@Override
public boolean isEditable() {
return editable;
diff --git a/subprojects/groovy-swing/src/main/java/groovy/swing/table/TableMap.java b/subprojects/groovy-swing/src/main/java/groovy/swing/table/TableMap.java
index 1414060537..9a9a059f9b 100644
--- a/subprojects/groovy-swing/src/main/java/groovy/swing/table/TableMap.java
+++ b/subprojects/groovy-swing/src/main/java/groovy/swing/table/TableMap.java
@@ -60,37 +60,80 @@ public class TableMap extends AbstractTableModel implements TableModelListener {
// By default, Implement TableModel by forwarding all messages
// to the model.
+ /**
+ * Returns the value from the wrapped model at the supplied coordinates.
+ *
+ * @param aRow the source row index
+ * @param aColumn the source column index
+ * @return the delegate value
+ */
@Override
public Object getValueAt(int aRow, int aColumn) {
return model.getValueAt(aRow, aColumn);
}
+ /**
+ * Writes a value through to the wrapped model.
+ *
+ * @param aValue the new cell value
+ * @param aRow the source row index
+ * @param aColumn the source column index
+ */
@Override
public void setValueAt(Object aValue, int aRow, int aColumn) {
model.setValueAt(aValue, aRow, aColumn);
}
+ /**
+ * Returns the current row count from the wrapped model.
+ *
+ * @return the delegate row count, or {@code 0} when no model is set
+ */
@Override
public int getRowCount() {
return (model == null) ? 0 : model.getRowCount();
}
+ /**
+ * Returns the current column count from the wrapped model.
+ *
+ * @return the delegate column count, or {@code 0} when no model is set
+ */
@Override
public int getColumnCount() {
return (model == null) ? 0 : model.getColumnCount();
}
+ /**
+ * Returns the delegate column name for the supplied index.
+ *
+ * @param aColumn the source column index
+ * @return the delegate column name
+ */
@Override
public String getColumnName(int aColumn) {
return model.getColumnName(aColumn);
}
+ /**
+ * Returns the delegate column class for the supplied index.
+ *
+ * @param aColumn the source column index
+ * @return the delegate column type
+ */
@SuppressWarnings("rawtypes")
@Override
public Class getColumnClass(int aColumn) {
return model.getColumnClass(aColumn);
}
+ /**
+ * Indicates whether the delegate model allows editing for the supplied cell.
+ *
+ * @param row the source row index
+ * @param column the source column index
+ * @return {@code true} when the delegate cell is editable
+ */
@Override
public boolean isCellEditable(int row, int column) {
return model.isCellEditable(row, column);
diff --git a/subprojects/groovy-swing/src/main/java/groovy/swing/table/TableSorter.java b/subprojects/groovy-swing/src/main/java/groovy/swing/table/TableSorter.java
index 141de3400f..f2c33b2e2c 100644
--- a/subprojects/groovy-swing/src/main/java/groovy/swing/table/TableSorter.java
+++ b/subprojects/groovy-swing/src/main/java/groovy/swing/table/TableSorter.java
@@ -82,6 +82,11 @@ public class TableSorter extends TableMap {
setModel(model);
}
+ /**
+ * Replaces the wrapped model and rebuilds the cached row index mapping.
+ *
+ * @param model the model to sort
+ */
@Override
public void setModel(TableModel model) {
super.setModel(model);
@@ -218,6 +223,11 @@ public class TableSorter extends TableMap {
indexes[row] = row;
}
+ /**
+ * Rebuilds the cached row mapping after any delegate table-model change.
+ *
+ * @param e the table-model event
+ */
@Override
public void tableChanged(TableModelEvent e) {
reallocateIndexes();
@@ -329,12 +339,26 @@ public class TableSorter extends TableMap {
// The mapping only affects the contents of the data rows.
// Pass all requests to these rows through the mapping array: "indexes".
+ /**
+ * Returns the value from the source row mapped to the supplied view row.
+ *
+ * @param aRow the sorted view row
+ * @param aColumn the model column
+ * @return the mapped cell value
+ */
@Override
public Object getValueAt(int aRow, int aColumn) {
checkModel();
return model.getValueAt(indexes[aRow], aColumn);
}
+ /**
+ * Writes a value to the source row mapped from the supplied view row.
+ *
+ * @param aValue the new cell value
+ * @param aRow the sorted view row
+ * @param aColumn the model column
+ */
@Override
public void setValueAt(Object aValue, int aRow, int aColumn) {
checkModel();
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/AbstractFullBinding.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/AbstractFullBinding.java
index acba02b55f..74861e0e28 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/AbstractFullBinding.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/AbstractFullBinding.java
@@ -69,6 +69,9 @@ public abstract class AbstractFullBinding implements FullBinding {
targetBinding.updateTargetValue(result);
}
+ /**
+ * Propagates the current source value to the target.
+ */
@Override
public void update() {
fireBinding();
@@ -85,6 +88,9 @@ public abstract class AbstractFullBinding implements FullBinding {
((TargetBinding)sourceBinding).updateTargetValue(result);
}
+ /**
+ * Propagates the current target value back to the source.
+ */
@Override
public void reverseUpdate() {
fireReverseBinding();
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/AggregateBinding.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/AggregateBinding.java
index b342080df7..3cad3dc593 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/AggregateBinding.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/AggregateBinding.java
@@ -59,6 +59,9 @@ public class AggregateBinding implements BindingUpdatable {
bindings.remove(binding);
}
+ /**
+ * Binds every member binding in insertion order.
+ */
@Override
public void bind() {
if (!bound) {
@@ -69,6 +72,9 @@ public class AggregateBinding implements BindingUpdatable {
}
}
+ /**
+ * Unbinds every member binding in insertion order.
+ */
@Override
public void unbind() {
if (bound) {
@@ -79,6 +85,9 @@ public class AggregateBinding implements BindingUpdatable {
}
}
+ /**
+ * Rebinds every member binding when the aggregate is currently active.
+ */
@Override
public void rebind() {
if (bound) {
@@ -87,6 +96,9 @@ public class AggregateBinding implements BindingUpdatable {
}
}
+ /**
+ * Pushes source updates through every member binding.
+ */
@Override
public void update() {
for (BindingUpdatable binding : bindings) {
@@ -94,6 +106,9 @@ public class AggregateBinding implements BindingUpdatable {
}
}
+ /**
+ * Pushes reverse updates through every member binding.
+ */
@Override
public void reverseUpdate() {
for (BindingUpdatable binding : bindings) {
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/BindPath.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/BindPath.java
index 4f1d5cfe42..a3aa247336 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/BindPath.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/BindPath.java
@@ -151,7 +151,13 @@ public class BindPath {
return newValue;
}
+ /**
+ * Signature used for property-specific {@code addPropertyChangeListener} lookups.
+ */
static final Class[] NAME_PARAMS = {String.class, PropertyChangeListener.class};
+ /**
+ * Signature used for global {@code addPropertyChangeListener} lookups.
+ */
static final Class[] GLOBAL_PARAMS = {PropertyChangeListener.class};
/**
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/BindingProxy.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/BindingProxy.java
index 498b7cd3f1..a7b69b018b 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/BindingProxy.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/BindingProxy.java
@@ -133,6 +133,9 @@ public class BindingProxy extends GroovyObjectSupport implements BindingUpdatabl
throw new ReadOnlyPropertyException(property, getModel().getClass());
}
+ /**
+ * Binds every generated full binding managed by this proxy.
+ */
@Override
public void bind() {
synchronized (generatedBindings) {
@@ -146,6 +149,9 @@ public class BindingProxy extends GroovyObjectSupport implements BindingUpdatabl
}
}
+ /**
+ * Unbinds every generated full binding managed by this proxy.
+ */
@Override
public void unbind() {
synchronized (generatedBindings) {
@@ -159,6 +165,9 @@ public class BindingProxy extends GroovyObjectSupport implements BindingUpdatabl
}
}
+ /**
+ * Rebinds every generated full binding while preserving the current bound state.
+ */
@Override
public void rebind() {
synchronized (generatedBindings) {
@@ -171,6 +180,9 @@ public class BindingProxy extends GroovyObjectSupport implements BindingUpdatabl
}
}
+ /**
+ * Pushes updates through every generated full binding.
+ */
@Override
public void update() {
synchronized (generatedBindings) {
@@ -181,6 +193,9 @@ public class BindingProxy extends GroovyObjectSupport implements BindingUpdatabl
}
}
+ /**
+ * Pushes reverse updates through every generated full binding.
+ */
@Override
public void reverseUpdate() {
synchronized (generatedBindings) {
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/ClosureSourceBinding.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/ClosureSourceBinding.java
index eb6b535f10..26c88b3d7b 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/ClosureSourceBinding.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/ClosureSourceBinding.java
@@ -76,6 +76,11 @@ public class ClosureSourceBinding implements SourceBinding {
this.closure = closure;
}
+ /**
+ * Invokes the configured closure with the current argument list.
+ *
+ * @return the computed source value
+ */
@Override
public Object getSourceValue() {
return closure.call(arguments);
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/MutualPropertyBinding.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/MutualPropertyBinding.java
index 2ad29e25dd..aa7742bbe0 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/MutualPropertyBinding.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/MutualPropertyBinding.java
@@ -92,16 +92,31 @@ public class MutualPropertyBinding implements FullBinding {
rebuildBindings();
}
+ /**
+ * Returns the forward source-side property binding.
+ *
+ * @return the source binding
+ */
@Override
public SourceBinding getSourceBinding() {
return sourceBinding;
}
+ /**
+ * Returns the forward target-side property binding.
+ *
+ * @return the target binding
+ */
@Override
public TargetBinding getTargetBinding() {
return targetBinding;
}
+ /**
+ * Replaces the source-side property binding and rebuilds the paired bindings.
+ *
+ * @param sourceBinding the new source binding
+ */
@Override
public void setSourceBinding(SourceBinding sourceBinding) {
try {
@@ -117,6 +132,11 @@ public class MutualPropertyBinding implements FullBinding {
rebuildBindings();
}
+ /**
+ * Replaces the target-side property binding and rebuilds the paired bindings.
+ *
+ * @param targetBinding the new target binding
+ */
@Override
public void setTargetBinding(TargetBinding targetBinding) {
try {
@@ -132,34 +152,64 @@ public class MutualPropertyBinding implements FullBinding {
rebuildBindings();
}
+ /**
+ * Replaces the validator applied to forward updates.
+ *
+ * @param validator the validator closure, or {@code null}
+ */
@Override
public void setValidator(Closure validator) {
this.validator = validator;
rebuildBindings();
}
+ /**
+ * Returns the validator applied to forward updates.
+ *
+ * @return the validator closure, or {@code null}
+ */
@Override
public Closure getValidator() {
return validator;
}
+ /**
+ * Replaces the converter applied from source to target.
+ *
+ * @param converter the forward converter, or {@code null}
+ */
@Override
public void setConverter(Closure converter) {
this.converter = converter;
rebuildBindings();
}
+ /**
+ * Returns the converter applied from source to target.
+ *
+ * @return the forward converter, or {@code null}
+ */
@Override
public Closure getConverter() {
return converter;
}
+ /**
+ * Replaces the converter applied from target to source.
+ *
+ * @param reverseConverter the reverse converter, or {@code null}
+ */
@Override
public void setReverseConverter(Closure reverseConverter) {
- this.reverseConverter = reverseConverter;
+ this.reverseConverter = reverseConverter;
rebuildBindings();
}
+ /**
+ * Returns the converter applied from target to source.
+ *
+ * @return the reverse converter, or {@code null}
+ */
@Override
public Closure getReverseConverter() {
return reverseConverter;
@@ -205,6 +255,9 @@ public class MutualPropertyBinding implements FullBinding {
}
+ /**
+ * Binds both forward and reverse bindings when the pair is fully configured.
+ */
@Override
public void bind() {
if (!bound) {
@@ -228,6 +281,9 @@ public class MutualPropertyBinding implements FullBinding {
}
}
+ /**
+ * Unbinds both forward and reverse bindings.
+ */
@Override
public void unbind() {
if (bound) {
@@ -237,6 +293,9 @@ public class MutualPropertyBinding implements FullBinding {
}
}
+ /**
+ * Rebinds both forward and reverse bindings when currently active.
+ */
@Override
public void rebind() {
if (bound) {
@@ -245,11 +304,17 @@ public class MutualPropertyBinding implements FullBinding {
}
}
+ /**
+ * Pushes an update from the source side to the target side.
+ */
@Override
public void update() {
forwardBinding.update();
}
+ /**
+ * Pushes an update from the target side back to the source side.
+ */
@Override
public void reverseUpdate() {
reverseBinding.update();
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyBinding.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyBinding.java
index 3dc18ba113..f11b2be370 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyBinding.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyBinding.java
@@ -316,6 +316,11 @@ public class PropertyBinding implements SourceBinding, TargetBinding, TriggerBin
}
}
+ /**
+ * Reads the current value of the bound property from the bean.
+ *
+ * @return the current property value
+ */
@Override
public Object getSourceValue() {
return propertyAccessor().read(bean, propertyName);
@@ -366,6 +371,11 @@ public class PropertyBinding implements SourceBinding, TargetBinding, TriggerBin
setTargetBinding(target);
}
+ /**
+ * Responds to observed property changes by pushing an updated value to the target.
+ *
+ * @param event the property change event
+ */
@Override
public void propertyChange(PropertyChangeEvent event) {
if (boundToProperty || event.getPropertyName().equals(boundProperty)) {
@@ -373,6 +383,9 @@ public class PropertyBinding implements SourceBinding, TargetBinding, TriggerBin
}
}
+ /**
+ * Starts listening for property changes on the current bean.
+ */
@Override
public void bind() {
if (!bound) {
@@ -393,6 +406,9 @@ public class PropertyBinding implements SourceBinding, TargetBinding, TriggerBin
}
}
+ /**
+ * Removes any property-change listeners installed by this binding.
+ */
@Override
public void unbind() {
if (bound) {
@@ -415,6 +431,9 @@ public class PropertyBinding implements SourceBinding, TargetBinding, TriggerBin
}
}
+ /**
+ * Rebinds property-change listeners when the binding is currently active.
+ */
@Override
public void rebind() {
if (bound) {
@@ -465,7 +484,30 @@ public class PropertyBinding implements SourceBinding, TargetBinding, TriggerBin
* Defines the thread on which target updates should run.
*/
public enum UpdateStrategy {
- MIXED, ASYNC, SYNC, SAME, OUTSIDE, DEFER;
+ /**
+ * Chooses a strategy dynamically based on the current execution context.
+ */
+ MIXED,
+ /**
+ * Always updates asynchronously.
+ */
+ ASYNC,
+ /**
+ * Always updates synchronously on the event-dispatch thread.
+ */
+ SYNC,
+ /**
+ * Updates on the calling thread.
+ */
+ SAME,
+ /**
+ * Updates synchronously off the event-dispatch thread.
+ */
+ OUTSIDE,
+ /**
+ * Defers updates until the event queue processes them.
+ */
+ DEFER;
/**
* Resolves an update strategy name.
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyChangeProxyTargetBinding.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyChangeProxyTargetBinding.java
index 6b13f7f3b9..5d24c49c5f 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyChangeProxyTargetBinding.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyChangeProxyTargetBinding.java
@@ -53,6 +53,11 @@ public class PropertyChangeProxyTargetBinding implements TargetBinding {
this.listener = listener;
}
+ /**
+ * Forwards a synthetic property-change event containing the supplied target value.
+ *
+ * @param value the new property value to report
+ */
@Override
public void updateTargetValue(Object value) {
listener.propertyChange(new PropertyChangeEvent(proxyObject, propertyName,
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyPathFullBinding.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyPathFullBinding.java
index 0ff2c5fbe5..861aec8269 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyPathFullBinding.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/PropertyPathFullBinding.java
@@ -43,6 +43,9 @@ public class PropertyPathFullBinding extends AbstractFullBinding implements Prop
*/
boolean bound;
+ /**
+ * Attaches listeners across every configured bind path.
+ */
@Override
public void bind() {
updateObjects.clear();
@@ -52,6 +55,9 @@ public class PropertyPathFullBinding extends AbstractFullBinding implements Prop
bound = true;
}
+ /**
+ * Removes listeners from every configured bind path.
+ */
@Override
public void unbind() {
updateObjects.clear();
@@ -63,11 +69,19 @@ public class PropertyPathFullBinding extends AbstractFullBinding implements Prop
bound = false;
}
+ /**
+ * Rebuilds listener registrations when the binding is currently active.
+ */
@Override
public void rebind() {
if (bound) bind();
}
+ /**
+ * Refreshes bind-path listeners and propagates the resulting value change.
+ *
+ * @param evt the property change event that triggered the refresh
+ */
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (updateObjects.contains(evt.getSource())) {
diff --git a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/SwingTimerTriggerBinding.java b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/SwingTimerTriggerBinding.java
index a929ced8f1..66142a5b2e 100644
--- a/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/SwingTimerTriggerBinding.java
+++ b/subprojects/groovy-swing/src/main/java/org/apache/groovy/swing/binding/SwingTimerTriggerBinding.java
@@ -121,6 +121,9 @@ class SwingTimerFullBinding extends AbstractFullBinding implements ActionListene
timer.start();
}
+ /**
+ * Starts the timer and begins producing timed updates.
+ */
@Override
public void bind() {
if (!bound) {
@@ -129,6 +132,9 @@ class SwingTimerFullBinding extends AbstractFullBinding implements ActionListene
}
}
+ /**
+ * Stops the timer and marks the binding as inactive.
+ */
@Override
public void unbind() {
if (bound) {
@@ -137,6 +143,9 @@ class SwingTimerFullBinding extends AbstractFullBinding implements ActionListene
}
}
+ /**
+ * Restarts the timer when the binding is already active.
+ */
@Override
public void rebind() {
if (bound) {
@@ -144,6 +153,11 @@ class SwingTimerFullBinding extends AbstractFullBinding implements ActionListene
}
}
+ /**
+ * Calculates the current timer progress value and pushes it to the target binding.
+ *
+ * @param e the timer event
+ */
@Override
public void actionPerformed(ActionEvent e) {
long currentTime = System.currentTimeMillis();
diff --git a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/IncludeType.java b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/IncludeType.java
index 4e4410d851..ac8eb25a5f 100644
--- a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/IncludeType.java
+++ b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/IncludeType.java
@@ -22,8 +22,17 @@ package groovy.text.markup;
* An enumeration used internally to map include types to {@link groovy.text.markup.BaseTemplate} method calls.
*/
enum IncludeType {
- template("includeGroovy"), // includes another Groovy template
- escaped("includeEscaped"), // includes raw content, escaped before rendering
+ /**
+ * Includes another Groovy template.
+ */
+ template("includeGroovy"),
+ /**
+ * Includes raw content after escaping it for markup output.
+ */
+ escaped("includeEscaped"),
+ /**
+ * Includes raw content without escaping it.
+ */
unescaped("includeUnescaped");
private final String methodName;
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Ackermann.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Ackermann.groovy
index 61470ee61a..cfdcb78ede 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Ackermann.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Ackermann.groovy
@@ -18,8 +18,17 @@
*/
package org.apache.groovy.bench
+/**
+ * Helper class providing Ackermann function implementation for benchmarking.
+ */
class Ackermann {
+ /**
+ * Computes the Ackermann function for given m and n values.
+ * @param m the first parameter
+ * @param n the second parameter
+ * @return the computed Ackermann value
+ */
static int ack(int m, int n) {
if (m == 0) return n + 1
if (n == 0) return ack(m - 1, 1)
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/AckermannBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/AckermannBench.java
index 4e04dd60fd..e014a17c28 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/AckermannBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/AckermannBench.java
@@ -31,6 +31,9 @@ import org.openjdk.jmh.annotations.Warmup;
import java.util.concurrent.TimeUnit;
+/**
+ * Benchmark comparing Java and Groovy implementations of the Ackermann function.
+ */
@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Fork(2)
@@ -42,11 +45,19 @@ public class AckermannBench {
@Param({"5", "6", "7", "8"})
private int n;
+ /**
+ * Baseline Java implementation of Ackermann function.
+ * @return the computed value
+ */
@Benchmark
public int java() {
return JavaAckermann.ack(3, n);
}
+ /**
+ * Groovy dynamic implementation of Ackermann function.
+ * @return the computed value
+ */
@Benchmark
public int groovy() {
return Ackermann.ack(3, n);
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Ary.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Ary.groovy
index 89681388ed..9618a2dc31 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Ary.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Ary.groovy
@@ -20,8 +20,16 @@ package org.apache.groovy.bench
import groovy.transform.CompileStatic
+/**
+ * Helper class providing array manipulation benchmark implementations.
+ */
class Ary {
+ /**
+ * Performs array operations in dynamic Groovy mode.
+ * @param n the size of the arrays
+ * @return the sum of first and last elements
+ */
static int ary(int n) {
int[] x = new int[n]
int[] y = new int[n]
@@ -35,6 +43,11 @@ class Ary {
return y[0] + y[n-1]
}
+ /**
+ * Performs array operations in {@code @CompileStatic} mode.
+ * @param n the size of the arrays
+ * @return the sum of first and last elements
+ */
@CompileStatic
static int aryCS(int n) {
int[] x = new int[n]
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/AryBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/AryBench.java
index f08e6d8d3f..7082f9d202 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/AryBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/AryBench.java
@@ -31,6 +31,9 @@ import org.openjdk.jmh.annotations.Warmup;
import java.util.concurrent.TimeUnit;
+/**
+ * Benchmark comparing Java, Groovy, and Groovy {@code @CompileStatic} array operations.
+ */
@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Fork(2)
@@ -42,16 +45,28 @@ public class AryBench {
@Param({"10", "100", "1000", "1000000"})
private int n;
+ /**
+ * Baseline Java array operations.
+ * @return the sum of first and last elements
+ */
@Benchmark
public int java() {
return JavaAry.ary(n);
}
+ /**
+ * Groovy dynamic array operations.
+ * @return the sum of first and last elements
+ */
@Benchmark
public int groovy() {
return Ary.ary(n);
}
+ /**
+ * Groovy {@code @CompileStatic} array operations.
+ * @return the sum of first and last elements
+ */
@Benchmark
public int groovyCS() {
return Ary.aryCS(n);
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Fibo.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Fibo.groovy
index 4602599766..5e5babad38 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Fibo.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/Fibo.groovy
@@ -18,8 +18,16 @@
*/
package org.apache.groovy.bench
+/**
+ * Helper class providing Fibonacci function implementation for benchmarking.
+ */
class Fibo {
+ /**
+ * Computes the nth Fibonacci number recursively.
+ * @param n the position in the Fibonacci sequence
+ * @return the Fibonacci value at position n
+ */
static int fib(int n) {
if (n < 2) return 1
return fib(n - 2) + fib(n - 1)
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/FiboBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/FiboBench.java
index 9d9ab6120b..86c8d38c99 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/FiboBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/FiboBench.java
@@ -31,6 +31,9 @@ import org.openjdk.jmh.annotations.Warmup;
import java.util.concurrent.TimeUnit;
+/**
+ * Benchmark comparing Java and Groovy implementations of the Fibonacci function.
+ */
@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Fork(2)
@@ -42,11 +45,19 @@ public class FiboBench {
@Param({"30", "31", "32", "33", "34"})
private int n;
+ /**
+ * Baseline Java Fibonacci implementation.
+ * @return the computed Fibonacci value
+ */
@Benchmark
public int java() {
return JavaFibo.fib(n);
}
+ /**
+ * Groovy dynamic Fibonacci implementation.
+ * @return the computed Fibonacci value
+ */
@Benchmark
public int groovy() {
return Fibo.fib(n);
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/GeneratedHashCode.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/GeneratedHashCode.groovy
index e67cd50147..088ed10099 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/GeneratedHashCode.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/GeneratedHashCode.groovy
@@ -21,10 +21,15 @@ package org.apache.groovy.bench
import groovy.transform.EqualsAndHashCode
+/**
+ * Test class for benchmarking generated hashCode/equals methods with null properties.
+ */
@EqualsAndHashCode(includeFields = true)
class GeneratedHashCode {
private String field
+
+ /** Property included in generated hash-code benchmarks. */
String property
}
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/GeneratedHashCodeBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/GeneratedHashCodeBench.java
index 793efdd267..c7fb342523 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/GeneratedHashCodeBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/GeneratedHashCodeBench.java
@@ -28,6 +28,9 @@ import org.openjdk.jmh.annotations.Warmup;
import java.util.concurrent.TimeUnit;
+/**
+ * Benchmark for generated hashCode on instances with null properties.
+ */
@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Fork(2)
@@ -35,6 +38,10 @@ import java.util.concurrent.TimeUnit;
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class GeneratedHashCodeBench {
+ /**
+ * Tests hashCode performance on a freshly-created instance with null properties.
+ * @return the computed hash code
+ */
@Benchmark
public int generated_hashcode_on_instance_with_null_properties() {
return new GeneratedHashCode().hashCode();
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/NonCapturingLambda.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/NonCapturingLambda.groovy
index 22df7763ae..3fcf448296 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/NonCapturingLambda.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/NonCapturingLambda.groovy
@@ -25,24 +25,47 @@ import java.util.function.Function
import java.util.function.IntUnaryOperator
import java.util.stream.IntStream
+/**
+ * Helper class for benchmarking non-capturing lambda optimization (GROOVY-11905).
+ */
@CompileStatic
class NonCapturingLambda {
+ /**
+ * Applies a non-capturing lambda that adds 1 to the input.
+ * @param x the input value
+ * @return x plus 1
+ */
static int applyNonCapturingLambda(int x) {
IntUnaryOperator op = (int i) -> i + 1
op.applyAsInt(x)
}
+ /**
+ * Applies a capturing lambda that adds an offset to the input.
+ * @param x the input value
+ * @return x plus the captured offset
+ */
static int applyCapturingLambda(int x) {
int offset = 1
IntUnaryOperator op = (int i) -> i + offset
op.applyAsInt(x)
}
+ /**
+ * Maps each element using a non-capturing lambda.
+ * @param input the input list
+ * @return a new list with each element incremented by 1
+ */
static List<Integer> streamMapNonCapturing(List<Integer> input) {
input.stream().map(e -> (Integer) (e + 1)).toList()
}
+ /**
+ * Reduces a range using a non-capturing lambda.
+ * @param n the upper bound of the range (inclusive)
+ * @return the sum of doubled values from 1 to n
+ */
static int streamReduceNonCapturing(int n) {
IntStream.rangeClosed(1, n).map((int i) -> i * 2).sum()
}
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/NonCapturingLambdaBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/NonCapturingLambdaBench.java
index d038b8c8b5..c6d87952cb 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/NonCapturingLambdaBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/NonCapturingLambdaBench.java
@@ -44,21 +44,37 @@ import java.util.concurrent.TimeUnit;
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class NonCapturingLambdaBench {
+ /**
+ * Benchmark non-capturing lambda application.
+ * @return the result value
+ */
@Benchmark
public int nonCapturingLambdaApply() {
return NonCapturingLambda.applyNonCapturingLambda(42);
}
+ /**
+ * Benchmark capturing lambda application.
+ * @return the result value
+ */
@Benchmark
public int capturingLambdaApply() {
return NonCapturingLambda.applyCapturingLambda(42);
}
+ /**
+ * Benchmark stream map with non-capturing lambda.
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void streamMapNonCapturing(Blackhole bh) {
bh.consume(NonCapturingLambda.streamMapNonCapturing(List.of(1, 2, 3, 4, 5)));
}
+ /**
+ * Benchmark stream reduce with non-capturing lambda.
+ * @return the sum
+ */
@Benchmark
public int streamReduceNonCapturing() {
return NonCapturingLambda.streamReduceNonCapturing(100);
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndy.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndy.groovy
index 5024e1e853..34029fdc97 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndy.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndy.groovy
@@ -34,10 +34,21 @@ class StaticMethodCallIndy {
// ---------- Dynamic Groovy — invokedynamic call sites ----------
+ /**
+ * Adds two integers.
+ * @param a the first operand
+ * @param b the second operand
+ * @return a plus b
+ */
static int staticAdd(int a, int b) {
return a + b
}
+ /**
+ * Computes sum from 0 to n-1 by repeated static method calls.
+ * @param n the upper bound (exclusive)
+ * @return the sum
+ */
static int staticSum(int n) {
int sum = 0
for (int i = 0; i < n; i++) {
@@ -46,25 +57,63 @@ class StaticMethodCallIndy {
return sum
}
+ /**
+ * Computes the nth Fibonacci number recursively.
+ * @param n the position in the sequence
+ * @return the Fibonacci value
+ */
static int staticFib(int n) {
if (n < 2) return n
return staticFib(n - 1) + staticFib(n - 2)
}
+ /**
+ * Squares an integer.
+ * @param x the input value
+ * @return x squared
+ */
static int staticSquare(int x) { return x * x }
+
+ /**
+ * Increments an integer by 1.
+ * @param x the input value
+ * @return x plus 1
+ */
static int staticIncrement(int x) { return x + 1 }
+
+ /**
+ * Doubles an integer.
+ * @param x the input value
+ * @return x times 2
+ */
static int staticDouble(int x) { return x * 2 }
+ /**
+ * Chains three static method calls.
+ * @param x the input value
+ * @return double(increment(square(x)))
+ */
static int staticChain(int x) {
return staticDouble(staticIncrement(staticSquare(x)))
}
// ---------- Instance methods — no early setTarget ----------
+ /**
+ * Adds two integers (instance method).
+ * @param a the first operand
+ * @param b the second operand
+ * @return a plus b
+ */
int instanceAdd(int a, int b) {
return a + b
}
+ /**
+ * Computes sum from 0 to n-1 by repeated instance method calls.
+ * @param n the upper bound (exclusive)
+ * @return the sum
+ */
int instanceSum(int n) {
int sum = 0
for (int i = 0; i < n; i++) {
@@ -73,26 +122,64 @@ class StaticMethodCallIndy {
return sum
}
+ /**
+ * Computes the nth Fibonacci number recursively (instance method).
+ * @param n the position in the sequence
+ * @return the Fibonacci value
+ */
int instanceFib(int n) {
if (n < 2) return n
return instanceFib(n - 1) + instanceFib(n - 2)
}
+ /**
+ * Squares an integer (instance method).
+ * @param x the input value
+ * @return x squared
+ */
int instanceSquare(int x) { return x * x }
+
+ /**
+ * Increments an integer by 1 (instance method).
+ * @param x the input value
+ * @return x plus 1
+ */
int instanceIncrement(int x) { return x + 1 }
+
+ /**
+ * Doubles an integer (instance method).
+ * @param x the input value
+ * @return x times 2
+ */
int instanceDouble(int x) { return x * 2 }
+ /**
+ * Chains three instance method calls.
+ * @param x the input value
+ * @return double(increment(square(x)))
+ */
int instanceChain(int x) {
return instanceDouble(instanceIncrement(instanceSquare(x)))
}
// ---------- @CompileStatic — invokestatic, no invokedynamic ----------
+ /**
+ * Adds two integers ({@code @CompileStatic}).
+ * @param a the first operand
+ * @param b the second operand
+ * @return a plus b
+ */
@CompileStatic
static int staticAddCS(int a, int b) {
return a + b
}
+ /**
+ * Computes sum from 0 to n-1 ({@code @CompileStatic}).
+ * @param n the upper bound (exclusive)
+ * @return the sum
+ */
@CompileStatic
static int staticSumCS(int n) {
int sum = 0
@@ -102,21 +189,46 @@ class StaticMethodCallIndy {
return sum
}
+ /**
+ * Computes the nth Fibonacci number recursively ({@code @CompileStatic}).
+ * @param n the position in the sequence
+ * @return the Fibonacci value
+ */
@CompileStatic
static int staticFibCS(int n) {
if (n < 2) return n
return staticFibCS(n - 1) + staticFibCS(n - 2)
}
+ /**
+ * Squares an integer ({@code @CompileStatic}).
+ * @param x the input value
+ * @return x squared
+ */
@CompileStatic
static int staticSquareCS(int x) { return x * x }
+ /**
+ * Increments an integer by 1 ({@code @CompileStatic}).
+ * @param x the input value
+ * @return x plus 1
+ */
@CompileStatic
static int staticIncrementCS(int x) { return x + 1 }
+ /**
+ * Doubles an integer ({@code @CompileStatic}).
+ * @param x the input value
+ * @return x times 2
+ */
@CompileStatic
static int staticDoubleCS(int x) { return x * 2 }
+ /**
+ * Chains three static method calls ({@code @CompileStatic}).
+ * @param x the input value
+ * @return double(increment(square(x)))
+ */
@CompileStatic
static int staticChainCS(int x) {
return staticDoubleCS(staticIncrementCS(staticSquareCS(x)))
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndyBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndyBench.java
index 918fc3f71e..dbf38188f4 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndyBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndyBench.java
@@ -62,6 +62,9 @@ public class StaticMethodCallIndyBench {
private StaticMethodCallIndy instance;
+ /**
+ * Creates the helper instance used by the instance-method benchmark variants.
+ */
@Setup
public void setUp() {
instance = new StaticMethodCallIndy();
@@ -69,21 +72,37 @@ public class StaticMethodCallIndyBench {
// ---- loop with static call: sum(0..n) via repeated add ----
+ /**
+ * Java baseline: static sum via repeated add.
+ * @return the computed sum
+ */
@Benchmark
public int staticSum_java() {
return JavaStaticMethods.sum(SUM_N);
}
+ /**
+ * Groovy dynamic: static sum via repeated add.
+ * @return the computed sum
+ */
@Benchmark
public int staticSum_groovy() {
return StaticMethodCallIndy.staticSum(SUM_N);
}
+ /**
+ * Groovy {@code @CompileStatic}: static sum via repeated add.
+ * @return the computed sum
+ */
@Benchmark
public int staticSum_groovyCS() {
return StaticMethodCallIndy.staticSumCS(SUM_N);
}
+ /**
+ * Groovy dynamic: instance sum via repeated add (control group).
+ * @return the computed sum
+ */
@Benchmark
public int instanceSum_groovy() {
return instance.instanceSum(SUM_N);
@@ -91,21 +110,37 @@ public class StaticMethodCallIndyBench {
// ---- recursive static call: Fibonacci ----
+ /**
+ * Java baseline: recursive Fibonacci.
+ * @return the computed Fibonacci value
+ */
@Benchmark
public int staticFib_java() {
return JavaStaticMethods.fib(FIB_N);
}
+ /**
+ * Groovy dynamic: recursive static Fibonacci.
+ * @return the computed Fibonacci value
+ */
@Benchmark
public int staticFib_groovy() {
return StaticMethodCallIndy.staticFib(FIB_N);
}
+ /**
+ * Groovy {@code @CompileStatic}: recursive static Fibonacci.
+ * @return the computed Fibonacci value
+ */
@Benchmark
public int staticFib_groovyCS() {
return StaticMethodCallIndy.staticFibCS(FIB_N);
}
+ /**
+ * Groovy dynamic: instance Fibonacci (control group).
+ * @return the computed Fibonacci value
+ */
@Benchmark
public int instanceFib_groovy() {
return instance.instanceFib(FIB_N);
@@ -113,6 +148,10 @@ public class StaticMethodCallIndyBench {
// ---- chained static calls ----
+ /**
+ * Java baseline: chained static calls.
+ * @return the accumulated result
+ */
@Benchmark
public int staticChain_java() {
int result = 0;
@@ -122,6 +161,10 @@ public class StaticMethodCallIndyBench {
return result;
}
+ /**
+ * Groovy dynamic: chained static calls.
+ * @return the accumulated result
+ */
@Benchmark
public int staticChain_groovy() {
int result = 0;
@@ -131,6 +174,10 @@ public class StaticMethodCallIndyBench {
return result;
}
+ /**
+ * Groovy {@code @CompileStatic}: chained static calls.
+ * @return the accumulated result
+ */
@Benchmark
public int staticChain_groovyCS() {
int result = 0;
@@ -140,6 +187,10 @@ public class StaticMethodCallIndyBench {
return result;
}
+ /**
+ * Groovy dynamic: chained instance calls (control group).
+ * @return the accumulated result
+ */
@Benchmark
public int instanceChain_groovy() {
int result = 0;
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndyColdBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndyColdBench.java
index e6409eebf7..b2cfd857a6 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndyColdBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/StaticMethodCallIndyColdBench.java
@@ -82,23 +82,42 @@ import java.util.concurrent.TimeUnit;
public class StaticMethodCallIndyColdBench {
@Param({"500", "2000", "20000"})
+ /**
+ * Input size used to exercise different cold-start dispatch regimes.
+ */
public int n;
+ /**
+ * Java baseline for cold-start sum.
+ * @return the computed sum
+ */
@Benchmark
public int staticSum_java() {
return javaSum(n);
}
+ /**
+ * Groovy dynamic cold-start static sum.
+ * @return the computed sum
+ */
@Benchmark
public int staticSum_groovy() {
return StaticMethodCallIndy.staticSum(n);
}
+ /**
+ * Groovy {@code @CompileStatic} cold-start static sum.
+ * @return the computed sum
+ */
@Benchmark
public int staticSum_groovyCS() {
return StaticMethodCallIndy.staticSumCS(n);
}
+ /**
+ * Groovy instance cold-start sum (control group).
+ * @return the computed sum
+ */
@Benchmark
public int instanceSum_groovy() {
return new StaticMethodCallIndy().instanceSum(n);
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/dispatch/Callsite.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/dispatch/Callsite.groovy
index 9e0791b3a0..708f080d0b 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/dispatch/Callsite.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/dispatch/Callsite.groovy
@@ -21,14 +21,27 @@ package org.apache.groovy.bench.dispatch
import groovy.transform.CompileStatic
import org.openjdk.jmh.infra.Blackhole
+/**
+ * Helper class for benchmarking dynamic call site dispatch under different morphic states.
+ */
class Callsite {
+ /**
+ * Dispatches {@code hashCode()} calls through dynamic Groovy.
+ * @param receivers the array of receiver objects
+ * @param bh the blackhole for consuming results
+ */
static void dispatch(Object[] receivers, bh) {
for (Object receiver : receivers) {
bh.consume(receiver.hashCode())
}
}
+ /**
+ * Dispatches {@code hashCode()} calls through {@code @CompileStatic}.
+ * @param receivers the array of receiver objects
+ * @param bh the blackhole for consuming results
+ */
@CompileStatic
static void dispatchCS(Object[] receivers, Blackhole bh) {
for (Object receiver : receivers) {
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/dispatch/CallsiteBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/dispatch/CallsiteBench.java
index a6aa42bf61..268d91be39 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/dispatch/CallsiteBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/bench/dispatch/CallsiteBench.java
@@ -25,6 +25,10 @@ import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.TimeUnit;
+/**
+ * Benchmark comparing dispatch performance under monomorphic, polymorphic,
+ * and megamorphic call site conditions for Java, Groovy, and Groovy {@code @CompileStatic}.
+ */
@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Fork(2)
@@ -32,46 +36,91 @@ import java.util.concurrent.TimeUnit;
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class CallsiteBench {
+ /**
+ * Monomorphic dispatch via Groovy dynamic.
+ * @param state the monomorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_1_monomorphic_groovy(MonomorphicState state, Blackhole bh) {
Callsite.dispatch(state.receivers, bh);
}
+ /**
+ * Monomorphic dispatch via Groovy {@code @CompileStatic}.
+ * @param state the monomorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_1_monomorphic_groovyCS(MonomorphicState state, Blackhole bh) {
Callsite.dispatchCS(state.receivers, bh);
}
+ /**
+ * Monomorphic dispatch via Java baseline.
+ * @param state the monomorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_1_monomorphic_java(MonomorphicState state, Blackhole bh) {
JavaDispatch.dispatch(state.receivers, bh);
}
+ /**
+ * Polymorphic dispatch (3 types) via Groovy dynamic.
+ * @param state the polymorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_3_polymorphic_groovy(PolymorphicState state, Blackhole bh) {
Callsite.dispatch(state.receivers, bh);
}
+ /**
+ * Polymorphic dispatch (3 types) via Groovy {@code @CompileStatic}.
+ * @param state the polymorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_3_polymorphic_groovyCS(PolymorphicState state, Blackhole bh) {
Callsite.dispatchCS(state.receivers, bh);
}
+ /**
+ * Polymorphic dispatch (3 types) via Java baseline.
+ * @param state the polymorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_3_polymorphic_java(PolymorphicState state, Blackhole bh) {
JavaDispatch.dispatch(state.receivers, bh);
}
+ /**
+ * Megamorphic dispatch (8 types) via Groovy dynamic.
+ * @param state the megamorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_8_megamorphic_groovy(MegamorphicState state, Blackhole bh) {
Callsite.dispatch(state.receivers, bh);
}
+ /**
+ * Megamorphic dispatch (8 types) via Groovy {@code @CompileStatic}.
+ * @param state the megamorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_8_megamorphic_groovyCS(MegamorphicState state, Blackhole bh) {
Callsite.dispatchCS(state.receivers, bh);
}
+ /**
+ * Megamorphic dispatch (8 types) via Java baseline.
+ * @param state the megamorphic receiver state
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void dispatch_8_megamorphic_java(MegamorphicState state, Blackhole bh) {
JavaDispatch.dispatch(state.receivers, bh);
@@ -92,9 +141,19 @@ public class CallsiteBench {
new Receiver5(), new Receiver6(), new Receiver7(), new Receiver8()
};
+ /**
+ * State holder for monomorphic (single type) call sites.
+ */
@State(Scope.Thread)
public static class MonomorphicState {
+ /**
+ * Receiver array that always contains the same target type.
+ */
Object[] receivers;
+
+ /**
+ * Populates the receiver array with a single repeated target instance.
+ */
@Setup(Level.Trial)
public void setUp() {
receivers = new Object[RECEIVER_COUNT];
@@ -102,10 +161,24 @@ public class CallsiteBench {
}
}
+ /**
+ * State holder for polymorphic (3 types) call sites.
+ */
@State(Scope.Thread)
public static class PolymorphicState {
+ /**
+ * Source of randomized receiver selection for polymorphic dispatch.
+ */
final Random random = new Random();
+
+ /**
+ * Receiver array containing a mix of three target types.
+ */
Object[] receivers;
+
+ /**
+ * Rebuilds the receiver array for a three-type polymorphic distribution.
+ */
@Setup(Level.Iteration)
public void setUp() {
receivers = new Object[RECEIVER_COUNT];
@@ -115,10 +188,24 @@ public class CallsiteBench {
}
}
+ /**
+ * State holder for megamorphic (8 types) call sites.
+ */
@State(Scope.Thread)
public static class MegamorphicState {
+ /**
+ * Source of randomized receiver selection for megamorphic dispatch.
+ */
final Random random = new Random();
+
+ /**
+ * Receiver array containing a mix of all benchmark target types.
+ */
Object[] receivers;
+
+ /**
+ * Rebuilds the receiver array for an eight-type megamorphic distribution.
+ */
@Setup(Level.Iteration)
public void setUp() {
receivers = new Object[RECEIVER_COUNT];
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/ClosureBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/ClosureBench.groovy
index 77382f1054..c2e6422939 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/ClosureBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/ClosureBench.groovy
@@ -36,8 +36,10 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class ClosureBench {
+ /** Number of loop iterations used by each benchmark invocation. */
static final int ITERATIONS = 1_000_000
+ /** Instance property for delegation tests. */
String instanceProperty = "instance"
/**
@@ -210,6 +212,12 @@ class ClosureBench {
bh.consume(sum)
}
+ /**
+ * Helper method accepting a closure parameter.
+ * @param value the input value
+ * @param operation the closure to apply
+ * @return the result of applying the closure
+ */
static int applyOperation(int value, Closure<Integer> operation) {
operation(value)
}
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GStringBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GStringBench.groovy
index f998f71eca..71bfb675b4 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GStringBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GStringBench.groovy
@@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class GStringBench {
+ /** Number of loop iterations used by each benchmark invocation. */
static final int ITERATIONS = 1_000_000
/**
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GroovyIdiomBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GroovyIdiomBench.groovy
index e93ed86132..4def60402e 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GroovyIdiomBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/GroovyIdiomBench.groovy
@@ -35,24 +35,43 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class GroovyIdiomBench {
+ /** Number of loop iterations used by each benchmark invocation. */
static final int ITERATIONS = 1_000_000
- // Helper class for safe-nav / spread-dot / with tests
+ /**
+ * Helper class for safe-nav / spread-dot / with tests.
+ */
static class Person {
+ /** Person name used by safe-navigation and spread-dot benchmarks. */
String name
+
+ /** Address associated with the person, when present. */
Address address
}
+ /**
+ * Helper class for nested property access tests.
+ */
static class Address {
+ /** City value used for nested property access. */
String city
+
+ /** Postal code paired with the benchmark city value. */
String zip
}
- // Pre-built test data
+ /** Person with a non-null address. */
Person personWithAddress
+
+ /** Person with a null address for safe-nav null path testing. */
Person personNullAddress
+
+ /** List of people for spread-dot tests. */
List<Person> people
+ /**
+ * Prepares the sample people used by the idiom benchmarks.
+ */
@Setup(Level.Trial)
void setup() {
personWithAddress = new Person(name: "Alice", address: new Address(city: "Springfield", zip: "62704"))
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/LoopsBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/LoopsBench.groovy
index 32f1aab5d6..b29f3a1203 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/LoopsBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/LoopsBench.groovy
@@ -38,6 +38,7 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class LoopsBench {
+ /** Number of loop iterations used by each benchmark invocation. */
static final int LOOP_COUNT = 1_000_000
/**
@@ -84,6 +85,11 @@ class LoopsBench {
}
}
+ /**
+ * Helper method for method call benchmarks.
+ * @param o the object to convert
+ * @return the string representation
+ */
static String doSomething(Object o) {
o.toString()
}
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MetaclassBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MetaclassBench.groovy
index b318dcea13..a8d8fb7d47 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MetaclassBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MetaclassBench.groovy
@@ -41,27 +41,66 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class MetaclassBench {
+ /** Number of metaclass mutation iterations used by each benchmark invocation. */
static final int ITERATIONS = 100_000
+ /**
+ * Helper class for metaclass modification tests.
+ */
class Foo {
+ /** Returns zero for one benchmark call-site variant. */
int m0() { 0 }
+
+ /** Returns one for one benchmark call-site variant. */
int m1() { 1 }
+
+ /** Returns two for one benchmark call-site variant. */
int m2() { 2 }
+
+ /** Returns three for one benchmark call-site variant. */
int m3() { 3 }
+
+ /** Returns four for one benchmark call-site variant. */
int m4() { 4 }
+
+ /** Returns five for one benchmark call-site variant. */
int m5() { 5 }
+
+ /** Returns six for one benchmark call-site variant. */
int m6() { 6 }
+
+ /** Returns seven for one benchmark call-site variant. */
int m7() { 7 }
+
+ /** Returns eight for one benchmark call-site variant. */
int m8() { 8 }
+
+ /** Returns nine for one benchmark call-site variant. */
int m9() { 9 }
+
+ /** Returns ten for one benchmark call-site variant. */
int m10() { 10 }
+
+ /** Returns eleven for one benchmark call-site variant. */
int m11() { 11 }
+
+ /** Returns twelve for one benchmark call-site variant. */
int m12() { 12 }
+
+ /** Returns thirteen for one benchmark call-site variant. */
int m13() { 13 }
+
+ /** Returns fourteen for one benchmark call-site variant. */
int m14() { 14 }
+
+ /** Returns fifteen for one benchmark call-site variant. */
int m15() { 15 }
}
+ /**
+ * Benchmark: method calls in the presence of metaclass modifications.
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
void methodCallsWithMetaclassChanges(Blackhole bh) {
long sum = 0
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MethodInvocationBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MethodInvocationBench.groovy
index f619f3aa20..b3de87fc1e 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MethodInvocationBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/MethodInvocationBench.groovy
@@ -40,37 +40,77 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class MethodInvocationBench {
+ /** Number of loop iterations used by each benchmark invocation. */
static final int ITERATIONS = 1_000_000
- // Simple fields for method tests
+ /** Instance field for method tests. */
int instanceField = 42
+
+ /** Static field for method tests. */
static int staticField = 100
- // Simple instance method
+ /**
+ * Simple instance method.
+ * @return the instance field value
+ */
int simpleMethod() {
instanceField
}
- // Method with parameters
+ /**
+ * Method with parameters.
+ * @param a first operand
+ * @param b second operand
+ * @return the sum
+ */
int methodWithParams(int a, int b) {
a + b
}
- // Method with object parameter
+ /**
+ * Method with object parameter.
+ * @param obj the object to convert
+ * @return the string representation
+ */
String methodWithObject(Object obj) {
obj.toString()
}
- // Overloaded methods to test dispatch
+ /**
+ * Overloaded method for String.
+ * @param s the string value
+ * @return a formatted result
+ */
String overloaded(String s) { "String: $s" }
+
+ /**
+ * Overloaded method for Integer.
+ * @param i the integer value
+ * @return a formatted result
+ */
String overloaded(Integer i) { "Integer: $i" }
+
+ /**
+ * Overloaded method for Object (catch-all).
+ * @param o the object value
+ * @return a formatted result
+ */
String overloaded(Object o) { "Object: $o" }
- // Static methods
+ /**
+ * Static method.
+ * @return the static field value
+ */
static int staticMethod() {
staticField
}
+ /**
+ * Static method with parameters.
+ * @param a first operand
+ * @param b second operand
+ * @return the sum
+ */
static int staticMethodWithParams(int a, int b) {
a + b
}
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/OperatorBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/OperatorBench.groovy
index 1fdc0bcba8..d354fe3437 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/OperatorBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/OperatorBench.groovy
@@ -36,6 +36,7 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class OperatorBench {
+ /** Number of loop iterations used by each benchmark invocation. */
static final int ITERATIONS = 1_000_000
/**
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/PropertyAccessBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/PropertyAccessBench.groovy
index c58f606541..fbe5848a05 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/PropertyAccessBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/PropertyAccessBench.groovy
@@ -36,14 +36,28 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class PropertyAccessBench {
+ /** Number of loop iterations used by each benchmark invocation. */
static final int ITERATIONS = 1_000_000
+ /** Instance field for property access tests. */
int instanceField = 42
+
+ /** String property for property access tests. */
String stringProperty = "hello"
// Explicit getter/setter for comparison
private int _backingField = 10
+
+ /**
+ * Gets the backing field value.
+ * @return the backing field value
+ */
int getBackingField() { _backingField }
+
+ /**
+ * Sets the backing field value.
+ * @param value the new value
+ */
void setBackingField(int value) { _backingField = value }
/**
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/RunnerRegistryBench.java b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/RunnerRegistryBench.java
index 78cea6079e..1e5c1df363 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/RunnerRegistryBench.java
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/RunnerRegistryBench.java
@@ -35,6 +35,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
+/**
+ * Benchmark comparing GroovyRunnerRegistry iteration against plain list iteration.
+ */
@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@Fork(2)
@@ -43,7 +46,14 @@ import java.util.concurrent.TimeUnit;
@State(Scope.Thread)
public class RunnerRegistryBench {
+ /**
+ * Baseline list used for plain iteration comparisons.
+ */
static List<Object> control = new ArrayList<>();
+
+ /**
+ * Registry instance iterated by the benchmark.
+ */
static GroovyRunnerRegistry registry = GroovyRunnerRegistry.getInstance();
static {
control.add(new Object());
@@ -52,6 +62,10 @@ public class RunnerRegistryBench {
registry.load(RunnerRegistryBench.class.getClassLoader());
}
+ /**
+ * Benchmark iteration over the GroovyRunnerRegistry.
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void registryIterator(Blackhole bh) {
for (GroovyRunner runner : registry) {
@@ -59,6 +73,10 @@ public class RunnerRegistryBench {
}
}
+ /**
+ * Benchmark iteration over a plain list (baseline).
+ * @param bh the blackhole for consuming results
+ */
@Benchmark
public void listIterator(Blackhole bh) {
for (Object obj : control) {
diff --git a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/CallSiteInvalidationBench.groovy b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/CallSiteInvalidationBench.groovy
index b239c44333..b0fa68b0ff 100644
--- a/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/CallSiteInvalidationBench.groovy
+++ b/subprojects/performance/src/jmh/groovy/org/apache/groovy/perf/grails/CallSiteInvalidationBench.groovy
@@ -37,33 +37,59 @@ import java.util.concurrent.TimeUnit
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
class CallSiteInvalidationBench {
+ /** Number of iterations per benchmark. */
static final int ITERATIONS = 100_000
+ /**
+ * Target class for hot method call sites.
+ */
static class HotTarget {
+ /** Test value for computations. */
int value = 42
+ /** Computes double of the value. */
int compute() { value * 2 }
+ /** Returns a string description of the value. */
String describe() { "v=$value" }
}
+ /**
+ * Second target class for multi-type call sites.
+ */
static class HotTargetB {
+ /** Count value for testing. */
int count = 10
+ /** Returns the count. */
int getCount() { count }
}
+ /**
+ * Third target class for multi-type call sites.
+ */
static class HotTargetC {
+ /** List of items for testing. */
List items = [1, 2, 3]
+ /** Returns the number of items. */
int itemCount() { items.size() }
}
+ /**
+ * Cold type for cross-type metaclass invalidation.
+ */
static class ColdType {
+ /** Label for cold type. */
String label = "cold"
}
+ /** Instance of HotTarget for benchmarking. */
HotTarget hotTarget
+ /** Instance of HotTargetB for benchmarking. */
HotTargetB hotTargetB
+ /** Instance of HotTargetC for benchmarking. */
HotTargetC hotTargetC
... 724 lines suppressed ...