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 14:30:31 UTC

(groovy) branch master updated: Add missing Javadoc for groovy-typecheckers,groovy-console,groovy-cli-commons,groovy-cli-picocli

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 f405f5b7d5 Add missing Javadoc for groovy-typecheckers,groovy-console,groovy-cli-commons,groovy-cli-picocli
f405f5b7d5 is described below

commit f405f5b7d57c557e3b4b4daa79205aef3a827fdb
Author: Daniel Sun <su...@apache.org>
AuthorDate: Mon Apr 27 23:30:14 2026 +0900

    Add missing Javadoc for groovy-typecheckers,groovy-console,groovy-cli-commons,groovy-cli-picocli
---
 .../groovy/groovy/cli/commons/CliBuilder.groovy    |  38 +++
 .../groovy/cli/commons/OptionAccessor.groovy       |  72 +++++
 .../groovy/groovy/cli/picocli/CliBuilder.groovy    |  24 +-
 .../groovy/cli/picocli/OptionAccessor.groovy       |  77 +++++
 .../src/main/groovy/groovy/console/TextNode.groovy |  36 ++-
 .../groovy/groovy/console/TextTreeNodeMaker.groovy |  19 +-
 .../groovy/groovy/console/ui/AstBrowser.groovy     | 199 +++++++++++++
 .../console/ui/AstNodeToScriptAdapter.groovy       |  53 +++-
 .../console/ui/ButtonOrDefaultRenderer.groovy      |   3 +
 .../groovy/console/ui/ButtonOrTextEditor.groovy    |   6 +
 .../console/ui/CellValueToolTipJTable.groovy       |   6 +
 .../main/groovy/groovy/console/ui/Console.groovy   | 331 ++++++++++++++++++---
 .../groovy/console/ui/ConsoleIvyPlugin.groovy      |   8 +
 .../groovy/console/ui/ConsoleMavenPlugin.groovy    |   9 +-
 .../groovy/console/ui/ConsolePreferences.groovy    |  28 +-
 .../groovy/groovy/console/ui/ConsoleSupport.java   |  45 ++-
 .../groovy/console/ui/ConsoleTextEditor.java       |  59 +++-
 .../groovy/groovy/console/ui/HistoryRecord.groovy  |  20 ++
 .../src/main/groovy/groovy/console/ui/Icons.groovy |  44 +++
 .../groovy/groovy/console/ui/ObjectBrowser.groovy  |  40 ++-
 .../groovy/console/ui/OutputTransforms.groovy      |  16 +
 .../console/ui/ScriptToTreeNodeAdapter.groovy      |  69 +++++
 .../groovy/groovy/console/ui/ThemeManager.groovy   |  25 +-
 .../groovy/console/ui/text/AutoIndentAction.groovy |  11 +
 .../groovy/console/ui/text/FindReplaceUtility.java |  40 +++
 .../groovy/console/ui/text/GroovyFilter.java       |  67 +++++
 .../console/ui/text/MatchingHighlighter.java       |  12 +
 .../console/ui/text/SmartDocumentFilter.java       |  38 +++
 .../ui/text/StructuredSyntaxDocumentFilter.java    | 118 ++++++--
 .../console/ui/text/StructuredSyntaxHandler.java   | 127 +++++++-
 .../console/ui/text/StructuredSyntaxResources.java |  33 ++
 .../groovy/groovy/console/ui/text/TextEditor.java  |  61 ++++
 .../groovy/console/ui/text/TextUndoManager.java    |  46 +++
 .../groovy/console/ui/view/BasicContentPane.groovy |  14 +
 .../groovy/console/ui/view/BasicMenuBar.groovy     |   3 +
 .../groovy/console/ui/view/BasicStatusBar.groovy   |   3 +
 .../groovy/console/ui/view/BasicToolBar.groovy     |   1 +
 .../groovy/console/ui/view/GTKDefaults.groovy      |   1 +
 .../groovy/console/ui/view/MacOSXDefaults.groovy   |   3 +-
 .../groovy/console/ui/view/MacOSXMenuBar.groovy    |   6 +
 .../groovy/typecheckers/FormatStringChecker.groovy |  10 +
 .../groovy/typecheckers/ModifiesChecker.groovy     |   3 +
 .../groovy/groovy/typecheckers/NullChecker.groovy  |   3 +
 .../groovy/typecheckers/PurityChecker.groovy       |   3 +
 .../groovy/groovy/typecheckers/RegexChecker.groovy |   3 +
 .../groovy/typecheckers/CheckingVisitor.groovy     |  25 ++
 46 files changed, 1773 insertions(+), 85 deletions(-)

diff --git a/subprojects/groovy-cli-commons/src/main/groovy/groovy/cli/commons/CliBuilder.groovy b/subprojects/groovy-cli-commons/src/main/groovy/groovy/cli/commons/CliBuilder.groovy
index 4f9cba80ef..4849b7d82c 100644
--- a/subprojects/groovy-cli-commons/src/main/groovy/groovy/cli/commons/CliBuilder.groovy
+++ b/subprojects/groovy-cli-commons/src/main/groovy/groovy/cli/commons/CliBuilder.groovy
@@ -302,8 +302,19 @@ class CliBuilder {
      */
     Options options = new Options()
 
+    /**
+     * Typed option metadata keyed by long name or short name.
+     */
     Map<String, TypedOption> savedTypeOptions = new HashMap<String, TypedOption>()
 
+    /**
+     * Creates and registers a typed option definition.
+     *
+     * @param args option attributes using the standard DSL keys
+     * @param type the target type for the option value
+     * @param description the option description
+     * @return the created typed option
+     */
     public <T> TypedOption<T> option(Map args, Class<T> type, String description) {
         def name = args.opt ?: '_'
         args.type = type
@@ -406,6 +417,12 @@ class CliBuilder {
         optionInstance
     }
 
+    /**
+     * Adds options declared with {@link Option} annotations to this builder.
+     *
+     * @param optionClass the annotated class or interface
+     * @param namesAreSetters whether annotated methods should be treated as setters
+     */
     void addOptionsFromAnnotations(Class optionClass, boolean namesAreSetters) {
         optionClass.methods.findAll{ it.getAnnotation(Option) }.each { Method m ->
             Annotation annotation = m.getAnnotation(Option)
@@ -506,6 +523,14 @@ class CliBuilder {
         result
     }
 
+    /**
+     * Applies parsed option values to an annotated target object or map.
+     *
+     * @param cli the parsed options accessor
+     * @param optionClass the annotated class or interface
+     * @param t the target object or backing map
+     * @param namesAreSetters whether annotated methods should be treated as setters
+     */
     def setOptionsFromAnnotations(def cli, Class optionClass, Object t, boolean namesAreSetters) {
         optionClass.methods.findAll{ it.getAnnotation(Option) }.each { Method m ->
             Annotation annotation = m.getAnnotation(Option)
@@ -611,6 +636,12 @@ class CliBuilder {
         return option
     }
 
+    /**
+     * Normalizes DSL option details into Commons CLI-compatible values.
+     *
+     * @param m the raw option details
+     * @return the normalized option details
+     */
     static Map adjustDetails(Map m) {
         m.collectMany { k, v ->
             if (k == 'args' && v == '+') {
@@ -626,6 +657,13 @@ class CliBuilder {
         }.sum()
     }
 
+    /**
+     * Expands {@code @file} arguments using command argument file semantics.
+     *
+     * @param args the original command-line arguments
+     * @return the arguments with any argument files expanded
+     * @throws IOException if an argument file cannot be read
+     */
     static expandArgumentFiles(args) throws IOException {
         def result = []
         for (arg in args) {
diff --git a/subprojects/groovy-cli-commons/src/main/groovy/groovy/cli/commons/OptionAccessor.groovy b/subprojects/groovy-cli-commons/src/main/groovy/groovy/cli/commons/OptionAccessor.groovy
index f2dd92c04a..685e5924dd 100644
--- a/subprojects/groovy-cli-commons/src/main/groovy/groovy/cli/commons/OptionAccessor.groovy
+++ b/subprojects/groovy-cli-commons/src/main/groovy/groovy/cli/commons/OptionAccessor.groovy
@@ -26,28 +26,68 @@ import org.codehaus.groovy.runtime.StringGroovyMethods
 
 import java.lang.reflect.Array
 
+/**
+ * Provides typed and dynamic access to parsed command-line options.
+ */
 class OptionAccessor {
+    /**
+     * The parsed command line.
+     */
     CommandLine commandLine
+
+    /**
+     * Typed option metadata keyed by long name or short name.
+     */
     Map<String, TypedOption> savedTypeOptions
 
+    /**
+     * Creates an accessor for the supplied parsed command line.
+     *
+     * @param commandLine the parsed command line
+     */
     OptionAccessor(CommandLine commandLine) {
         this.commandLine = commandLine
     }
 
+    /**
+     * Checks whether the supplied typed option was specified.
+     *
+     * @param typedOption the option metadata
+     * @return {@code true} if the option is present
+     */
     boolean hasOption(TypedOption typedOption) {
         commandLine.hasOption(typedOption.longOpt ?: typedOption.opt)
     }
 
+    /**
+     * Returns the converted default value for the named option.
+     *
+     * @param name the option name
+     * @return the converted default value, or {@code null} if none is defined
+     */
     public <T> T defaultValue(String name) {
         Class<T> type = savedTypeOptions[name]?.type
         String value = savedTypeOptions[name]?.defaultValue() ? savedTypeOptions[name].defaultValue() : null
         return (T) value ? getTypedValue(type, name, value) : null
     }
 
+    /**
+     * Returns the typed value for the supplied option.
+     *
+     * @param typedOption the option metadata
+     * @return the converted option value, or {@code null} if the option is absent
+     */
     public <T> T getOptionValue(TypedOption<T> typedOption) {
         getOptionValue(typedOption, null)
     }
 
+    /**
+     * Returns the typed value for the supplied option, falling back to the given default.
+     *
+     * @param typedOption the option metadata
+     * @param defaultValue the value to return when the option is absent
+     * @return the converted option value or {@code defaultValue}
+     */
     public <T> T getOptionValue(TypedOption<T> typedOption, T defaultValue) {
         String optionName = (String) typedOption.longOpt ?: typedOption.opt
         if (commandLine.hasOption(optionName)) {
@@ -79,10 +119,24 @@ class OptionAccessor {
         return result
     }
 
+    /**
+     * Returns the typed value for the supplied option using subscript syntax.
+     *
+     * @param typedOption the option metadata
+     * @return the converted option value, or {@code null} if the option is absent
+     */
     public <T> T getAt(TypedOption<T> typedOption) {
         getAt(typedOption, null)
     }
 
+    /**
+     * Returns the typed value for the supplied option using subscript syntax,
+     * falling back to the given default.
+     *
+     * @param typedOption the option metadata
+     * @param defaultValue the value to return when the option is absent
+     * @return the converted option value or {@code defaultValue}
+     */
     public <T> T getAt(TypedOption<T> typedOption, T defaultValue) {
         String optionName = (String) typedOption.longOpt ?: typedOption.opt
         if (savedTypeOptions.containsKey(optionName)) {
@@ -118,10 +172,23 @@ class OptionAccessor {
         StringGroovyMethods.asType(optionValue, (Class<T>) type)
     }
 
+    /**
+     * Delegates unknown method calls to the underlying {@link CommandLine}.
+     *
+     * @param name the method name
+     * @param args the method arguments
+     * @return the delegated result
+     */
     def invokeMethod(String name, Object args) {
         return InvokerHelper.getMetaClass(commandLine).invokeMethod(commandLine, name, args)
     }
 
+    /**
+     * Supports property-style access to option values and flags.
+     *
+     * @param name the property name
+     * @return the option value, default value, or flag state
+     */
     def getProperty(String name) {
         if (!savedTypeOptions.containsKey(name)) {
             def alt = savedTypeOptions.find{ it.value.opt == name }
@@ -157,6 +224,11 @@ class OptionAccessor {
         return result
     }
 
+    /**
+     * Returns the remaining non-option arguments.
+     *
+     * @return the remaining arguments
+     */
     List<String> arguments() {
         commandLine.args.toList()
     }
diff --git a/subprojects/groovy-cli-picocli/src/main/groovy/groovy/cli/picocli/CliBuilder.groovy b/subprojects/groovy-cli-picocli/src/main/groovy/groovy/cli/picocli/CliBuilder.groovy
index bf114f06ef..246d2e91b4 100644
--- a/subprojects/groovy-cli-picocli/src/main/groovy/groovy/cli/picocli/CliBuilder.groovy
+++ b/subprojects/groovy-cli-picocli/src/main/groovy/groovy/cli/picocli/CliBuilder.groovy
@@ -544,6 +544,14 @@ class CliBuilder {
         this.errorWriter = writer
     }
 
+    /**
+     * Defines an option with an explicit value type using the dynamic builder API.
+     *
+     * @param args the option attributes
+     * @param type the type used to convert option values
+     * @param description the usage text for the option
+     * @return the created typed option descriptor
+     */
     public <T> TypedOption<T> option(Map args, Class<T> type, String description) {
         def name = args.opt ?: '_'
         args.type = type
@@ -609,6 +617,9 @@ class CliBuilder {
     /**
      * Make options accessible from command line args with parser.
      * Returns null on bad command lines after displaying usage message.
+     *
+     * @param args the command line arguments to parse
+     * @return an accessor for the parsed options, or {@code null} if parsing failed
      */
     OptionAccessor parse(args) {
         CommandLine commandLine = createCommandLine()
@@ -649,8 +660,8 @@ class CliBuilder {
      * Given an interface containing members with annotations, derive
      * the options specification.
      *
-     * @param optionsClass
-     * @param args
+     * @param optionsClass the annotated interface describing the supported options
+     * @param args the command line arguments to parse
      * @return an instance containing the processed options
      */
     public <T> T parseFromSpec(Class<T> optionsClass, String[] args) {
@@ -666,8 +677,8 @@ class CliBuilder {
      * Given an instance containing members with annotations, derive
      * the options specification.
      *
-     * @param optionInstance
-     * @param args
+     * @param optionInstance the annotated instance to populate
+     * @param args the command line arguments to parse
      * @return the options instance populated with the processed options
      */
     public <T> T parseFromInstance(T optionInstance, args) {
@@ -897,6 +908,11 @@ class CliBuilder {
     // implementation details -------------------------------------
     /**
      * Internal method: How to create an OptionSpec from the specification.
+     *
+     * @param shortname the short option name, or {@code _} for long-only options
+     * @param details the option attributes
+     * @param description the usage text for the option
+     * @return the created picocli option specification
      */
     OptionSpec option(shortname, Map details, description) {
         OptionSpec.Builder builder
diff --git a/subprojects/groovy-cli-picocli/src/main/groovy/groovy/cli/picocli/OptionAccessor.groovy b/subprojects/groovy-cli-picocli/src/main/groovy/groovy/cli/picocli/OptionAccessor.groovy
index 4f9f2a4810..c2303df5b2 100644
--- a/subprojects/groovy-cli-picocli/src/main/groovy/groovy/cli/picocli/OptionAccessor.groovy
+++ b/subprojects/groovy-cli-picocli/src/main/groovy/groovy/cli/picocli/OptionAccessor.groovy
@@ -24,28 +24,68 @@ import org.codehaus.groovy.runtime.StringGroovyMethods
 import picocli.CommandLine.Model.OptionSpec
 import picocli.CommandLine.ParseResult
 
+/**
+ * Provides typed and dynamic access to values produced by {@link CliBuilder#parse(Object)}.
+ */
 class OptionAccessor {
+    /**
+     * The underlying picocli parse result.
+     */
     ParseResult parseResult
+
+    /**
+     * Type metadata for options declared by the originating {@link CliBuilder}.
+     */
     Map<String, TypedOption> savedTypeOptions
 
+    /**
+     * Creates an accessor for the specified parse result.
+     *
+     * @param parseResult the parsed command line state
+     */
     OptionAccessor(ParseResult parseResult) {
         this.parseResult = parseResult
     }
 
+    /**
+     * Checks whether the specified typed option was matched.
+     *
+     * @param typedOption the option to inspect
+     * @return {@code true} if the option was supplied on the command line
+     */
     boolean hasOption(TypedOption typedOption) {
         parseResult.hasMatchedOption(typedOption.longOpt ?: typedOption.opt as String)
     }
 
+    /**
+     * Returns the converted default value for a named option.
+     *
+     * @param name the option name used to register the option metadata
+     * @return the converted default value, or {@code null} if none was declared
+     */
     public <T> T defaultValue(String name) {
         Class<T> type = savedTypeOptions[name]?.type
         String value = savedTypeOptions[name]?.defaultValue() ? savedTypeOptions[name].defaultValue() : null
         return (T) value ? getTypedValue(type, name, value) : null
     }
 
+    /**
+     * Returns the value of the specified typed option.
+     *
+     * @param typedOption the option to inspect
+     * @return the parsed or configured value, or {@code null} if none is available
+     */
     public <T> T getOptionValue(TypedOption<T> typedOption) {
         getOptionValue(typedOption, null)
     }
 
+    /**
+     * Returns the value of the specified typed option.
+     *
+     * @param typedOption the option to inspect
+     * @param defaultValue the fallback value to use when the option has no value
+     * @return the parsed value, configured default, or supplied fallback
+     */
     public <T> T getOptionValue(TypedOption<T> typedOption, T defaultValue) {
         String optionName = (String) typedOption.longOpt ?: typedOption.opt
         if (parseResult.hasMatchedOption(optionName)) {
@@ -56,10 +96,23 @@ class OptionAccessor {
         }
     }
 
+    /**
+     * Returns the value of the specified typed option using subscript syntax.
+     *
+     * @param typedOption the option to inspect
+     * @return the parsed or configured value, or {@code null} if none is available
+     */
     public <T> T getAt(TypedOption<T> typedOption) {
         getAt(typedOption, null)
     }
 
+    /**
+     * Returns the value of the specified typed option using subscript syntax.
+     *
+     * @param typedOption the option to inspect
+     * @param defaultValue the fallback value to use when the option has no value
+     * @return the parsed value, configured default, or supplied fallback
+     */
     public <T> T getAt(TypedOption<T> typedOption, T defaultValue) {
         getOptionValue(typedOption, defaultValue)
     }
@@ -85,6 +138,12 @@ class OptionAccessor {
         StringGroovyMethods.asType(optionValue, (Class<T>) type)
     }
 
+    /**
+     * Returns properties collected for a map-style option.
+     *
+     * @param name the option name
+     * @return the parsed properties, or {@code null} if the option was not matched
+     */
     Properties getOptionProperties(String name) {
         if (!parseResult.hasMatchedOption(name)) {
             return null
@@ -95,6 +154,13 @@ class OptionAccessor {
         result
     }
 
+    /**
+     * Provides limited Apache Commons CLI compatibility by delegating selected method calls to the underlying parse result.
+     *
+     * @param name the method name to invoke
+     * @param args the method arguments
+     * @return the delegated call result
+     */
     def invokeMethod(String name, Object args) {
         // TODO we could just declare normal methods to map commons-cli CommandLine methods to picocli ParseResult methods
         if (name == 'hasOption')      { name = 'hasMatchedOption';   args = [args[0]      ].toArray() }
@@ -102,6 +168,12 @@ class OptionAccessor {
         return InvokerHelper.getMetaClass(parseResult).invokeMethod(parseResult, name, args)
     }
 
+    /**
+     * Resolves dynamic property lookups to parsed option values, defaults, or multi-value views.
+     *
+     * @param name the property name to resolve
+     * @return the resolved value, or {@code false} when no matching option exists
+     */
     def getProperty(String name) {
         if (name == 'parseResult') { return parseResult }
         if (parseResult.hasMatchedOption(name)) {
@@ -150,6 +222,11 @@ class OptionAccessor {
         false
     }
 
+    /**
+     * Returns the remaining positional arguments.
+     *
+     * @return the unmatched positional arguments in encounter order
+     */
     List<String> arguments() {
         parseResult.hasMatchedPositional(0) ? parseResult.matchedPositional(0).stringValues() : []
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/TextNode.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/TextNode.groovy
index 8621cf5284..753a6028a4 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/TextNode.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/TextNode.groovy
@@ -16,38 +16,68 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-/**
- * Represents a plain text node for use in the AST tree made by ASTBrowser
- */
 package groovy.console
 
 import groovy.transform.CompileStatic
 
+/**
+ * Represents a plain text node for use in the AST tree made by ASTBrowser.
+ */
 @CompileStatic
 class TextNode {
+    /** Value displayed for this node. */
     Object userObject
+    /** Additional name/value metadata shown for this node. */
     List<List<?>> properties
+    /** Parent node in the text tree. */
     TextNode parent
+    /** Child nodes in insertion order. */
     List children
 
+    /**
+     * Creates a node with the supplied display value.
+     *
+     * @param userObject value displayed for the node
+     */
     TextNode(Object userObject) {
         this.userObject = userObject
         children = new ArrayList<TextNode>()
     }
 
+    /**
+     * Creates a node with the supplied display value and metadata.
+     *
+     * @param userObject value displayed for the node
+     * @param properties metadata associated with the node
+     */
     TextNode(Object userObject, List<List<?>> properties) {
         this(userObject)
         this.properties = properties
     }
 
+    /**
+     * Adds a child node.
+     *
+     * @param child child node to append
+     */
     void add(TextNode child) {
         children << child
     }
 
+    /**
+     * Sets the parent node.
+     *
+     * @param newParent parent node reference
+     */
     void setParent(TextNode newParent) {
         parent = newParent
     }
 
+    /**
+     * Returns the display text for this node.
+     *
+     * @return the node text
+     */
     String toString() {
         userObject ? userObject.toString() : 'null'
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/TextTreeNodeMaker.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/TextTreeNodeMaker.groovy
index 9b6cd46ada..503a03736b 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/TextTreeNodeMaker.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/TextTreeNodeMaker.groovy
@@ -16,20 +16,33 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-/**
- * A factory class for text nodes for use in the AST tree made by ASTBrowser
- */
 package groovy.console
 
 import groovy.console.ui.AstBrowserNodeMaker
 import groovy.transform.CompileStatic
 
+/**
+ * Factory for the text nodes displayed by ASTBrowser.
+ */
 @CompileStatic
 class TextTreeNodeMaker implements AstBrowserNodeMaker<TextNode> {
+    /**
+     * Creates a text node without additional metadata.
+     *
+     * @param userObject value displayed for the node
+     * @return the created text node
+     */
     TextNode makeNode(Object userObject) {
         new TextNode(userObject)
     }
 
+    /**
+     * Creates a text node with additional metadata.
+     *
+     * @param userObject value displayed for the node
+     * @param properties metadata associated with the node
+     * @return the created text node
+     */
     TextNode makeNodeWithProperties(Object userObject, List<List<?>> properties) {
         new TextNode(userObject, properties)
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstBrowser.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstBrowser.groovy
index a6c674b714..6ae9d8b308 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstBrowser.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstBrowser.groovy
@@ -71,14 +71,27 @@ class AstBrowser {
     private static final String BYTECODE_MSG_SELECT_NODE = '// Please select a class node in the tree view.'
     private static final String NO_BYTECODE_AVAILABLE_AT_THIS_PHASE = '// No bytecode available at this phase'
 
+    /** UI components used by the browser panes and splitters. */
     private inputArea, rootElement, decompiledSource, jTree, propertyTable, splitterPane, mainSplitter, bytecodeView, asmifierView
+    /** Display flags that control which script representations are shown. */
     boolean showScriptFreeForm, showScriptClass, showClosureClasses, showTreeView
+    /** Class loader used to capture generated bytecode for the selected phase. */
     GeneratedBytecodeAwareGroovyClassLoader classLoader
+    /** Persisted UI preferences for the browser window. */
     def prefs = new AstBrowserUiPreferences()
+    /** Refresh action shared by toolbar and menu items. */
     Action refreshAction
     private CompilerConfiguration config
     private Runnable themeChangeListener
 
+    /**
+     * Creates a browser for the supplied editor state.
+     *
+     * @param inputArea input component whose selection should track the tree
+     * @param rootElement root document element for the input component
+     * @param classLoader parent class loader used for compilation
+     * @param config optional compiler configuration
+     */
     AstBrowser(inputArea, rootElement, classLoader, config = null) {
         this.inputArea = inputArea
         this.rootElement = rootElement
@@ -86,9 +99,16 @@ class AstBrowser {
         this.config = config
     }
 
+    /** Swing builder used to create and update the browser UI. */
     SwingBuilder swing
+    /** Top-level browser window. */
     def frame
 
+    /**
+     * Launches the AST browser for the supplied script file.
+     *
+     * @param args command-line arguments containing the script file path
+     */
     static void main(args) {
 
         if (!args) {
@@ -104,15 +124,29 @@ class AstBrowser {
         }
     }
 
+    /**
+     * Resets the auxiliary source views to their default placeholder text.
+     */
     void initAuxViews() {
         bytecodeView.textEditor.text = BYTECODE_MSG_SELECT_NODE
         asmifierView.textEditor.text = BYTECODE_MSG_SELECT_NODE
     }
 
+    /**
+     * Opens the browser for the supplied script producer.
+     *
+     * @param script closure that supplies the current script text
+     */
     void run(Closure script) {
         run(script, null)
     }
 
+    /**
+     * Opens the browser for the supplied script producer.
+     *
+     * @param script closure that supplies the current script text
+     * @param name optional source name displayed in the window title
+     */
     void run(Closure script, String name) {
 
         swing = new SwingBuilder()
@@ -385,6 +419,13 @@ class AstBrowser {
         return sw.toString()
     }
 
+    /**
+     * Creates the table mouse listener used for copy and browse actions.
+     *
+     * @param valueCol column index containing the browsable value
+     * @param pathClosure closure used to build the browser path for a selected row
+     * @return the configured mouse listener
+     */
     def mouseListener(int valueCol, Closure pathClosure) {
         def outer = this
         new MouseAdapter() {
@@ -444,10 +485,20 @@ class AstBrowser {
         }
     }
 
+    /**
+     * Increases the font size used by the browser views.
+     *
+     * @param evt triggering event, if any
+     */
     void largerFont(EventObject evt = null) {
         updateFontSize(decompiledSource.textEditor.font.size + 2)
     }
 
+    /**
+     * Decreases the font size used by the browser views.
+     *
+     * @param evt triggering event, if any
+     */
     void smallerFont(EventObject evt = null) {
         updateFontSize(decompiledSource.textEditor.font.size - 2)
     }
@@ -472,6 +523,13 @@ class AstBrowser {
         propertyTable.rowHeight = newFontSize + 2
     }
 
+    /**
+     * Opens the selected value in the object browser.
+     *
+     * @param table source table
+     * @param valueCol column containing the browsable value
+     * @param pathClosure closure used to build the browser path
+     */
     void launch(table, valueCol, pathClosure) {
         def selectedRow = table.selectedRow
         if (selectedRow != -1) {
@@ -482,10 +540,16 @@ class AstBrowser {
         }
     }
 
+    /**
+     * Action handler that delegates to {@link #launch(Object, Object, Object)}.
+     */
     void launchAction(table, valueCol, pathClosure, EventObject evt) {
         launch(table, valueCol, pathClosure)
     }
 
+    /**
+     * Copies the current tooltip value to the system clipboard.
+     */
     void copyAction(table, MouseEvent me, EventObject evt) {
         def toolTipText = table.getToolTipText(me)
         if (toolTipText) {
@@ -493,6 +557,9 @@ class AstBrowser {
         }
     }
 
+    /**
+     * Displays the browser about dialog.
+     */
     void aboutAction(EventObject evt) {
         def pane = swing.optionPane()
         def version = GroovySystem.version
@@ -502,18 +569,32 @@ class AstBrowser {
         dialog.visible = true
     }
 
+    /**
+     * Toggles display of the free-form script body.
+     */
     void showScriptFreeForm(EventObject evt) {
         showScriptFreeForm = evt.source.selected
     }
 
+    /**
+     * Toggles display of the generated script class.
+     */
     void showScriptClass(EventObject evt) {
         showScriptClass = evt.source.selected
     }
 
+    /**
+     * Toggles display of generated closure and lambda classes.
+     */
     void showClosureClasses(EventObject evt) {
         showClosureClasses = evt.source.selected
     }
 
+    /**
+     * Toggles visibility of the tree pane.
+     *
+     * @param evt triggering event, if any
+     */
     void showTreeView(EventObject evt = null) {
         showTreeView = !showTreeView
         splitterPane.visible = showTreeView
@@ -532,6 +613,12 @@ class AstBrowser {
         'ASMifier'
     }
 
+    /**
+     * Rebuilds the decompiled source view for the selected compile phase.
+     *
+     * @param phaseId compile phase identifier
+     * @param source current source text
+     */
     void decompile(phaseId, source) {
         decompiledSource.textEditor.cursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)
         decompiledSource.textEditor.text = 'Loading...'
@@ -556,6 +643,13 @@ class AstBrowser {
         }
     }
 
+    /**
+     * Rebuilds the AST tree for the selected compile phase.
+     *
+     * @param jTree tree component to update
+     * @param script current source text
+     * @param compilePhase compile phase identifier
+     */
     void compile(jTree, String script, int compilePhase) {
         jTree.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR))
         def model = jTree.model
@@ -591,17 +685,30 @@ class AstBrowser {
  */
 class AstBrowserUiPreferences {
 
+    /** Saved window location. */
     final frameLocation
+    /** Saved window size. */
     final frameSize
+    /** Saved divider location for the tree/property splitter. */
     final verticalDividerLocation
+    /** Saved divider location for the main splitter. */
     final horizontalDividerLocation
+    /** Saved free-form script visibility flag. */
     final boolean showScriptFreeForm
+    /** Saved tree visibility flag. */
     final boolean showTreeView
+    /** Saved script class visibility flag. */
     final boolean showScriptClass
+    /** Saved closure class visibility flag. */
     final boolean showClosureClasses
+    /** Saved decompiled source font size. */
     int decompiledSourceFontSize
+    /** Saved compile phase selection. */
     final CompilePhaseAdapter selectedPhase
 
+    /**
+     * Loads persisted browser UI preferences.
+     */
     AstBrowserUiPreferences() {
         Preferences prefs = Preferences.userNodeForPackage(AstBrowserUiPreferences)
         frameLocation = [
@@ -624,6 +731,9 @@ class AstBrowserUiPreferences {
         }
     }
 
+    /**
+     * Persists the current browser UI state.
+     */
     def save(frame, vSplitter, hSplitter, scriptFreeFormPref, scriptClassPref, closureClassesPref, CompilePhaseAdapter phase, showTreeView) {
         Preferences prefs = Preferences.userNodeForPackage(AstBrowserUiPreferences)
         prefs.putInt('decompiledFontSize', decompiledSourceFontSize as int)
@@ -656,14 +766,27 @@ enum CompilePhaseAdapter {
     OUTPUT(Phases.OUTPUT, 'Output'),
     FINALIZATION(Phases.FINALIZATION, 'Finalization')
 
+    /** Compile phase identifier from {@link Phases}. */
     final int phaseId
+    /** Human-readable label shown in the phase picker. */
     final String string
 
+    /**
+     * Creates a phase adapter for the supplied compile phase.
+     *
+     * @param phaseId compile phase identifier
+     * @param string display label
+     */
     CompilePhaseAdapter(int phaseId, String string) {
         this.phaseId = phaseId
         this.string = string
     }
 
+    /**
+     * Returns the label shown in the phase picker.
+     *
+     * @return the display label
+     */
     String toString() {
         return string
     }
@@ -676,6 +799,7 @@ enum CompilePhaseAdapter {
 class TreeNodeWithProperties extends DefaultMutableTreeNode {
     private static final long serialVersionUID = -1428101618435607457L
 
+    /** Additional properties associated with this tree node. */
     List<List<?>> properties
 
     /**
@@ -688,15 +812,31 @@ class TreeNodeWithProperties extends DefaultMutableTreeNode {
         this.properties = properties
     }
 
+    /**
+     * Returns the value of the named property.
+     *
+     * @param name property name
+     * @return the property value, or {@code null} if absent
+     */
     String getPropertyValue(String name) {
         def match = properties.find { List list -> name == list[0] }
         return match != null ? match[1] : null
     }
 
+    /**
+     * Indicates whether this node represents a class node.
+     *
+     * @return {@code true} for class and inner class nodes
+     */
     boolean isClassNode() {
         getPropertyValue('class') in ['class org.codehaus.groovy.ast.ClassNode', 'class org.codehaus.groovy.ast.InnerClassNode']
     }
 
+    /**
+     * Indicates whether this node represents a method or constructor node.
+     *
+     * @return {@code true} for method and constructor nodes
+     */
     boolean isMethodNode() {
         getPropertyValue('class') in ['class org.codehaus.groovy.ast.MethodNode', 'class org.codehaus.groovy.ast.ConstructorNode']
     }
@@ -707,8 +847,21 @@ class TreeNodeWithProperties extends DefaultMutableTreeNode {
  */
 @CompileStatic
 interface AstBrowserNodeMaker<T> {
+    /**
+     * Creates a node for the supplied user object.
+     *
+     * @param userObject value shown for the node
+     * @return the created node
+     */
     T makeNode(Object userObject)
 
+    /**
+     * Creates a node for the supplied user object and metadata.
+     *
+     * @param userObject value shown for the node
+     * @param properties metadata associated with the node
+     * @return the created node
+     */
     T makeNodeWithProperties(Object userObject, List<List<?>> properties)
 }
 
@@ -717,24 +870,50 @@ interface AstBrowserNodeMaker<T> {
  */
 @CompileStatic
 class SwingTreeNodeMaker implements AstBrowserNodeMaker<DefaultMutableTreeNode> {
+    /**
+     * Creates a Swing tree node without metadata.
+     *
+     * @param userObject value shown for the node
+     * @return the created tree node
+     */
     DefaultMutableTreeNode makeNode(Object userObject) {
         new DefaultMutableTreeNode(userObject)
     }
 
+    /**
+     * Creates a Swing tree node with metadata.
+     *
+     * @param userObject value shown for the node
+     * @param properties metadata associated with the node
+     * @return the created tree node
+     */
     DefaultMutableTreeNode makeNodeWithProperties(Object userObject, List<List<?>> properties) {
         new TreeNodeWithProperties(userObject, properties)
     }
 }
 
+/**
+ * Captures generated bytecode while delegating normal class creation.
+ */
 class BytecodeCollector extends ClassCollector {
 
+    /** Captured bytecode keyed by class name. */
     Map<String, byte[]> bytecode
 
+    /**
+     * Creates a collector that stores generated bytecode in the supplied map.
+     *
+     * @param delegate collector providing the compilation context
+     * @param bytecode destination map for generated bytecode
+     */
     BytecodeCollector(ClassCollector delegate, Map<String, byte[]> bytecode) {
         super(delegate.cl, delegate.unit, delegate.su)
         this.bytecode = bytecode
     }
 
+    /**
+     * Stores generated bytecode before defining the class.
+     */
     @Override
     protected Class createClass(byte[] code, ClassNode classNode) {
         bytecode[classNode.name] = code
@@ -743,25 +922,45 @@ class BytecodeCollector extends ClassCollector {
 
 }
 
+/**
+ * Groovy class loader that retains generated bytecode for AST Browser inspection.
+ */
 @CompileStatic
 class GeneratedBytecodeAwareGroovyClassLoader extends GroovyClassLoader {
 
     private final Map<String, byte[]> bytecode = new HashMap<String, byte[]>()
 
+    /**
+     * Creates a class loader that records generated bytecode.
+     *
+     * @param parent parent class loader
+     */
     GeneratedBytecodeAwareGroovyClassLoader(final GroovyClassLoader parent) {
         super(parent)
     }
 
+    /**
+     * Creates a collector that stores generated bytecode for later display.
+     */
     @Override
     protected ClassCollector createCollector(CompilationUnit unit, SourceUnit su) {
         def collector = super.createCollector(unit, su)
         new BytecodeCollector(collector, bytecode)
     }
 
+    /**
+     * Clears any previously captured bytecode.
+     */
     void clearBytecodeTable() {
         bytecode.clear()
     }
 
+    /**
+     * Returns the captured bytecode for the named class.
+     *
+     * @param className fully qualified class name
+     * @return the captured bytecode, or {@code null} if unavailable
+     */
     byte[] getBytecode(final String className) {
         bytecode[className]
     }
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 fc6f2ab327..67677329c9 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
@@ -186,13 +186,26 @@ and [compilephase] is a valid Integer based org.codehaus.groovy.control.CompileP
 class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperation, GroovyClassVisitor, GroovyCodeVisitor {
 
     private final Writer _out
+    /** Stack of nested class names used while rendering constructors. */
     Stack<String> classNameStack = []
+    /** Current indentation prefix. */
     String _indent = ''
+    /** Indicates whether the next write should emit indentation first. */
     boolean readyToIndent = true
+    /** Whether free-form script statements should be rendered. */
     boolean showScriptFreeForm
+    /** Whether the generated script class should be rendered. */
     boolean showScriptClass
+    /** Tracks whether the free-form script body has already been emitted. */
     boolean scriptHasBeenVisited
 
+    /**
+     * Creates a visitor that renders AST nodes as Groovy source.
+     *
+     * @param writer target writer
+     * @param showScriptFreeForm whether free-form script statements should be rendered
+     * @param showScriptClass whether the generated script class should be rendered
+     */
     AstNodeToScriptVisitor(Writer writer, boolean showScriptFreeForm = true, boolean showScriptClass = true) {
         this._out = writer
         this.showScriptFreeForm = showScriptFreeForm
@@ -200,6 +213,9 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         this.scriptHasBeenVisited = false
     }
 
+    /**
+     * Renders the supplied primary class node and optional script body.
+     */
     @Override
     void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
 
@@ -246,6 +262,11 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         }
     }
 
+    /**
+     * Writes text, applying the current indentation rules.
+     *
+     * @param parameter value to append to the output
+     */
     void print(parameter) {
         def output = parameter.toString()
 
@@ -264,10 +285,20 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         _out.print output
     }
 
+    /**
+     * This visitor writes directly to its target and does not support println-style output.
+     *
+     * @param parameter ignored output parameter
+     */
     def println(parameter) {
         throw new UnsupportedOperationException('Wrong API')
     }
 
+    /**
+     * Executes the supplied block one indentation level deeper.
+     *
+     * @param block block to execute while indented
+     */
     def indented(Closure block) {
         String startingIndent = _indent
         _indent = _indent + '    '
@@ -275,6 +306,9 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         _indent = startingIndent
     }
 
+    /**
+     * Ensures the output ends with a single line break.
+     */
     def printLineBreak() {
         if (!_out.toString().endsWith('\n')) {
             _out.print '\n'
@@ -282,6 +316,9 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         readyToIndent = true
     }
 
+    /**
+     * Ensures the output ends with a blank line.
+     */
     def printDoubleBreak() {
         if (_out.toString().endsWith('\n\n')) {
             // do nothing
@@ -294,6 +331,11 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         readyToIndent = true
     }
 
+    /**
+     * Writes the package declaration for the current source unit.
+     *
+     * @param packageNode package node to render
+     */
     void visitPackage(PackageNode packageNode) {
 
         if (packageNode) {
@@ -312,6 +354,11 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         }
     }
 
+    /**
+     * Writes an import declaration.
+     *
+     * @param node import node to render
+     */
     void visitImport(ImportNode node) {
         if (node) {
             node.annotations?.each {
@@ -940,7 +987,8 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
 
     /**
      * Prints out the type, safely handling arrays.
-     * @param classNode
+     *
+     * @param classNode type to render
      */
     void visitType(ClassNode classNode) {
         def name = classNode.name
@@ -1109,6 +1157,9 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         statement?.messageExpression?.visit this
     }
 
+    /**
+     * Retained for compatibility; delegates to {@link #visitArgumentlistExpression(ArgumentListExpression)}.
+     */
     @Deprecated
     void visitArgumentlistExpression(ArgumentListExpression expression, boolean showTypesIgnored) {
         visitArgumentlistExpression(expression)
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrDefaultRenderer.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrDefaultRenderer.groovy
index ab796a1513..c76b67b5d3 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrDefaultRenderer.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrDefaultRenderer.groovy
@@ -34,6 +34,9 @@ import java.awt.Component
 class ButtonOrDefaultRenderer extends DefaultTableCellRenderer {
     private static final long serialVersionUID = 4771388915540692105L
 
+    /**
+     * Returns the supplied component directly when possible, otherwise delegates to the default renderer.
+     */
     Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
         if (value instanceof JComponent) {
             value.setSize(Math.round(value.getSize().getWidth())?.toInteger(), table.getRowHeight(row))
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrTextEditor.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrTextEditor.groovy
index 383f1bb09e..08aa6c5543 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrTextEditor.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ButtonOrTextEditor.groovy
@@ -42,6 +42,9 @@ class ButtonOrTextEditor extends AbstractCellEditor implements TableCellEditor {
     /** The Swing component being edited. */
     protected JComponent editorComponent
 
+    /**
+     * Returns an editor component that matches the current cell value.
+     */
     @Override
     Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
         if (value instanceof JButton) {
@@ -58,6 +61,9 @@ class ButtonOrTextEditor extends AbstractCellEditor implements TableCellEditor {
         editorComponent
     }
 
+    /**
+     * Returns the current editor component.
+     */
     @Override
     Object getCellEditorValue() {
         editorComponent
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/CellValueToolTipJTable.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/CellValueToolTipJTable.groovy
index 1d45047c1a..ec530978ef 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/CellValueToolTipJTable.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/CellValueToolTipJTable.groovy
@@ -21,9 +21,15 @@ package groovy.console.ui
 import javax.swing.JTable
 import java.awt.event.MouseEvent
 
+/**
+ * Table that exposes the current cell value as a tooltip.
+ */
 class CellValueToolTipJTable extends JTable {
     private static final long serialVersionUID = 7112943034646629299L
 
+    /**
+     * Returns the hovered cell value as tooltip text.
+     */
     String getToolTipText(MouseEvent me) {
         int viewRowIndex = rowAtPoint(me.point)
         int viewColumnIndex = columnAtPoint(me.point)
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy
index ca78b92d18..bb9781c6cb 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Console.groovy
@@ -108,148 +108,228 @@ import java.util.prefs.Preferences
  */
 class Console implements CaretListener, HyperlinkListener, ComponentListener, FocusListener {
 
+    /** Prefix used for generated script names inside the console. */
     static final String DEFAULT_SCRIPT_NAME_START = 'ConsoleScript'
     private static final boolean DEBUG_GRAPE = Boolean.getBoolean('groovy.grape.debug')
 
+    /** User preferences backing console settings. */
     static prefs = Preferences.userNodeForPackage(Console)
 
-    // Whether or not std output should be captured to the console
+    /** Whether stdout is redirected into the console output pane. */
     static boolean captureStdOut = prefs.getBoolean('captureStdOut', true)
+    /** Whether stderr is redirected into the console output pane. */
     static boolean captureStdErr = prefs.getBoolean('captureStdErr', true)
+    /** Active console controllers sharing the global stream interceptors. */
     static consoleControllers = []
 
+    /** Whether the smart syntax highlighter is enabled by default. */
     static boolean smartHighlighter = prefs.getBoolean('smartHighlighter',
             Boolean.valueOf(SystemUtil.getSystemPropertySafe('groovy.console.enable.smart.highlighter', 'true')))
 
+    /** Whether full stack traces are shown for execution failures. */
     boolean fullStackTraces = prefs.getBoolean('fullStackTraces',
             Boolean.valueOf(System.getProperty('groovy.full.stacktrace', 'false')))
+    /** Action that toggles full stack trace output. */
     Action fullStackTracesAction
 
+    /** Whether executed script text is echoed into the output pane. */
     boolean showScriptInOutput = prefs.getBoolean('showScriptInOutput', true)
+    /** Action that toggles script echoing in the output pane. */
     Action showScriptInOutputAction
 
+    /** Whether non-null results are transformed for visual display. */
     boolean visualizeScriptResults = prefs.getBoolean('visualizeScriptResults', false)
+    /** Action that toggles result visualization. */
     Action visualizeScriptResultsAction
 
+    /** Whether the toolbar is visible. */
     boolean showToolbar = prefs.getBoolean('showToolbar', true)
+    /** Toolbar component shown above the editor. */
     Component toolbar
+    /** Action that toggles toolbar visibility. */
     Action showToolbarAction
 
+    /** Whether output is shown in a detached window. */
     boolean detachedOutput = prefs.getBoolean('detachedOutput', false)
+    /** Action that toggles detached output mode. */
     Action detachedOutputAction
 
+    /** Whether the split pane stacks input and output vertically. */
     boolean orientationVertical = prefs.getBoolean('orientationVertical', true)
+    /** Action that toggles the split-pane orientation. */
     Action orientationVerticalAction
+    /** Action that shows the detached output window. */
     Action showOutputWindowAction
+    /** Menu action variant that hides the detached output window. */
     Action hideOutputWindowAction1
+    /** Toolbar action variant that hides the detached output window. */
     Action hideOutputWindowAction2
+    /** Popup action variant that hides the detached output window. */
     Action hideOutputWindowAction3
+    /** Shortcut action variant that hides the detached output window. */
     Action hideOutputWindowAction4
+    /** Divider size to restore when output is no longer detached. */
     int origDividerSize
+    /** Detached output window component. */
     Component outputWindow
+    /** Last focused text component used by copy/select-all actions. */
     Component copyFromComponent
+    /** Placeholder component shown when output is detached. */
     Component blank
+    /** Scroll container that wraps the output area. */
     Component scrollArea
 
+    /** Whether output is cleared before each run. */
     boolean autoClearOutput = prefs.getBoolean('autoClearOutput', false)
+    /** Action that toggles automatic output clearing. */
     Action autoClearOutputAction
 
-    // Safer thread interruption
+    /** Whether the {@code @ThreadInterrupt} transform is applied to scripts. */
     boolean threadInterrupt = prefs.getBoolean('threadInterrupt', false)
+    /** Action that toggles thread interruption support. */
     Action threadInterruptAction
 
+    /** Action that toggles saving before each run. */
     Action saveOnRunAction
+    /** Whether the current script is saved before it is run. */
     boolean saveOnRun = prefs.getBoolean('saveOnRun', false)
 
+    /** Action that toggles loop mode. */
     Action loopModeAction
+    /** Whether unchanged scripts are rerun after a delay. */
     boolean loopMode = prefs.getBoolean('loopMode', false)
+    /** Hash of the last script text scheduled for execution. */
     int inputAreaContentHash
 
+    /** Name of the currently selected theme mode. */
     String currentTheme = ThemeManager.currentMode.name()
 
-    //to allow loading classes dynamically when using @Grab (GROOVY-4877, GROOVY-5871)
+    /** Whether script execution uses the shell class loader as context loader. */
     boolean useScriptClassLoaderForScriptExecution = false
 
-    // Maximum size of history
+    /** Maximum number of history entries retained by the console. */
     int maxHistory = 10
 
-    // Maximum number of characters to show on console at any time
+    /** Maximum number of characters retained in the output pane. */
     int maxOutputChars = System.getProperty('groovy.console.output.limit', '20000') as int
 
-    // File to output stdout & stderr, in addition to console
+    /** Optional writer that mirrors output to a log file. */
     PrintWriter outputPrintWriter = null
 
-    // UI
+    /** Swing builder used to create and wire the console UI. */
     SwingBuilder swing
+    /** Main console frame or dialog. */
     RootPaneContainer frame
+    /** Styled text editor used for script input. */
     ConsoleTextEditor inputEditor
+    /** Split pane separating input and output. */
     JSplitPane splitPane
+    /** Raw text component used for script editing. */
     JTextPane inputArea
+    /** Output text pane used for results and errors. */
     JTextPane outputArea
+    /** Status label shown in the footer. */
     JLabel statusLabel
+    /** Footer label showing the caret row and column. */
     JLabel rowNumAndColNum
 
-    // row info
+    /** Root document element for row calculations. */
     Element rootElement
+    /** Current caret offset in the input document. */
     int cursorPos
+    /** Current one-based caret row. */
     int rowNum
+    /** Current one-based caret column. */
     int colNum
 
-    // Styles for output area
+    /** Style used for prompt text in the output pane. */
     Style promptStyle
+    /** Style used for echoed commands in the output pane. */
     Style commandStyle
+    /** Style used for regular output text. */
     Style outputStyle
+    /** Style used for stack traces and error text. */
     Style stacktraceStyle
+    /** Style used for clickable error links. */
     Style hyperlinkStyle
+    /** Style used for evaluated result text. */
     Style resultStyle
 
-    // Internal history
+    /** Execution history records kept for navigation and result lookup. */
     List history = []
+    /** Index of the currently selected history record. */
     int historyIndex = 1 // valid values are 0..history.length()
+    /** Pending editor state kept while navigating command history. */
     HistoryRecord pendingRecord = new HistoryRecord(allText: '', selectionStart: 0, selectionEnd: 0)
+    /** Action that moves to the previous history entry. */
     Action prevHistoryAction
+    /** Action that moves to the next history entry. */
     Action nextHistoryAction
 
-    // Current editor state
+    /** Whether the current editor contents differ from the saved script. */
     boolean dirty
+    /** Action that saves the current script. */
     Action saveAction
+    /** Selection start cached from the caret listener. */
     int textSelectionStart  // keep track of selections in inputArea
+    /** Selection end cached from the caret listener. */
     int textSelectionEnd
+    /** Current script file or generated script identifier. */
     def scriptFile
+    /** Initial directory for file open/save dialogs. */
     File currentFileChooserDir = new File(Preferences.userNodeForPackage(Console).get('currentFileChooserDir', '.'))
+    /** Initial directory for classpath jar selection dialogs. */
     File currentClasspathJarDir = new File(Preferences.userNodeForPackage(Console).get('currentClasspathJarDir', '.'))
+    /** Initial directory for classpath directory selection dialogs. */
     File currentClasspathDir = new File(Preferences.userNodeForPackage(Console).get('currentClasspathDir', '.'))
 
-    // Running scripts
+    /** Base compiler configuration used to seed new scripts. */
     CompilerConfiguration baseConfig
+    /** Compiler configuration for the current script shell. */
     CompilerConfiguration config
+    /** Shell used to compile and run scripts. */
     GroovyShell shell
+    /** Counter used for generated script names. */
     int scriptNameCounter = 0
+    /** Interceptor that captures stdout. */
     SystemOutputInterceptor systemOutInterceptor
+    /** Interceptor that captures stderr. */
     SystemOutputInterceptor systemErrorInterceptor
+    /** Background thread currently compiling or running a script. */
     Thread runThread = null
+    /** Optional hook invoked before script execution starts. */
     Closure beforeExecution
+    /** Optional hook invoked after script execution completes. */
     Closure afterExecution
 
+    /** Console window icon resource. */
     public static URL ICON_PATH = Console.class.classLoader.getResource('groovy/console/ui/ConsoleIcon.png')
-    // used by ObjectBrowser and AST Viewer
+    /** Returns the icon used for AST and object browser tree nodes. */
     static javax.swing.Icon getNodeIcon() { Icons.green('fiber_manual_record') }
-    // used by AST Viewer
 
+    /** File filter used for Groovy script open/save dialogs. */
     static groovyFileFilter = new GroovyFileFilter()
+    /** Whether a script is currently being compiled or executed. */
     boolean scriptRunning = false
+    /** Whether the last failure was a stack overflow. */
     boolean stackOverFlowError = false
+    /** Action that interrupts the active script thread. */
     Action interruptAction
 
-    // Script arguments
+    /** Space-separated arguments passed to script execution. */
     String scriptArgs = ''
+    /** Action that edits the configured script arguments. */
     Action setScriptArgsAction
 
+    /** Action that selects the next word in the editor. */
     Action selectWordAction
+    /** Action that selects the previous word in the editor. */
     Action selectPreviousWordAction
 
+    /** Lazily created preferences dialog controller. */
     ConsolePreferences consolePreferences
 
+    /** Launches the console application from the command line. */
     static void main(args) {
         MessageSource messages = new MessageSource(Console)
         def cli = new CliBuilderInternal(usage: 'groovyConsole [options] [filename]', stopAtNonOption: false,
@@ -314,6 +394,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Loads the configured output size limit, honoring the system property override. */
     int loadMaxOutputChars() {
         // For backwards compatibility 'maxOutputChars' remains defined in the Console class
         // and the System Property takes precedence as the default value.
@@ -321,6 +402,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         return System.getProperty('groovy.console.output.limit', "${max}") as int
     }
 
+    /** Shows the console preferences dialog. */
     void preferences(EventObject evt = null) {
         if (!consolePreferences) {
             consolePreferences = new ConsolePreferences(this)
@@ -328,6 +410,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         consolePreferences.show()
     }
 
+    /** Updates output mirroring preferences and recreates the log writer if needed. */
     void setOutputPreferences(boolean useOutputFile, File outputFile) {
         prefs.remove('outputLogFileName')
         if (!useOutputFile) {
@@ -341,12 +424,14 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Opens the configured output log file in append mode. */
     void createOutputPrintWriter(File outputFile) {
         outputPrintWriter = new PrintWriter(new FileOutputStream(
                 outputFile,
                 true))
     }
 
+    /** Closes the optional output log writer. */
     void closeOutputPrintWriter() {
         if (outputPrintWriter != null) {
             outputPrintWriter.close()
@@ -354,10 +439,12 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Creates a console backed by a fresh binding. */
     Console(Binding binding = new Binding()) {
         this(null, binding)
     }
 
+    /** Creates a console with the supplied parent loader, binding, and base compiler configuration. */
     Console(ClassLoader parent, Binding binding = new Binding(), CompilerConfiguration baseConfig = new CompilerConfiguration(System.getProperties())) {
         this.baseConfig = baseConfig
         this.maxOutputChars = loadMaxOutputChars()
@@ -403,6 +490,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         binding.variables._outputTransforms = OutputTransforms.loadOutputTransforms()
     }
 
+    /** Recreates the Groovy shell for a new script context. */
     void newScript(ClassLoader parent, Binding binding) {
         config = new CompilerConfiguration(baseConfig)
         config.addCompilationCustomizers(*baseConfig.compilationCustomizers)
@@ -412,6 +500,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         shell = new GroovyShell(parent, binding, config)
     }
 
+    /** Default Swing delegates used to build the console frame and menu bar. */
     static frameConsoleDelegates = [
             rootContainerDelegate: {
                 frame(
@@ -433,10 +522,12 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
             }
     ]
 
+    /** Builds and shows the console UI using default delegates. */
     void run() {
         run(frameConsoleDelegates)
     }
 
+    /** Builds and shows the console UI using the supplied Swing delegates. */
     void run(Map defaults) {
 
         swing = new SwingBuilder()
@@ -518,6 +609,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         })
     }
 
+    /** Starts interceptors that route standard output and error into the console. */
     void installInterceptor() {
         systemOutInterceptor = new SystemOutputInterceptor(this.&notifySystemOut, true)
         systemOutInterceptor.start()
@@ -526,6 +618,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         // TODO: would this be a good place to assign the console id?
     }
 
+    /** Adds a history record and trims the list to the configured maximum size. */
     void addToHistory(record) {
         history.add(record)
         // history.size here just retrieves method closure
@@ -547,21 +640,24 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
-    // Append a string to the output area
+    /** Appends plain text to the output pane. */
     void appendOutput(String text, AttributeSet style) {
         def doc = outputArea.styledDocument
         insertString(doc, doc.length, text, style)
         ensureNoDocLengthOverflow(doc)
     }
 
+    /** Appends a window description to the output pane. */
     void appendOutput(Window window, AttributeSet style) {
         appendOutput(window.toString(), style)
     }
 
+    /** Appends an object's string form to the output pane. */
     void appendOutput(Object object, AttributeSet style) {
         appendOutput(object.toString(), style)
     }
 
+    /** Appends an embedded component to the output pane. */
     void appendOutput(Component component, AttributeSet style) {
         SimpleAttributeSet sas = new SimpleAttributeSet()
         sas.addAttribute(StyleConstants.NameAttribute, 'component')
@@ -569,6 +665,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         appendOutput(component.toString(), sas)
     }
 
+    /** Appends an embedded icon to the output pane. */
     void appendOutput(Icon icon, AttributeSet style) {
         SimpleAttributeSet sas = new SimpleAttributeSet()
         sas.addAttribute(StyleConstants.NameAttribute, 'icon')
@@ -576,6 +673,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         appendOutput(icon.toString(), sas)
     }
 
+    /** Appends a stack trace, hyperlinking script line references when possible. */
     void appendStacktrace(text) {
         // prevent NPE when outputArea is missing, i.e. there is currently no window present
         // TODO the text should not be swallowed (options: postpone output, open new window, log file, terminal, ...)
@@ -621,6 +719,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         ensureNoDocLengthOverflow(doc)
     }
 
+    /** Inserts text into a document and optionally mirrors it to the output log file. */
     void insertString(Document doc, int offset, String text, AttributeSet attributeSet, boolean outputToFile = true) {
         doc.insertString(offset, text, attributeSet)
 
@@ -631,7 +730,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
-    // Append a string to the output area on a new line
+    /** Appends text to the output pane, forcing a preceding line break. */
     void appendOutputNl(text, style) {
         def doc = outputArea.styledDocument
         def len = doc.length
@@ -643,6 +742,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         appendOutput(text, style)
     }
 
+    /** Appends text and preserves compact line spacing in the output pane. */
     void appendOutputLines(text, style) {
         appendOutput(text, style)
         def doc = outputArea.styledDocument
@@ -653,7 +753,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         doc.remove(len, 2) // windows hack to fix (improve?) line spacing
     }
 
-    // Return false if use elected to cancel
+    /** Prompts to save unsaved changes before an operation proceeds. */
     boolean askToSaveFile() {
         if (!dirty) {
             return true
@@ -670,27 +770,30 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Emits the platform default warning beep. */
     void beep() {
         Toolkit.defaultToolkit.beep()
     }
 
-    // Binds the '_' and '__' variables in the shell
+    /** Refreshes the shell bindings that expose the last result and result history. */
     void bindResults() {
         shell.setVariable('_', getLastResult()) // lastResult doesn't seem to work
         shell.setVariable('__', history.collect { it.result })
     }
 
-    // Handles menu event
+    /** Toggles whether stdout is captured by all console windows. */
     static void captureStdOut(EventObject evt) {
         captureStdOut = evt.source.selected
         prefs.putBoolean('captureStdOut', captureStdOut)
     }
 
+    /** Toggles whether stderr is captured by all console windows. */
     static void captureStdErr(EventObject evt) {
         captureStdErr = evt.source.selected
         prefs.putBoolean('captureStdErr', captureStdErr)
     }
 
+    /** Toggles whether full stack traces are reported for failures. */
     void fullStackTraces(EventObject evt) {
         fullStackTraces = evt.source.selected
         System.setProperty('groovy.full.stacktrace',
@@ -698,22 +801,26 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         prefs.putBoolean('fullStackTraces', fullStackTraces)
     }
 
+    /** Toggles whether executed source text is echoed to the output pane. */
     void showScriptInOutput(EventObject evt) {
         showScriptInOutput = evt.source.selected
         prefs.putBoolean('showScriptInOutput', showScriptInOutput)
     }
 
+    /** Toggles whether results are transformed before display. */
     void visualizeScriptResults(EventObject evt) {
         visualizeScriptResults = evt.source.selected
         prefs.putBoolean('visualizeScriptResults', visualizeScriptResults)
     }
 
+    /** Toggles toolbar visibility and persists the selection. */
     void showToolbar(EventObject evt) {
         showToolbar = evt.source.selected
         prefs.putBoolean('showToolbar', showToolbar)
         toolbar.visible = showToolbar
     }
 
+    /** Toggles the input/output split orientation. */
     void orientationVertical(EventObject evt) {
         def oldValue = orientationVertical
         orientationVertical = evt.source.selected
@@ -729,6 +836,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Toggles whether output is shown in a detached window. */
     void detachedOutput(EventObject evt) {
         def oldDetachedOutput = detachedOutput
         detachedOutput = evt.source.selected
@@ -751,18 +859,35 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Toggles whether output is cleared before each run or compile. */
     void autoClearOutput(EventObject evt) {
         autoClearOutput = evt.source.selected
         prefs.putBoolean('autoClearOutput', autoClearOutput)
     }
 
-    /** @since 6.0.0 */
+    /**
+     * Switches the console to the bundled light theme.
+     *
+     * @since 6.0.0
+     */
     void lightTheme(EventObject evt = null) { switchTheme(ThemeManager.ThemeMode.LIGHT) }
-    /** @since 6.0.0 */
+    /**
+     * Switches the console to the bundled dark theme.
+     *
+     * @since 6.0.0
+     */
     void darkTheme(EventObject evt = null) { switchTheme(ThemeManager.ThemeMode.DARK) }
-    /** @since 6.0.0 */
+    /**
+     * Switches the console to follow the operating system theme.
+     *
+     * @since 6.0.0
+     */
     void systemTheme(EventObject evt = null) { switchTheme(ThemeManager.ThemeMode.SYSTEM) }
-    /** @since 6.0.0 */
+    /**
+     * Advances to the next available theme mode.
+     *
+     * @since 6.0.0
+     */
     void cycleTheme(EventObject evt = null) { switchTheme(ThemeManager.cycleMode()) }
 
     private void switchTheme(ThemeManager.ThemeMode mode) {
@@ -856,6 +981,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         outputArea.repaint()
     }
 
+    /** Toggles the {@code @ThreadInterrupt} transform for future scripts. */
     void threadInterruption(EventObject evt) {
         threadInterrupt = evt.source.selected
         prefs.putBoolean('threadInterrupt', threadInterrupt)
@@ -874,6 +1000,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Updates cached selection bounds and the row/column display. */
     void caretUpdate(CaretEvent e) {
         textSelectionStart = Math.min(dot(e), mark(e))
         textSelectionEnd = Math.max(dot(e), mark(e))
@@ -882,21 +1009,24 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
 
     // GROOVY-8339: to avoid illegal access to a non-visible implementation class - can be removed if a more general solution is found
     @CompileStatic
+    /** Returns the caret dot position without touching implementation details. */
     int dot(CaretEvent e) {
         e.dot
     }
 
     // GROOVY-8339: to avoid illegal access to a non-visible implementation class - can be removed if a more general solution is found
     @CompileStatic
+    /** Returns the caret mark position without touching implementation details. */
     int mark(CaretEvent e) {
         e.mark
     }
 
+    /** Clears all text from the output pane. */
     void clearOutput(EventObject evt = null) {
         outputArea.text = ''
     }
 
-    // If at exit time, a script is running, the user is given an option to interrupt it first
+    /** Prompts to interrupt the running script before exiting. */
     def askToInterruptScript() {
         if (!scriptRunning) return true
         def rc = JOptionPane.showConfirmDialog(frame, "Script executing. Press 'OK' to attempt to interrupt it before exiting.",
@@ -909,10 +1039,12 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Interrupts the currently running script thread, if any. */
     void doInterrupt(EventObject evt = null) {
         runThread?.interrupt()
     }
 
+    /** Handles desktop quit requests by delegating to {@link #exit}. */
     void exitDesktop(EventObject evt = null, quitResponse = null) {
         if (exit(evt)) {
             quitResponse.performQuit()
@@ -921,6 +1053,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Closes this console after offering to interrupt and save. */
     boolean exit(EventObject evt = null) {
         if (askToInterruptScript()) {
             def exit = askToSaveFile()
@@ -941,6 +1074,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Resets the editor to a new unsaved script. */
     void fileNewFile(EventObject evt = null) {
         if (askToSaveFile()) {
             scriptFile = null
@@ -949,7 +1083,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
-    // Start a new window with a copy of current variables
+    /** Opens another console window seeded with the current binding variables. */
     void fileNewWindow(EventObject evt = null) {
         Console consoleController = new Console(
                 new Binding(
@@ -974,6 +1108,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         swing.doLater swing.inputArea.&requestFocus
     }
 
+    /** Prompts for a script file and loads it into the editor. */
     void fileOpen(EventObject evt = null) {
         if (askToSaveFile()) {
             def scriptName = selectFilename()
@@ -983,6 +1118,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Loads the supplied script file into the editor. */
     void loadScriptFile(File file) {
         swing.edt {
             inputArea.editable = false
@@ -1014,7 +1150,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
-    // Save file - return false if user cancelled save
+    /** Saves the current script, prompting for a file when needed. */
     boolean fileSave(EventObject evt = null) {
         if (scriptFile == null) {
             return fileSaveAs(evt)
@@ -1025,7 +1161,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         return true
     }
 
-    // Save file - return false if user cancelled save
+    /** Saves the current script under a newly selected file name. */
     boolean fileSaveAs(EventObject evt = null) {
         scriptFile = selectFilename('Save')
         if (scriptFile != null) {
@@ -1037,6 +1173,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Reports a compilation or execution failure in the output pane. */
     def finishException(Throwable t, boolean executing) {
         if (executing) {
             statusLabel.text = 'Execution terminated with exception.'
@@ -1133,6 +1270,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         appendStacktrace("\n${sw.builder}\n")
     }
 
+    /** Reports successful execution and publishes the resulting value. */
     def finishNormal(Object result, Long elapsedTime=null) {
         String elapsedTimeStr = null != elapsedTime ? " Elapsed time: ${elapsedTime}ms." : ''
         // Take down the wait/cancel dialog
@@ -1156,6 +1294,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Reports successful compilation without execution. */
     def compileFinishNormal() {
         statusLabel.text = 'Compilation complete.'
     }
@@ -1168,7 +1307,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         outputWindow.pack()
     }
 
-    // Gets the last, non-null result
+    /** Returns the most recent non-null result from execution history. */
     def getLastResult() {
         // runtime bugs in here history.reverse produces odd lookup
         // return history.reverse.find {it != null}
@@ -1183,6 +1322,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         return null
     }
 
+    /** Moves forward in command history. */
     void historyNext(EventObject evt = null) {
         if (historyIndex < history.size()) {
             setInputTextFromHistory(historyIndex + 1)
@@ -1192,6 +1332,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Moves backward in command history. */
     void historyPrev(EventObject evt = null) {
         if (historyIndex > 0) {
             setInputTextFromHistory(historyIndex - 1)
@@ -1201,6 +1342,7 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
+    /** Opens the object browser for the last non-null result. */
     void inspectLast(EventObject evt = null) {
         if (null == lastResult) {
             JOptionPane.showMessageDialog(frame, 'The last result is null.',
@@ -1210,14 +1352,17 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         ObjectBrowser.inspect(lastResult)
     }
 
+    /** Opens the object browser for the current shell variables. */
     void inspectVariables(EventObject evt = null) {
         ObjectBrowser.inspect(shell.getContext().variables)
     }
 
+    /** Opens the AST browser for the current editor contents. */
     void inspectAst(EventObject evt = null) {
         new AstBrowser(inputArea, rootElement, shell.getClassLoader(), config).run({ inputArea.getText() })
     }
 
+    /** Opens the CST viewer for the current editor contents. */
     void inspectCst(EventObject evt = null) {
         String text = this.inputEditor.textEditor.text
         def charStream = CharStreams.fromReader(new StringReader(text))
@@ -1269,30 +1414,59 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         null
     }
 
+    /** Opens the lexer token inspector for the current editor contents. */
     void inspectTokens(EventObject evt = null) {
         def content = inputArea.getText()
         def lf = new LexerFrame(new StringReader(content))
         lf.visible = true
     }
 
-    /** @since 6.0.0 */
+    /**
+     * Returns whether toolbar icons follow the editor font size.
+     *
+     * @since 6.0.0
+     */
     boolean isScaleIconsWithFont() { prefs.getBoolean('scaleIconsWithFont', false) }
-    /** @since 6.0.0 */
+    /**
+     * Returns the current toolbar icon size.
+     *
+     * @since 6.0.0
+     */
     int getCurrentIconSize() { Icons.currentSize }
 
-    /** @since 6.0.0 */
+    /**
+     * Switches toolbar icons to the small preset.
+     *
+     * @since 6.0.0
+     */
     void smallIcons(EventObject evt = null) { applyIconSize(Icons.SIZE_SMALL) }
-    /** @since 6.0.0 */
+    /**
+     * Switches toolbar icons to the normal preset.
+     *
+     * @since 6.0.0
+     */
     void normalIcons(EventObject evt = null) { applyIconSize(Icons.SIZE_NORMAL) }
-    /** @since 6.0.0 */
+    /**
+     * Switches toolbar icons to the large preset.
+     *
+     * @since 6.0.0
+     */
     void largeIcons(EventObject evt = null) { applyIconSize(Icons.SIZE_LARGE) }
 
-    /** @since 6.0.0 */
+    /**
+     * Toggles whether toolbar icons track the editor font size.
+     *
+     * @since 6.0.0
+     */
     void scaleIconsWithFont(EventObject evt = null) {
         setScaleIconsWithFont(evt?.source?.isSelected() as boolean)
     }
 
-    /** @since 6.0.0 */
+    /**
+     * Persists whether toolbar icons track the editor font size.
+     *
+     * @since 6.0.0
+     */
     void setScaleIconsWithFont(boolean enabled) {
         prefs.putBoolean('scaleIconsWithFont', enabled)
         if (enabled) {
@@ -1302,7 +1476,11 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         }
     }
 
-    /** @since 6.0.0 */
+    /**
+     * Applies a toolbar icon size and refreshes the toolbar.
+     *
+     * @since 6.0.0
+     */
     void applyIconSize(int size) {
         // only persist the preset when not tracking the font
         if (!prefs.getBoolean('scaleIconsWithFont', false)) {
@@ -1313,12 +1491,20 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         toolbar?.repaint()
     }
 
-    /** @since 6.0.0 */
+    /**
+     * Reapplies the current theme and retints console components.
+     *
+     * @since 6.0.0
+     */
     void reapplyTheme() {
         switchTheme(ThemeManager.currentMode)
     }
 
-    /** @since 6.0.0 */
+    /**
+     * Reloads theme definitions and reapplies the active theme.
+     *
+     * @since 6.0.0
+     */
     void reloadThemes() {
         ThemeManager.reloadThemes()
         reapplyTheme()
@@ -1341,10 +1527,12 @@ class Console implements CaretListener, HyperlinkListener, ComponentListener, Fo
         prefs.getInt('iconSize', Icons.SIZE_NORMAL)
     }
 
-void largerFont(EventObject evt = null) {
+    /** Increases the editor font size. */
+    void largerFont(EventObject evt = null) {
         updateFontSize(inputArea.font.size + 2)
     }
 
+    /** Routes captured stdout to the owning console or every console window. */
     static boolean notifySystemOut(int consoleId, String str) {
         if (!captureStdOut) {
             // Output as normal
@@ -1369,6 +1557,7 @@ void largerFont(EventObject evt = null) {
         return false
     }
 
+    /** Routes captured stderr to the owning console or every console window. */
     static boolean notifySystemErr(int consoleId, String str) {
         if (!captureStdErr) {
             // Output as normal
@@ -1393,6 +1582,7 @@ void largerFont(EventObject evt = null) {
         return false
     }
 
+    /** Returns the identifier used by output interceptors for this console. */
     int getConsoleId() {
         return System.identityHashCode(this)
     }
@@ -1460,11 +1650,12 @@ void largerFont(EventObject evt = null) {
         abstract Object compile(String src)
     }
 
+    /** Compiles and runs the current editor contents as Java source. */
     void runJava(EventObject evt = null) {
         runScript(evt, new JavaSourceType())
     }
 
-    // actually run the script
+    /** Compiles and runs the current editor contents. */
     void runScript(EventObject evt = null, SourceType st = new GroovySourceType()) {
         saveInputAreaContentHash()
         if (saveOnRun && scriptFile != null) {
@@ -1474,25 +1665,30 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Toggles whether scripts are saved before they run. */
     void saveOnRun(EventObject evt = null) {
         saveOnRun = evt.source.selected
         prefs.putBoolean('saveOnRun', saveOnRun)
     }
 
+    /** Toggles whether the console reruns unchanged scripts after a delay. */
     void loopMode(EventObject evt = null) {
         loopMode = evt.source.selected
         prefs.putBoolean('loopMode', loopMode)
     }
 
+    /** Compiles and runs the current selection as Java source. */
     void runSelectedJava(EventObject evt = null) {
         runSelectedScript(evt, new JavaSourceType())
     }
 
+    /** Compiles and runs only the current editor selection. */
     void runSelectedScript(EventObject evt = null, SourceType st = new GroovySourceType()) {
         saveInputAreaContentHash()
         runScriptImpl(true, st)
     }
 
+    /** Adds jar files to the shell classpath. */
     void addClasspathJar(EventObject evt = null) {
         def fc = new JFileChooser(currentClasspathJarDir)
         fc.fileSelectionMode = JFileChooser.FILES_ONLY
@@ -1507,6 +1703,7 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Adds a directory to the shell classpath. */
     void addClasspathDir(EventObject evt = null) {
         def fc = new JFileChooser(currentClasspathDir)
         fc.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY
@@ -1518,6 +1715,7 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Displays the current shell classpath in a dialog. */
     void listClasspath(EventObject evt = null) {
         List<URL> urls = []
 
@@ -1548,6 +1746,7 @@ void largerFont(EventObject evt = null) {
         dialog.visible = true
     }
 
+    /** Clears the shell binding and starts a fresh script context. */
     void clearContext(EventObject evt = null) {
         def binding = new Binding()
         newScript(null, binding)
@@ -1555,7 +1754,11 @@ void largerFont(EventObject evt = null) {
         binding.variables._outputTransforms = OutputTransforms.loadOutputTransforms()
     }
 
-    /** @since 6.0.0 */
+    /**
+     * Prompts for space-separated script arguments used by future runs.
+     *
+     * @since 6.0.0
+     */
     void setScriptArgs(EventObject evt = null) {
         def result = JOptionPane.showInputDialog(frame, 'Enter script arguments (space-separated):',
                 'Set Script Arguments', JOptionPane.PLAIN_MESSAGE, null, null, scriptArgs)
@@ -1687,10 +1890,12 @@ void largerFont(EventObject evt = null) {
         return Optional.empty()
     }
 
+    /** Compiles the current editor contents as Java source. */
     void compileAsJava(EventObject evt = null) {
         compileScript(evt, new JavaSourceType())
     }
 
+    /** Compiles the current editor contents without running them. */
     void compileScript(EventObject evt = null, SourceType st = new GroovySourceType()) {
         if (scriptRunning) {
             statusLabel.text = 'Cannot compile script now as a script is already running. Please wait or use "Interrupt Script" option.'
@@ -1728,6 +1933,7 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Opens a file chooser and returns the selected script file. */
     def selectFilename(name = 'Open') {
         def fc = new JFileChooser(currentFileChooserDir)
         fc.fileSelectionMode = JFileChooser.FILES_ONLY
@@ -1745,6 +1951,7 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Marks the editor dirty state and refreshes save affordances. */
     void setDirty(boolean newDirty) {
         //TODO when @BoundProperty is live, this should be handled via listeners
         dirty = newDirty
@@ -1779,12 +1986,12 @@ void largerFont(EventObject evt = null) {
         prevHistoryAction.enabled = historyIndex > 0
     }
 
-    // Adds a variable to the binding
-    // Useful for adding variables before opening the console
+    /** Adds a variable to the shell binding. */
     void setVariable(String name, Object value) {
         shell.getContext().setVariable(name, value)
     }
 
+    /** Shows the about dialog for the console. */
     void showAbout(EventObject evt = null) {
         def version = GroovySystem.getVersion()
         def pane = swing.optionPane()
@@ -1802,14 +2009,17 @@ void largerFont(EventObject evt = null) {
         dialog.show()
     }
 
+    /** Shows the find dialog. */
     void find(EventObject evt = null) {
         FindReplaceUtility.showDialog()
     }
 
+    /** Repeats the previous find operation in the forward direction. */
     void findNext(EventObject evt = null) {
         FindReplaceUtility.FIND_ACTION.actionPerformed(evt)
     }
 
+    /** Repeats the previous find operation in the reverse direction. */
     void findPrevious(EventObject evt = null) {
         def reverseEvt = new ActionEvent(
                 evt.getSource(), evt.getID(),
@@ -1818,10 +2028,12 @@ void largerFont(EventObject evt = null) {
         FindReplaceUtility.FIND_ACTION.actionPerformed(reverseEvt)
     }
 
+    /** Shows the replace dialog. */
     void replace(EventObject evt = null) {
         FindReplaceUtility.showDialog(true)
     }
 
+    /** Comments or uncomments the current line selection. */
     void comment(EventObject evt = null) {
         def rootElement = inputArea.document.defaultRootElement
         def cursorPos = inputArea.getCaretPosition()
@@ -1863,6 +2075,7 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Expands the selection from word to line to surrounding block. */
     void selectBlock(EventObject evt = null) {
         final int startPos = inputArea.getSelectionStart()
         final int endPos = inputArea.getSelectionEnd()
@@ -1931,19 +2144,22 @@ void largerFont(EventObject evt = null) {
         inputArea.setSelectionEnd(endBlockPos)
     }
 
+    /** Updates the status bar with the supplied message. */
     void showMessage(String message) {
         statusLabel.text = message
     }
 
+    /** Shows the standard script-executing status message. */
     void showExecutingMessage() {
         statusLabel.text = 'Script executing now. Please wait or use "Interrupt Script" option.'
     }
 
+    /** Shows the standard script-compiling status message. */
     void showCompilingMessage() {
         statusLabel.text = 'Script compiling now. Please wait.'
     }
 
-    // Shows the detached 'outputArea' dialog
+    /** Shows the detached output window when detached mode is enabled. */
     void showOutputWindow(EventObject evt = null) {
         if (detachedOutput) {
             outputWindow.setLocationRelativeTo(frame)
@@ -1951,27 +2167,32 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Hides the detached output window when detached mode is enabled. */
     void hideOutputWindow(EventObject evt = null) {
         if (detachedOutput) {
             outputWindow.visible = false
         }
     }
 
+    /** Clears and then hides the detached output window. */
     void hideAndClearOutputWindow(EventObject evt = null) {
         clearOutput()
         hideOutputWindow()
     }
 
+    /** Decreases the editor font size. */
     void smallerFont(EventObject evt = null) {
         updateFontSize(inputArea.font.size - 2)
     }
 
+    /** Switches between smart and regex-based syntax highlighters. */
     void smartHighlighter(EventObject evt = null) {
         inputEditor.enableHighLighter(evt.source.selected ? SmartDocumentFilter : GroovyFilter)
         inputEditor.textEditor.setText(inputEditor.textEditor.getText()) // enable the highlighter immediately
         prefs.putBoolean('smartHighlighter', evt.source.selected)
     }
 
+    /** Updates the main window title to reflect the current script and dirty state. */
     void updateTitle() {
         if (frame.title) {
             String title = 'GroovyConsole'
@@ -2020,6 +2241,7 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Invokes a text action against the active source component when present. */
     void invokeTextAction(evt, closure, area = inputArea) {
         def source = evt.getSource()
         if (source != null) {
@@ -2027,22 +2249,27 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** Cuts the current editor selection. */
     void cut(EventObject evt = null) {
         invokeTextAction(evt, { source -> source.cut() })
     }
 
+    /** Copies the current selection from the focused text component. */
     void copy(EventObject evt = null) {
         invokeTextAction(evt, { source -> source.copy() }, copyFromComponent ?: inputArea)
     }
 
+    /** Pastes clipboard text into the input editor. */
     void paste(EventObject evt = null) {
         invokeTextAction(evt, { source -> source.paste() })
     }
 
+    /** Selects all text in the focused text component. */
     void selectAll(EventObject evt = null) {
         invokeTextAction(evt, { source -> source.selectAll() }, copyFromComponent ?: inputArea)
     }
 
+    /** Updates the cached caret row and column display. */
     void setRowNumAndColNum() {
         cursorPos = inputArea.getCaretPosition()
         rowNum = rootElement.getElementIndex(cursorPos) + 1
@@ -2053,18 +2280,22 @@ void largerFont(EventObject evt = null) {
         rowNumAndColNum.setText("$rowNum:$colNum")
     }
 
+    /** Prints the input editor contents. */
     void print(EventObject evt = null) {
         inputEditor.printAction.actionPerformed(evt)
     }
 
+    /** Undoes the most recent edit in the input editor. */
     void undo(EventObject evt = null) {
         inputEditor.undoAction.actionPerformed(evt)
     }
 
+    /** Redoes the most recently undone edit in the input editor. */
     void redo(EventObject evt = null) {
         inputEditor.redoAction.actionPerformed(evt)
     }
 
+    /** Highlights the source line referenced by an activated output hyperlink. */
     void hyperlinkUpdate(HyperlinkEvent e) {
         if (e.eventType == HyperlinkEvent.EventType.ACTIVATED) {
             // URL of the form: file://myscript.groovy:32
@@ -2099,10 +2330,13 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** No-op component listener implementation. */
     void componentHidden(ComponentEvent e) {}
 
+    /** No-op component listener implementation. */
     void componentMoved(ComponentEvent e) {}
 
+    /** Persists component dimensions when the editor or frame is resized. */
     void componentResized(ComponentEvent e) {
         def component = e.getComponent()
         if (component == outputArea || component == inputArea) {
@@ -2115,8 +2349,10 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** No-op component listener implementation. */
     void componentShown(ComponentEvent e) {}
 
+    /** Tracks the last focused text component for copy and select-all actions. */
     void focusGained(FocusEvent e) {
         // remember component with focus for text-copy functionality
         if (e.component == outputArea || e.component == inputArea) {
@@ -2124,6 +2360,7 @@ void largerFont(EventObject evt = null) {
         }
     }
 
+    /** No-op focus listener implementation. */
     void focusLost(FocusEvent e) {}
 
     private static boolean isWindows() {
@@ -2135,11 +2372,13 @@ void largerFont(EventObject evt = null) {
     }
 }
 
+/** File filter for Groovy source files recognized by the console. */
 @CompileStatic
 class GroovyFileFilter extends FileFilter {
     private static final List GROOVY_SOURCE_EXTENSIONS = ['*.groovy', '*.gvy', '*.gy', '*.gsh', '*.story', '*.gpp', '*.grunit']
     private static final GROOVY_SOURCE_EXT_DESC = GROOVY_SOURCE_EXTENSIONS.join(',')
 
+    /** Accepts directories and files with supported Groovy source extensions. */
     boolean accept(File f) {
         if (f.isDirectory()) {
             return true
@@ -2147,10 +2386,12 @@ class GroovyFileFilter extends FileFilter {
         GROOVY_SOURCE_EXTENSIONS.find { it == getExtension(f) } ? true : false
     }
 
+    /** Returns the chooser description for supported Groovy source files. */
     String getDescription() {
         "Groovy Source Files ($GROOVY_SOURCE_EXT_DESC)"
     }
 
+    /** Returns the wildcard extension for the supplied file name. */
     static String getExtension(File f) {
         def ext = null
         def s = f.getName()
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleIvyPlugin.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleIvyPlugin.groovy
index a2580e6734..21e0b3a080 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleIvyPlugin.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleIvyPlugin.groovy
@@ -27,10 +27,18 @@ import groovy.grape.GrapeEngine
  * Adds Groovy Grape feedback (via an Ivy listener).
  */
 class ConsoleIvyPlugin {
+    /** Console receiving dependency progress messages. */
     Console savedConsole
+    /** Dependency coordinates already reported as resolving. */
     Set<String> resolvedDependencies = []
+    /** Artifacts already reported as downloading. */
     Set<String> downloadedArtifacts = []
 
+    /**
+     * Registers an Ivy listener that reports Grape progress to the console.
+     *
+     * @param console console to receive progress messages
+     */
     def addListener(Console console) {
         savedConsole = console
         GrapeEngine engine = Grape.instance
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleMavenPlugin.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleMavenPlugin.groovy
index fb21e82cfa..96f39f8cc1 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleMavenPlugin.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleMavenPlugin.groovy
@@ -27,10 +27,18 @@ import groovy.grape.GrapeEngine
  * @since 6.0.0
  */
 class ConsoleMavenPlugin {
+    /** Console receiving dependency progress messages. */
     Console savedConsole
+    /** Dependency coordinates already reported as resolving. */
     Set<String> resolvedDependencies = []
+    /** Artifacts already reported as downloading. */
     Set<String> downloadedArtifacts = []
 
+    /**
+     * Registers a Maven Resolver listener that reports Grape progress to the console.
+     *
+     * @param console console to receive progress messages
+     */
     def addListener(Console console) {
         savedConsole = console
         GrapeEngine engine = Grape.instance
@@ -52,4 +60,3 @@ class ConsoleMavenPlugin {
         }
     }
 }
-
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsolePreferences.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsolePreferences.groovy
index 912191804b..47b99ec1fa 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsolePreferences.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsolePreferences.groovy
@@ -28,27 +28,37 @@ import javax.swing.JOptionPane
 import javax.swing.filechooser.FileNameExtensionFilter
 import java.awt.Dimension
 
+/**
+ * Manages the Groovy Console preferences dialog and persisted settings.
+ */
 class ConsolePreferences {
 
-    // Default maximum number of characters to show on console at any time
+    /** Default maximum number of characters retained in the output area. */
     static int DEFAULT_MAX_OUTPUT_CHARS = 20000
+    /** Default loop mode delay, in milliseconds. */
     static int DEFAULT_LOOP_MODE_DELAY_MILLIS = 1000
 
+    /** Maximum number of characters retained in the output area. */
     @Bindable
     int maxOutputChars
 
+    /** Delay between loop mode executions, in milliseconds. */
     @Bindable
     int loopModeDelay
 
+    /** Selected icon size for console actions. */
     @Bindable
     int iconSize
 
+    /** Whether action icons should track the current font size. */
     @Bindable
     boolean scaleIconsWithFont
 
+    /** Optional custom light theme path. */
     @Bindable
     String customLightThemePath
 
+    /** Optional custom dark theme path. */
     @Bindable
     String customDarkThemePath
 
@@ -56,8 +66,14 @@ class ConsolePreferences {
     private final MessageSource T
 
     private JDialog dialog
+    /** Output file currently selected in the preferences dialog. */
     File outputFile
 
+    /**
+     * Creates a preferences controller for the supplied console.
+     *
+     * @param console console instance that owns the dialog
+     */
     ConsolePreferences(console) {
         this.console = console
         T = new MessageSource(Console)
@@ -71,6 +87,9 @@ class ConsolePreferences {
         console.maxOutputChars = maxOutputChars
     }
 
+    /**
+     * Displays the preferences dialog.
+     */
     void show() {
         console.swing.edt {
             if (!dialog) {
@@ -345,6 +364,11 @@ class ConsolePreferences {
     }
 
     // Useful for testing gui
+    /**
+     * Launches the preferences dialog in isolation for manual UI checks.
+     *
+     * @param args ignored command-line arguments
+     */
     static void main(args) {
         javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName())
         def c = new Expando().with {
@@ -363,4 +387,4 @@ class ConsolePreferences {
         println "console.maxOutputChars==${c.maxOutputChars}"
         println 'done'
     }
-}
\ No newline at end of file
+}
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleSupport.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleSupport.java
index d304f5b676..e2dfc8dcac 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleSupport.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleSupport.java
@@ -28,16 +28,25 @@ import javax.swing.text.StyledDocument;
 import java.awt.Color;
 
 /**
- * Base class for console
+ * Base support class for consoles that evaluate Groovy scripts and render styled output.
  */
 public abstract class ConsoleSupport {
 
+    /** Style used for prompts. */
     Style promptStyle;
+    /** Style used for entered commands. */
     Style commandStyle;
+    /** Style used for evaluated output. */
     Style outputStyle;
     private GroovyShell shell;
+    /** Counter used to create unique script names. */
     int counter;
 
+    /**
+     * Initializes the styles used by the output document.
+     *
+     * @param outputArea text pane whose styled document should be configured
+     */
     protected void addStylesToDocument(JTextPane outputArea) {
         StyledDocument doc = outputArea.getStyledDocument();
 
@@ -56,18 +65,38 @@ public abstract class ConsoleSupport {
         StyleConstants.setBold(outputStyle, true);
     }
 
+    /**
+     * Returns the style used for entered commands.
+     *
+     * @return the command style
+     */
     public Style getCommandStyle() {
         return commandStyle;
     }
 
+    /**
+     * Returns the style used for evaluated output.
+     *
+     * @return the output style
+     */
     public Style getOutputStyle() {
         return outputStyle;
     }
 
+    /**
+     * Returns the style used for prompts.
+     *
+     * @return the prompt style
+     */
     public Style getPromptStyle() {
         return promptStyle;
     }
 
+    /**
+     * Returns the shell used for script evaluation.
+     *
+     * @return the lazily created shell
+     */
     public GroovyShell getShell() {
         if (shell == null) {
             shell = new GroovyShell();
@@ -75,6 +104,12 @@ public abstract class ConsoleSupport {
         return shell;
     }
 
+    /**
+     * Evaluates the supplied text and delegates failures to {@link #handleException(String, Exception)}.
+     *
+     * @param text script text to evaluate
+     * @return the evaluation result, or {@code null} when evaluation fails
+     */
     protected Object evaluate(String text) {
         String name = "Script" + counter++;
         try {
@@ -85,5 +120,11 @@ public abstract class ConsoleSupport {
         }
     }
 
+    /**
+     * Handles an exception raised while evaluating the supplied script text.
+     *
+     * @param text script text being evaluated
+     * @param e exception raised during evaluation
+     */
     protected abstract void handleException(String text, Exception e);
-}
\ No newline at end of file
+}
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleTextEditor.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleTextEditor.java
index dca38fadeb..27328dc2f7 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleTextEditor.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleTextEditor.java
@@ -69,10 +69,20 @@ public class ConsoleTextEditor extends JScrollPane {
     private static final String PREFERENCE_FONT_SIZE = "fontSize";
     private static final int DEFAULT_FONT_SIZE = 12;
 
+    /**
+     * Returns the preferred monospaced font family for the editor.
+     *
+     * @return the default font family name
+     */
     public String getDefaultFamily() {
         return defaultFamily;
     }
 
+    /**
+     * Sets the preferred monospaced font family for the editor.
+     *
+     * @param defaultFamily the font family name to use
+     */
     public void setDefaultFamily(String defaultFamily) {
         this.defaultFamily = defaultFamily;
     }
@@ -152,6 +162,9 @@ public class ConsoleTextEditor extends JScrollPane {
     private int fontSize;
 
     /**
+     * Returns the undo manager backing this editor.
+     *
+     * @return the editor undo manager
      * @since 6.0.0
      */
     public TextUndoManager getUndoManager() {
@@ -184,7 +197,8 @@ public class ConsoleTextEditor extends JScrollPane {
     }
 
     /**
-     * Creates a new instance of ConsoleTextEditor
+     * Creates a styled text editor with line numbers, undo/redo support,
+     * printing support, and syntax highlighting.
      */
     public ConsoleTextEditor() {
         fontSize = PREFERENCES.getInt(PREFERENCE_FONT_SIZE, DEFAULT_FONT_SIZE);
@@ -278,6 +292,11 @@ public class ConsoleTextEditor extends JScrollPane {
         }
     }
 
+    /**
+     * Shows or hides the line-number gutter.
+     *
+     * @param showLineNumbers {@code true} to show line numbers
+     */
     public void setShowLineNumbers(boolean showLineNumbers) {
         if (showLineNumbers) {
             JPanel view = new JPanel(new BorderLayout());
@@ -289,19 +308,37 @@ public class ConsoleTextEditor extends JScrollPane {
         }
     }
 
+    /**
+     * Updates whether the text editor accepts user edits.
+     *
+     * @param editable {@code true} if the editor should be editable
+     */
     public void setEditable(boolean editable) {
         textEditor.setEditable(editable);
     }
 
+    /**
+     * Reports whether plain-text clipboard content is currently available.
+     *
+     * @return {@code true} if the clipboard contains a string
+     */
     public boolean clipBoardAvailable() {
         Transferable t = StructuredSyntaxResources.SYSTEM_CLIPBOARD.getContents(this);
         return t.isDataFlavorSupported(DataFlavor.stringFlavor);
     }
 
+    /**
+     * Returns the wrapped text editor component.
+     *
+     * @return the embedded text editor
+     */
     public TextEditor getTextEditor() {
         return textEditor;
     }
 
+    /**
+     * Installs actions exposed by this editor on its action map.
+     */
     protected void initActions() {
         ActionMap map = getActionMap();
         map.put(StructuredSyntaxResources.PRINT, new PrintAction());
@@ -394,18 +431,38 @@ public class ConsoleTextEditor extends JScrollPane {
         }
     }
 
+    /**
+     * Returns the action that undoes the most recent edit.
+     *
+     * @return the undo action
+     */
     public Action getUndoAction() {
         return undoAction;
     }
 
+    /**
+     * Returns the action that redoes the most recently undone edit.
+     *
+     * @return the redo action
+     */
     public Action getRedoAction() {
         return redoAction;
     }
 
+    /**
+     * Returns the action that prints the editor content.
+     *
+     * @return the print action
+     */
     public Action getPrintAction() {
         return printAction;
     }
 
+    /**
+     * Replaces the current syntax highlighter document filter.
+     *
+     * @param clazz the filter type to instantiate for the current document
+     */
     public void enableHighLighter(Class<? extends DocumentFilter> clazz) {
         DefaultStyledDocument doc = (DefaultStyledDocument) textEditor.getDocument();
 
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/HistoryRecord.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/HistoryRecord.groovy
index 6eddf0d060..0ced82b8f5 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/HistoryRecord.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/HistoryRecord.groovy
@@ -20,15 +20,30 @@ package groovy.console.ui
 
 import groovy.transform.CompileStatic
 
+/**
+ * Captures the editor state and execution outcome for a console history entry.
+ */
 @CompileStatic
 class HistoryRecord {
+    /** Full editor contents captured for this history entry. */
     String allText
+    /** Start offset of the selected text. */
     int selectionStart
+    /** End offset of the selected text. */
     int selectionEnd
+    /** Generated script name used during execution. */
     String scriptName
+    /** Execution result, when evaluation completed successfully. */
     Object result
+    /** Execution failure, when evaluation did not complete successfully. */
     Throwable exception
 
+    /**
+     * Returns the text that should be executed for this history entry.
+     *
+     * @param useSelection whether to execute only the current selection
+     * @return the selected text with leading imports, or the full script text
+     */
     String getTextToRun(boolean useSelection) {
         if (useSelection && selectionStart != selectionEnd) {
             // Retrieve all the imports included in the script before the current selection
@@ -41,6 +56,11 @@ class HistoryRecord {
         return allText
     }
 
+    /**
+     * Returns the execution result or captured exception.
+     *
+     * @return the successful result, or the exception when execution failed
+     */
     Object getValue() {
         return exception ? exception : result
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Icons.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Icons.groovy
index 4078efb811..59b838b1dd 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Icons.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/Icons.groovy
@@ -46,9 +46,13 @@ import java.util.function.Function
  * @since 6.0.0
  */
 class Icons {
+    /** Small toolbar icon size in pixels. */
     static final int SIZE_SMALL = 16
+    /** Default toolbar icon size in pixels. */
     static final int SIZE_NORMAL = 18
+    /** Large toolbar icon size in pixels. */
     static final int SIZE_LARGE = 28
+    /** Fixed menu icon size in pixels. */
     static final int MENU_SIZE = 18
 
     private static final String PATH = 'groovy/console/ui/icons/'
@@ -59,47 +63,74 @@ class Icons {
 
     // ---- fixed-size icons (in-window menus, popups, AstBrowser/ObjectBrowser toolbars) ----
 
+    /** Returns a neutral app-themed icon at the fixed menu size. */
     static DynamicSVGIcon load(String name) {
         menuIcon(name, { Color c -> UIManager.getColor('Label.foreground') ?: c })
     }
 
+    /** Returns a green app-themed icon at the fixed menu size. */
     static DynamicSVGIcon green(String name)  { menuIcon(name, greenMapper({ ThemeManager.isDark() })) }
+    /** Returns a red app-themed icon at the fixed menu size. */
     static DynamicSVGIcon red(String name)    { menuIcon(name, redMapper({ ThemeManager.isDark() })) }
+    /** Returns a blue app-themed icon at the fixed menu size. */
     static DynamicSVGIcon blue(String name)   { menuIcon(name, blueMapper({ ThemeManager.isDark() })) }
+    /** Returns an amber app-themed icon at the fixed menu size. */
     static DynamicSVGIcon amber(String name)  { menuIcon(name, amberMapper({ ThemeManager.isDark() })) }
+    /** Returns a violet app-themed icon at the fixed menu size. */
     static DynamicSVGIcon violet(String name) { menuIcon(name, violetMapper({ ThemeManager.isDark() })) }
+    /** Returns a teal app-themed icon at the fixed menu size. */
     static DynamicSVGIcon teal(String name)   { menuIcon(name, tealMapper({ ThemeManager.isDark() })) }
+    /** Returns a Java-brand blue app-themed icon at the fixed menu size. */
     static DynamicSVGIcon javaBlue(String name) { menuIcon(name, javaBlueMapper({ ThemeManager.isDark() })) }
+    /** Returns a muted blue app-themed icon at the fixed menu size. */
     static DynamicSVGIcon subtleBlue(String name) { menuIcon(name, subtleBlueMapper({ ThemeManager.isDark() })) }
 
     // ---- main menu-bar icons (tint follows the menu-bar background, which is OS-drawn on macOS) ----
 
+    /** Returns a neutral menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menu(String name) {
         menuIcon(name, { Color c -> ThemeManager.menuIconForeground ?: c })
     }
 
+    /** Returns a green menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menuGreen(String name)  { menuIcon(name, greenMapper({ ThemeManager.isMenuDark() })) }
+    /** Returns a red menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menuRed(String name)    { menuIcon(name, redMapper({ ThemeManager.isMenuDark() })) }
+    /** Returns a blue menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menuBlue(String name)   { menuIcon(name, blueMapper({ ThemeManager.isMenuDark() })) }
+    /** Returns an amber menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menuAmber(String name)  { menuIcon(name, amberMapper({ ThemeManager.isMenuDark() })) }
+    /** Returns a violet menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menuViolet(String name) { menuIcon(name, violetMapper({ ThemeManager.isMenuDark() })) }
+    /** Returns a teal menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menuTeal(String name)   { menuIcon(name, tealMapper({ ThemeManager.isMenuDark() })) }
+    /** Returns a Java-brand blue menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menuJavaBlue(String name) { menuIcon(name, javaBlueMapper({ ThemeManager.isMenuDark() })) }
+    /** Returns a muted blue menu-bar icon tinted for the current menu background. */
     static DynamicSVGIcon menuSubtleBlue(String name) { menuIcon(name, subtleBlueMapper({ ThemeManager.isMenuDark() })) }
 
     // ---- toolbar / resizable ----
 
+    /** Returns a neutral resizable toolbar icon. */
     static DynamicSVGIcon toolbar(String name) {
         toolbarIcon(name, { Color c -> UIManager.getColor('Label.foreground') ?: c })
     }
 
+    /** Returns a green resizable toolbar icon. */
     static DynamicSVGIcon toolbarGreen(String name)  { toolbarIcon(name, greenMapper({ ThemeManager.isDark() })) }
+    /** Returns a red resizable toolbar icon. */
     static DynamicSVGIcon toolbarRed(String name)    { toolbarIcon(name, redMapper({ ThemeManager.isDark() })) }
+    /** Returns a blue resizable toolbar icon. */
     static DynamicSVGIcon toolbarBlue(String name)   { toolbarIcon(name, blueMapper({ ThemeManager.isDark() })) }
+    /** Returns an amber resizable toolbar icon. */
     static DynamicSVGIcon toolbarAmber(String name)  { toolbarIcon(name, amberMapper({ ThemeManager.isDark() })) }
+    /** Returns a violet resizable toolbar icon. */
     static DynamicSVGIcon toolbarViolet(String name) { toolbarIcon(name, violetMapper({ ThemeManager.isDark() })) }
+    /** Returns a teal resizable toolbar icon. */
     static DynamicSVGIcon toolbarTeal(String name)   { toolbarIcon(name, tealMapper({ ThemeManager.isDark() })) }
+    /** Returns a Java-brand blue resizable toolbar icon. */
     static DynamicSVGIcon toolbarJavaBlue(String name) { toolbarIcon(name, javaBlueMapper({ ThemeManager.isDark() })) }
+    /** Returns a muted blue resizable toolbar icon. */
     static DynamicSVGIcon toolbarSubtleBlue(String name) { toolbarIcon(name, subtleBlueMapper({ ThemeManager.isDark() })) }
 
     // Material "700" for light theme / "400" for dark — muted enough not to
@@ -141,6 +172,7 @@ class Icons {
         toolbarIcons.each { it.setSize(size) }
     }
 
+    /** Returns the current toolbar icon size in pixels. */
     static int getCurrentSize() { currentSize }
 
     /** Re-run the colour filter so every icon adopts the new LaF foreground. */
@@ -159,17 +191,26 @@ class Icons {
         private Icon disabledDelegate
         private int size
 
+        /**
+         * Creates a dynamic icon wrapper for the given SVG resource.
+         *
+         * @param path the classpath-relative SVG resource path
+         * @param size the initial square icon size in pixels
+         * @param colorMapper the color filter applied to the loaded icon
+         */
         DynamicSVGIcon(String path, int size, Closure<Color> colorMapper) {
             this.path = path
             this.colorMapper = colorMapper
             setSize(size)
         }
 
+        /** Rebuilds this icon at a new square size. */
         void setSize(int newSize) {
             this.size = newSize
             rebuildDelegates()
         }
 
+        /** Rebuilds this icon so it adopts current theme colours. */
         void refreshColors() {
             // rebuild the FlatSVGIcon entirely — setColorFilter alone leaves the
             // internal raster cache in a state where some contexts (notably the
@@ -186,8 +227,11 @@ class Icons {
             this.disabledDelegate = delegate.getDisabledIcon()
         }
 
+        /** Returns the current icon width in pixels. */
         @Override int getIconWidth() { size }
+        /** Returns the current icon height in pixels. */
         @Override int getIconHeight() { size }
+        /** Paints the enabled or disabled delegate icon for the target component. */
         @Override void paintIcon(Component c, Graphics g, int x, int y) {
             if (c != null && !c.isEnabled()) {
                 disabledDelegate.paintIcon(c, g, x, y)
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ObjectBrowser.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ObjectBrowser.groovy
index dcc0ae0f15..59c710781d 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ObjectBrowser.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ObjectBrowser.groovy
@@ -53,17 +53,42 @@ import static org.apache.groovy.parser.antlr4.GroovyLexer.VOCABULARY
  */
 class ObjectBrowser {
 
+    /** Inspector backing the currently displayed object. */
     def inspector
+    /** Breadcrumb text describing the current inspection path. */
     String path
+    /** Number of path cards created so far. */
     int pathCount = 0
+    /** Tracks the currently selected inspection card. */
     def tracker
-    def swing, frame, fieldTable, methodTable, arrayTable, collectionTable, mapTable, cards, pathMenu, mb
+    /** Swing builder used to create browser UI components. */
+    def swing
+    /** Top-level browser window. */
+    def frame
+    /** Table showing property and field data. */
+    def fieldTable
+    /** Table showing methods and meta-methods. */
+    def methodTable
+    /** Table showing array contents. */
+    def arrayTable
+    /** Table showing collection contents. */
+    def collectionTable
+    /** Table showing map entries. */
+    def mapTable
+    /** Card container holding each inspected object view. */
+    def cards
+    /** Menu listing visited inspection paths. */
+    def pathMenu
+    /** Menu bar attached to the browser window. */
+    def mb
     private static final Comparator<Object> comparator = new Inspector.MemberComparatorWithValue()
 
+    /** Launches the browser against a sample string. */
     static void main(args) {
         inspect('some String')
     }
 
+    /** Opens an object browser for the supplied object. */
     static void inspect(objectUnderInspection, String path = '') {
         def browser = new ObjectBrowser(path: path ?: '')
         browser.inspector = new Inspector(objectUnderInspection)
@@ -73,6 +98,7 @@ class ObjectBrowser {
         browser.run()
     }
 
+    /** Adds another inspected object as a new card in the current window. */
     void inspectAlso(objectUnderInspection, String path = '') {
         int idx = pathCount++
         def pathId = 'path' + idx
@@ -84,6 +110,7 @@ class ObjectBrowser {
         mb.revalidate()
     }
 
+    /** Builds and shows the object browser window. */
     void run() {
         swing = new SwingBuilder()
         tracker = new CardTracker()
@@ -302,6 +329,7 @@ class ObjectBrowser {
         }
     }
 
+    /** Creates a mouse listener that can browse or copy the selected table row. */
     def mouseListener(int valueCol, Closure pathClosure) {
         def outer = this
         new MouseAdapter() {
@@ -352,6 +380,7 @@ class ObjectBrowser {
         }
     }
 
+    /** Opens the selected table value in this window or a new window. */
     void launch(table, valueCol, boolean newWindow, pathClosure) {
         def selectedRow = table.selectedRow
         if (selectedRow != -1) {
@@ -365,6 +394,7 @@ class ObjectBrowser {
         }
     }
 
+    /** Adds column sorting support to the supplied table. */
     void addSorter(table) {
         if (table != null) {
             def sorter = new TableSorter(table.model)
@@ -373,16 +403,19 @@ class ObjectBrowser {
         }
     }
 
+    /** Switches the visible inspection card to the supplied index. */
     void showAction(int idx, EventObject evt) {
         tracker.current = idx
         show()
     }
 
+    /** Shows the card for the current tracker position. */
     void show() {
         cards.layout.show(cards, 'path' + tracker.current)
         cards.revalidate()
     }
 
+    /** Displays usage help for the object browser. */
     void usageAction(EventObject evt) {
         def pane = swing.optionPane()
         // work around GROOVY-1048
@@ -396,10 +429,12 @@ class ObjectBrowser {
         dialog.show()
     }
 
+    /** Delegates popup-menu browsing to {@link #launch}. */
     void launchAction(table, valueCol, boolean newWindow, pathClosure, EventObject evt) {
         launch(table, valueCol, newWindow, pathClosure)
     }
 
+    /** Copies the tooltip text for the clicked table cell to the clipboard. */
     void copyAction(table, MouseEvent me, EventObject evt) {
         def toolTipText = table.getToolTipText(me)
         if (toolTipText) {
@@ -407,6 +442,7 @@ class ObjectBrowser {
         }
     }
 
+    /** Displays the about dialog for the object browser. */
     void aboutAction(EventObject evt) {
         def pane = swing.optionPane()
         // work around GROOVY-1048
@@ -417,6 +453,8 @@ class ObjectBrowser {
     }
 }
 
+/** Tracks the currently selected card index for the browser. */
 @Bindable class CardTracker {
+    /** Zero-based index of the visible card. */
     int current = 0
 }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/OutputTransforms.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/OutputTransforms.groovy
index 022b4d754c..025ec54404 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/OutputTransforms.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/OutputTransforms.groovy
@@ -35,11 +35,20 @@ import java.awt.Transparency
 import java.awt.Window
 import java.awt.image.BufferedImage
 
+/**
+ * Provides the transformation pipeline used to render console results.
+ */
 @CompileStatic
 class OutputTransforms {
 
+    /** Lazily loaded output transforms composed from user and built-in transforms. */
     @Lazy static List<Closure> localTransforms = loadOutputTransforms()
 
+    /**
+     * Loads user-defined and built-in output transforms.
+     *
+     * @return transforms applied to console results
+     */
     static List<Closure> loadOutputTransforms() {
         def transforms = []
 
@@ -97,6 +106,13 @@ class OutputTransforms {
         return (List<Closure>) transforms
     }
 
+    /**
+     * Applies the configured transforms until one returns a non-null value.
+     *
+     * @param base original result value
+     * @param transforms transforms to apply
+     * @return the transformed value, or the original value when no transform matches
+     */
     static transformResult(base, List<Closure> transforms = localTransforms) {
         for (Closure c : transforms) {
             def result = c(base as Object)
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 d6eab946eb..e0e406ab77 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
@@ -116,9 +116,13 @@ import java.util.concurrent.atomic.AtomicBoolean
  */
 class ScriptToTreeNodeAdapter {
 
+    /** Maps AST node class names to display templates. */
     static Properties classNameToStringForm
+    /** Display flags that control which script structures are included. */
     boolean showScriptFreeForm, showScriptClass, showClosureClasses
+    /** Class loader used for script compilation. */
     final GroovyClassLoader classLoader
+    /** Factory used to create tree node instances. */
     final AstBrowserNodeMaker nodeMaker
     private final CompilerConfiguration config
 
@@ -148,6 +152,16 @@ class ScriptToTreeNodeAdapter {
         }
     }
 
+    /**
+     * Creates an adapter for the supplied compilation settings.
+     *
+     * @param classLoader class loader used for compilation
+     * @param showScriptFreeForm whether to include free-form script statements
+     * @param showScriptClass whether to include the generated script class
+     * @param showClosureClasses whether to include generated closure classes
+     * @param nodeMaker node factory used for tree creation
+     * @param config optional compiler configuration
+     */
     ScriptToTreeNodeAdapter(classLoader, showScriptFreeForm, showScriptClass, showClosureClasses, nodeMaker, config = null) {
         this.classLoader = classLoader ?: new GroovyClassLoader(getClass().classLoader)
         this.showScriptFreeForm = showScriptFreeForm
@@ -164,6 +178,7 @@ class ScriptToTreeNodeAdapter {
      *      a Groovy script in String form
      * @param compilePhase
      *      the int based CompilePhase to compile it to.
+     * @return the generated tree root
      */
     def compile(String script, int compilePhase) {
         def scriptName = 'script' + System.currentTimeMillis() + '.groovy'
@@ -194,10 +209,22 @@ class ScriptToTreeNodeAdapter {
         return operation.root
     }
 
+    /**
+     * Creates a tree node for the supplied AST node.
+     *
+     * @param node AST node to adapt
+     * @return the created tree node
+     */
     def make(node) {
         makeWithTable(node, getPropertyTable(node))
     }
 
+    /**
+     * Creates a tree node for a method node with its descriptor metadata.
+     *
+     * @param node method node to adapt
+     * @return the created tree node
+     */
     def make(MethodNode node) {
         def table = getPropertyTable(node)
         extendMethodNodePropertyTable(table, node)
@@ -210,6 +237,9 @@ class ScriptToTreeNodeAdapter {
 
     /**
      * Extends the method node property table by adding custom properties.
+     *
+     * @param table property table to extend
+     * @param node method node supplying the descriptor
      */
     void extendMethodNodePropertyTable(List<List<?>> table, MethodNode node) {
         def descriptor = BytecodeHelper.getMethodDescriptor(node)
@@ -244,6 +274,12 @@ class ScriptToTreeNodeAdapter {
         }.sort { list -> list[0] } // sort by name
     }
 
+    /**
+     * Returns a string representation without crossing visibility boundaries.
+     *
+     * @param o value to convert
+     * @return string form of the supplied value
+     */
     // GROOVY-8339: to avoid illegal access to a non-visible implementation class - can be removed if a more general solution is found
     @CompileStatic
     String toString(Object o) {
@@ -273,20 +309,42 @@ class ScriptToTreeNodeAdapter {
  */
 class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNodeOperation {
 
+    /** Root node for the generated tree. */
     final root
+    /** Tracks whether free-form source nodes were already collected. */
     final sourceCollected = new AtomicBoolean(false)
+    /** Adapter used to create child nodes. */
     final ScriptToTreeNodeAdapter adapter
 
+    /** Whether free-form script statements should be included. */
     final showScriptFreeForm
+    /** Whether the generated script class should be included. */
     final showScriptClass
+    /** Whether generated closure classes should be included. */
     final showClosureClasses
 
+    /** Factory used to create tree nodes. */
     final nodeMaker
 
+    /**
+     * Creates an operation with closure class nodes hidden.
+     *
+     * @param adapter adapter used to create tree nodes
+     * @param showScriptFreeForm whether free-form script statements should be shown
+     * @param showScriptClass whether the generated script class should be shown
+     */
     TreeNodeBuildingNodeOperation(ScriptToTreeNodeAdapter adapter, showScriptFreeForm, showScriptClass) {
         this(adapter, showScriptFreeForm, showScriptClass, false)
     }
 
+    /**
+     * Creates an operation for building the AST tree.
+     *
+     * @param adapter adapter used to create tree nodes
+     * @param showScriptFreeForm whether free-form script statements should be shown
+     * @param showScriptClass whether the generated script class should be shown
+     * @param showClosureClasses whether generated closure classes should be shown
+     */
     TreeNodeBuildingNodeOperation(ScriptToTreeNodeAdapter adapter, showScriptFreeForm, showScriptClass, showClosureClasses) {
         if (!adapter) throw new IllegalArgumentException('Null: adapter')
         this.adapter = adapter
@@ -297,6 +355,9 @@ class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNode
         root = nodeMaker.makeNode('root')
     }
 
+    /**
+     * Adds the current class node and optional script statements to the tree.
+     */
     @Override
     void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
         // module node
@@ -326,6 +387,11 @@ class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNode
         }
     }
 
+    /**
+     * Adds generated closure and lambda classes for the supplied outer class.
+     *
+     * @param classNode outer class being inspected
+     */
     protected void makeClosureClassTreeNodes(ClassNode classNode) {
         def compileUnit = classNode.compileUnit
         if (!compileUnit.generatedInnerClasses) return
@@ -463,6 +529,7 @@ class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNode
 @PackageScope
 class TreeNodeBuildingVisitor extends CodeVisitorSupport {
 
+    /** Node currently being populated by the visitor. */
     def currentNode
     private final adapter
 
@@ -653,6 +720,8 @@ class TreeNodeBuildingVisitor extends CodeVisitorSupport {
 
     /**
      * Makes walking parameters look like others in the visitor.
+     *
+     * @param node parameter node to add
      */
     void visitParameter(Parameter node) {
         addNode(node, Parameter, { })
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ThemeManager.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ThemeManager.groovy
index 44fec58c67..a62c483b0d 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ThemeManager.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ThemeManager.groovy
@@ -37,10 +37,17 @@ import java.util.prefs.Preferences
 class ThemeManager {
 
     /**
+     * Available theme selection modes for the console.
+     *
      * @since 6.0.0
      */
     enum ThemeMode {
-        LIGHT, DARK, SYSTEM
+        /** Always use the light theme. */
+        LIGHT,
+        /** Always use the dark theme. */
+        DARK,
+        /** Follow the operating system theme. */
+        SYSTEM
     }
 
     private static final Preferences prefs = Preferences.userNodeForPackage(Console)
@@ -53,18 +60,22 @@ class ThemeManager {
     // frames (AstBrowser, ObjectBrowser) can retint their own text panes/icons
     private static final List<Runnable> themeChangeListeners = new CopyOnWriteArrayList<>()
 
+    /** Registers a listener notified after the console theme changes. */
     static void addThemeChangeListener(Runnable listener) {
         themeChangeListeners << listener
     }
 
+    /** Removes a previously registered theme-change listener. */
     static void removeThemeChangeListener(Runnable listener) {
         themeChangeListeners.remove(listener)
     }
 
+    /** Notifies all registered listeners that the theme has changed. */
     static void notifyThemeChanged() {
         themeChangeListeners.each { it.run() }
     }
 
+    /** Returns the configured theme mode, defaulting to {@link ThemeMode#SYSTEM}. */
     static ThemeMode getCurrentMode() {
         try {
             ThemeMode.valueOf(prefs.get('theme', 'SYSTEM').toUpperCase())
@@ -73,11 +84,13 @@ class ThemeManager {
         }
     }
 
+    /** Returns whether the active console theme currently resolves to dark. */
     static boolean isDark() {
         def mode = currentMode
         mode == ThemeMode.DARK || (mode == ThemeMode.SYSTEM && isSystemDarkMode())
     }
 
+    /** Applies and persists the supplied theme mode. */
     static void applyTheme(ThemeMode mode) {
         prefs.put('theme', mode.name())
         refreshSystemDarkMode()
@@ -95,6 +108,7 @@ class ThemeManager {
         prior == null || prior != cachedSystemDark
     }
 
+    /** Returns whether the operating system appearance currently resolves to dark. */
     static boolean isSystemDarkMode() {
         if (cachedSystemDark == null) {
             cachedSystemDark = probeSystemDarkMode()
@@ -126,6 +140,7 @@ class ThemeManager {
         }
     }
 
+    /** Cycles through light, dark, and system theme modes. */
     static ThemeMode cycleMode() {
         switch (currentMode) {
             case ThemeMode.LIGHT: return ThemeMode.DARK
@@ -134,6 +149,7 @@ class ThemeManager {
         }
     }
 
+    /** Returns a user-facing label for the current theme mode. */
     static String getThemeLabel() {
         switch (currentMode) {
             case ThemeMode.LIGHT: return 'Light'
@@ -142,14 +158,17 @@ class ThemeManager {
         }
     }
 
+    /** Returns the active theme's editor background colour. */
     static Color getInputBackground() {
         activeTheme.inputBackground
     }
 
+    /** Returns the active theme's output background colour. */
     static Color getOutputBackground() {
         activeTheme.outputBackground
     }
 
+    /** Builds the Swing style map for the active theme and font family. */
     static Map getStyles(String fontFamily) {
         buildSwingStyles(activeTheme, fontFamily)
     }
@@ -170,13 +189,17 @@ class ThemeManager {
 
     private static final Map<String, Object> themeCache = [:]
 
+    /** Returns the configured custom light-theme file path, if any. */
     static String getCustomLightPath() { prefs.get('themeCustomLightPath', null) }
+    /** Returns the configured custom dark-theme file path, if any. */
     static String getCustomDarkPath()  { prefs.get('themeCustomDarkPath',  null) }
 
+    /** Persists the custom light-theme file path or clears it when blank. */
     static void setCustomLightPath(String path) {
         path ? prefs.put('themeCustomLightPath', path) : prefs.remove('themeCustomLightPath')
     }
 
+    /** Persists the custom dark-theme file path or clears it when blank. */
     static void setCustomDarkPath(String path) {
         path ? prefs.put('themeCustomDarkPath', path) : prefs.remove('themeCustomDarkPath')
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/AutoIndentAction.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/AutoIndentAction.groovy
index 055b011694..185cd3cd91 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/AutoIndentAction.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/AutoIndentAction.groovy
@@ -26,12 +26,23 @@ import javax.swing.text.AttributeSet
 import javax.swing.text.SimpleAttributeSet
 import java.awt.event.ActionEvent
 
+/**
+ * Inserts a newline that preserves the indentation of the current line.
+ */
 @CompileStatic
 class AutoIndentAction extends AbstractAction {
     private static final long serialVersionUID = -2680684287296849370L
 
+    /**
+     * Attributes used for inserted text.
+     */
     AttributeSet simpleAttributeSet = new SimpleAttributeSet()
 
+    /**
+     * Inserts a newline and copies the leading whitespace of the current line.
+     *
+     * @param evt the action event providing the target text pane
+     */
     void actionPerformed(ActionEvent evt) {
         JTextPane inputArea = (JTextPane) evt.source
         def rootElement = inputArea.document.defaultRootElement
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/FindReplaceUtility.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/FindReplaceUtility.java
index b3469098f4..ee7b7b2a03 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/FindReplaceUtility.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/FindReplaceUtility.java
@@ -49,16 +49,34 @@ import java.awt.event.TextEvent;
 import java.awt.event.TextListener;
 import java.util.EventListener;
 
+/**
+ * Shared find/replace dialog support for text components used by the console.
+ */
 public final class FindReplaceUtility {
 
+    /**
+     * Action command for find operations.
+     */
     public static final String FIND_ACTION_COMMAND = "Find";
 
+    /**
+     * Action command for single replace operations.
+     */
     public static final String REPLACE_ACTION_COMMAND = "Replace";
 
+    /**
+     * Action command for replace-all operations.
+     */
     public static final String REPLACE_ALL_ACTION_COMMAND = "Replace All";
 
+    /**
+     * Action command for closing the dialog.
+     */
     public static final String CLOSE_ACTION_COMMAND = "Close";
 
+    /**
+     * Shared action that repeats a find against the active text component.
+     */
     public static final Action FIND_ACTION = new FindAction();
 
     private static final JDialog FIND_REPLACE_DIALOG = new JDialog();
@@ -198,6 +216,11 @@ public final class FindReplaceUtility {
     private FindReplaceUtility() {
     }
 
+    /**
+     * Registers a listener for dialog text events.
+     *
+     * @param tl the listener to add
+     */
     public static void addTextListener(TextListener tl) {
         EVENT_LISTENER_LIST.add(TextListener.class, tl);
     }
@@ -236,12 +259,19 @@ public final class FindReplaceUtility {
     }
 
     /**
+     * Starts tracking the supplied text component for find/replace actions.
+     *
      * @param textComponent the text component to listen to
      */
     public static void registerTextComponent(JTextComponent textComponent) {
         textComponent.addFocusListener(TEXT_FOCUS_LISTENER);
     }
 
+    /**
+     * Removes a listener for dialog text events.
+     *
+     * @param tl the listener to remove
+     */
     public static void removeTextListener(TextListener tl) {
         EVENT_LISTENER_LIST.remove(TextListener.class, tl);
     }
@@ -353,11 +383,16 @@ public final class FindReplaceUtility {
 
     }
 
+    /**
+     * Shows the find dialog for the active text component.
+     */
     public static void showDialog() {
         showDialog(false);
     }
 
     /**
+     * Shows either the find or replace dialog for the active text component.
+     *
      * @param isReplace show a replace dialog rather than a find dialog if true
      */
     public static void showDialog(boolean isReplace) {
@@ -403,6 +438,8 @@ public final class FindReplaceUtility {
     }
 
     /**
+     * Stops tracking the supplied text component for find/replace actions.
+     *
      * @param textComponent the text component to stop listening to
      */
     public static void unregisterTextComponent(JTextComponent textComponent) {
@@ -557,6 +594,9 @@ public final class FindReplaceUtility {
         }
     }
 
+    /**
+     * Disposes of the shared find/replace dialog.
+     */
     public static void dispose() {
         FIND_REPLACE_DIALOG.dispose();
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/GroovyFilter.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/GroovyFilter.java
index d2ae3a6436..c2a7ed6086 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/GroovyFilter.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/GroovyFilter.java
@@ -32,39 +32,99 @@ import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 
+/**
+ * Regex-based syntax-highlighting filter for Groovy source text.
+ */
 public class GroovyFilter extends StructuredSyntaxDocumentFilter {
 
     // java tab policy action
     private static final Action AUTO_TAB_ACTION = new AutoTabAction();
 
     // Style names
+    /**
+     * Style name used for comments.
+     */
     public static final String COMMENT = "comment";
+    /**
+     * Pattern matching block comments.
+     */
     public static final String SLASH_STAR_COMMENT = "/\\*(?s:.)*?(?:\\*/|\\z)";
+    /**
+     * Pattern matching line comments.
+     */
     public static final String SLASH_SLASH_COMMENT = "//.*";
 
+    /**
+     * Pattern matching double-quoted and triple-double-quoted strings.
+     */
     public static final String QUOTES =
             "(?ms:\"{3}.*?(?:\"{3}|\\z))|(?:\"{1}.*?(?:\"|\\Z))";
 
+    /**
+     * Pattern matching single-quoted and triple-single-quoted strings.
+     */
     public static final String SINGLE_QUOTES =
             "(?ms:'{3}(?!'{1,3}).*?(?:'{3}|\\z))|(?:'{1}.*?(?:'|\\z))";
 
+    /**
+     * Pattern matching slashy and dollar-slashy strings.
+     */
     public static final String SLASHY_QUOTES = "(?:/[^/*].*?(?<!\\\\)/|(?ms:\\$/.*?(?:/\\$|\\z)))";
 
+    /**
+     * Style name used for numeric literals.
+     */
     public static final String DIGIT = "DIGIT";
+    /**
+     * Pattern matching decimal integer literals.
+     */
     public static final String DECIMAL_INTEGER_LITERAL = "(?:0|[1-9](?:[_0-9]*[0-9])?)[lL]?";
+    /**
+     * Pattern matching hexadecimal integer literals.
+     */
     public static final String HEX_INTEGER_LITERAL = "0[xX][0-9a-fA-F](?:[0-9a-fA-F_]*[0-9a-fA-F])?";
+    /**
+     * Pattern matching octal integer literals.
+     */
     public static final String OCTAL_INTEGER_LITERAL = "0[0-7](?:[_0-7]*[0-7])?";
+    /**
+     * Pattern matching binary integer literals.
+     */
     public static final String BINARY_INTEGER_LITERAL = "0[bB][01](?:[_01]*[01])?";
+    /**
+     * Pattern matching decimal floating-point literals.
+     */
     public static final String DECIMAL_FLOATING_POINT_LITERAL = "(?:0|[1-9](?:[_0-9]*[0-9])?)?\\.?[0-9](?:[_0-9]*[0-9])?(?:[eE][+-]?[0-9]+(?:[_0-9]*[0-9])?)?[fFdD]?";
+    /**
+     * Pattern matching hexadecimal floating-point literals.
+     */
     public static final String HEXADECIMAL_FLOATING_POINT_LITERAL = "0[xX](?:[0-9a-fA-F](?:[0-9a-fA-F_]*[0-9a-fA-F])?)?\\.?(?:[0-9a-fA-F_]*[0-9a-fA-F])?(?:[pP][+-]?[0-9]+(?:[_0-9]*[0-9])?)?[fFdD]?";
 
+    /**
+     * Pattern matching annotations.
+     */
     public static final String ANNOTATION = "@[A-Za-z](?:[\\w.]*\\w)?";
 
+    /**
+     * Pattern matching identifiers.
+     */
     public static final String IDENT = "[\\w\\$&&[\\D]][\\w\\$]*";
+    /**
+     * Pattern matching method-style identifiers followed by an opening parenthesis.
+     */
     public static final String OPERATION = "[\\w\\$&&[\\D]][\\w\\$]* *\\(";
+    /**
+     * Pattern matching left parentheses inside operation matches.
+     */
     public static final String LEFT_PARENS = "\\(";
 
+    /**
+     * Style name used for reserved words.
+     */
     public static final String RESERVED_WORD = "reserved";
+    /**
+     * Patterns matching Groovy reserved words.
+     */
     public static final String[] RESERVED_WORDS = {"\\babstract\\b",
             "\\bassert\\b",
             "\\bdefault\\b",
@@ -125,6 +185,8 @@ public class GroovyFilter extends StructuredSyntaxDocumentFilter {
 
     /**
      * Creates a new instance of GroovyFilter
+     *
+     * @param doc the document to highlight
      */
     public GroovyFilter(DefaultStyledDocument doc) {
         super(doc);
@@ -189,6 +251,11 @@ public class GroovyFilter extends StructuredSyntaxDocumentFilter {
         getRootNode().putChild(IDENT, node);
     }
 
+    /**
+     * Installs the auto-indent action on the supplied text component.
+     *
+     * @param tComp the text component to configure
+     */
     public static void installAutoTabAction(JTextComponent tComp) {
         tComp.getActionMap().put("GroovyFilter-autoTab", AUTO_TAB_ACTION);
         KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false);
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/MatchingHighlighter.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/MatchingHighlighter.java
index 5978fe2352..b3be8dd8b9 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/MatchingHighlighter.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/MatchingHighlighter.java
@@ -71,6 +71,12 @@ public class MatchingHighlighter implements CaretListener {
     );
     private volatile List<Tuple3<Integer, Position, Integer>> highlightedTokenInfoList = Collections.emptyList();
 
+    /**
+     * Creates a highlighter bound to the supplied document filter and editor.
+     *
+     * @param smartDocumentFilter the token source used to find matching delimiters
+     * @param textEditor the text pane whose delimiters are highlighted
+     */
     public MatchingHighlighter(SmartDocumentFilter smartDocumentFilter, JTextPane textEditor) {
         this.smartDocumentFilter = smartDocumentFilter;
         this.textEditor = textEditor;
@@ -79,11 +85,17 @@ public class MatchingHighlighter implements CaretListener {
         initStyles();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void caretUpdate(CaretEvent e) {
         highlight();
     }
 
+    /**
+     * Schedules highlighting for the delimiter nearest the caret.
+     */
     public void highlight() {
         // `SwingUtilities.invokeLater` is used to avoid "java.lang.IllegalStateException: Attempt to mutate in notification"
         SwingUtilities.invokeLater(this::doHighlight);
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/SmartDocumentFilter.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/SmartDocumentFilter.java
index c6f54867dd..25dcc7d393 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/SmartDocumentFilter.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/SmartDocumentFilter.java
@@ -133,6 +133,9 @@ import static org.apache.groovy.parser.antlr4.GroovyLexer.YIELD;
  * @since 3.0.0
  */
 public class SmartDocumentFilter extends DocumentFilter {
+    /**
+     * Token types rendered with the reserved-word style.
+     */
     public static final List<Integer> HIGHLIGHTED_TOKEN_TYPE_LIST =
         Arrays.asList(AS, ASYNC, AWAIT, DEF, DEFER, IN, TRAIT, THREADSAFE,
             VAR, BuiltInPrimitiveType, ABSTRACT, ASSERT, BREAK, CASE, CATCH, CLASS, CONST, CONTINUE, DEFAULT, DO,
@@ -145,6 +148,11 @@ public class SmartDocumentFilter extends DocumentFilter {
     private final StyleContext styleContext;
     private final Style defaultStyle;
 
+    /**
+     * Creates a filter that styles the supplied document.
+     *
+     * @param styledDocument the document to tokenize and highlight
+     */
     public SmartDocumentFilter(DefaultStyledDocument styledDocument) {
         this.styledDocument = styledDocument;
 
@@ -155,6 +163,9 @@ public class SmartDocumentFilter extends DocumentFilter {
         initStyles();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void insertString(DocumentFilter.FilterBypass fb, int offset,
                              String text, AttributeSet attrs) throws BadLocationException {
@@ -165,6 +176,9 @@ public class SmartDocumentFilter extends DocumentFilter {
         parseDocument();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void remove(DocumentFilter.FilterBypass fb, int offset, int length)
             throws BadLocationException {
@@ -173,6 +187,9 @@ public class SmartDocumentFilter extends DocumentFilter {
         parseDocument();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void replace(DocumentFilter.FilterBypass fb, int offset,
                         int length, String text, AttributeSet attrs)
@@ -489,17 +506,38 @@ public class SmartDocumentFilter extends DocumentFilter {
     private volatile List<Token> latestTokenList = Collections.emptyList();
     private volatile Tuple2<Integer, Integer> renderRange;
 
+    /**
+     * Indicates whether the cached token list reflects the current document text.
+     *
+     * @return {@code true} if the latest parse completed successfully
+     */
     public boolean isLatest() {
         return latest;
     }
 
+    /**
+     * Returns the tokens produced by the most recent successful parse.
+     *
+     * @return the latest token list
+     */
     public List<Token> getLatestTokenList() {
         return latestTokenList;
     }
 
+    /**
+     * Limits rendering to the supplied character range for the next parse.
+     *
+     * @param renderRange the inclusive start and stop offsets to re-render, or {@code null} for all text
+     */
     public void setRenderRange(Tuple2<Integer, Integer> renderRange) {
         this.renderRange = renderRange;
     }
+
+    /**
+     * Returns the character range scheduled for selective re-rendering.
+     *
+     * @return the current render range, or {@code null} if the whole document will be rendered
+     */
     public Tuple2<Integer, Integer> getRenderRange() {
         return renderRange;
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxDocumentFilter.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxDocumentFilter.java
index 9437c87a45..0a8537bdfc 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxDocumentFilter.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxDocumentFilter.java
@@ -40,8 +40,14 @@ import java.util.TreeSet;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+/**
+ * Document filter that applies regex-driven syntax highlighting to styled text.
+ */
 public class StructuredSyntaxDocumentFilter extends DocumentFilter {
 
+    /**
+     * Spaces inserted in place of tab characters.
+     */
     public static final String TAB_REPLACEMENT = "    ";
 
     private static final MLComparator ML_COMPARATOR = new MLComparator();
@@ -51,7 +57,9 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
      */
     protected LexerNode lexer = new LexerNode(true);
 
-    // The styled document the filter parses
+    /**
+     * The styled document currently being parsed.
+     */
     protected DefaultStyledDocument styledDocument;
 
     // the document buffer and segment
@@ -272,6 +280,9 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
         return string;
     }
 
+    /**
+     * Regex-driven lexer node that applies styles and nested lexers.
+     */
     public final class LexerNode {
 
         private Style defaultStyle;
@@ -286,8 +297,10 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
 
         private CharBuffer lastBuffer;
 
-        /*
-         * Creates a new instance of LexerNode
+        /**
+         * Creates a lexer node.
+         *
+         * @param isParent {@code true} if this node is the root node
          */
         LexerNode(boolean isParent) {
             StyleContext sc = StyleContext.getDefaultStyleContext();
@@ -305,6 +318,11 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
             return regexp.substring(1);
         }
 
+        /**
+         * Returns the fallback style for unmatched text.
+         *
+         * @return the default style
+         */
         public Style getDefaultStyle() {
             return defaultStyle;
         }
@@ -340,10 +358,12 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
         }
 
         /**
-         * @param buffer
-         * @param offset
-         * @param length
-         * @throws BadLocationException
+         * Parses the supplied buffer and applies styles to matching ranges.
+         *
+         * @param buffer the character buffer to parse
+         * @param offset the starting offset
+         * @param length the number of characters to parse
+         * @throws BadLocationException if document positions cannot be resolved
          */
         public void parse(CharBuffer buffer, int offset, int length) throws BadLocationException {
             // get the index of where we can start to look for an exit:
@@ -416,8 +436,10 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
         }
 
         /**
-         * @param regexp
-         * @param node
+         * Registers a child lexer for matches of the supplied expression.
+         *
+         * @param regexp the expression to match
+         * @param node the child lexer to apply within matching text
          */
         public void putChild(String regexp, LexerNode node) {
             node.defaultStyle = styleMap.get(regexp);
@@ -428,16 +450,20 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
         }
 
         /**
-         * @param regexps
-         * @param node
+         * Registers a child lexer for matches of any supplied expression.
+         *
+         * @param regexps the expressions to match
+         * @param node the child lexer to apply within matching text
          */
         public void putChild(String[] regexps, LexerNode node) {
             putChild(buildRegexp(regexps), node);
         }
 
         /**
-         * @param regexp
-         * @param style
+         * Associates a style with matches of the supplied expression.
+         *
+         * @param regexp the expression to match
+         * @param style the style to apply
          */
         public void putStyle(String regexp, Style style) {
             checkRegexp(regexp);
@@ -446,22 +472,28 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
         }
 
         /**
-         * @param regexps
-         * @param style
+         * Associates a style with matches of any supplied expression.
+         *
+         * @param regexps the expressions to match
+         * @param style the style to apply
          */
         public void putStyle(String[] regexps, Style style) {
             putStyle(buildRegexp(regexps), style);
         }
 
         /**
-         * @param regexp
+         * Removes the child lexer registered for the supplied expression.
+         *
+         * @param regexp the expression whose child lexer should be removed
          */
         public void removeChild(String regexp) {
             children.remove(regexp);
         }
 
         /**
-         * @param regexp
+         * Removes the style associated with the supplied expression.
+         *
+         * @param regexp the expression whose style should be removed
          */
         public void removeStyle(String regexp) {
             styleMap.remove(regexp);
@@ -469,27 +501,52 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
         }
 
         /**
-         * @param regexps
+         * Removes the style associated with any of the supplied expressions.
+         *
+         * @param regexps the expressions whose combined style should be removed
          */
         public void removeStyle(String[] regexps) {
             removeStyle(buildRegexp(regexps));
         }
 
+        /**
+         * Sets the fallback style for unmatched text.
+         *
+         * @param style the default style to use
+         */
         public void setDefaultStyle(Style style) {
             defaultStyle = style;
         }
     }
 
+    /**
+     * Tracks a multi-line styled region within the document.
+     */
     protected class MultiLineRun {
 
         private Position start;
         private Position end;
         private int delimiterSize;
 
+        /**
+         * Creates a multi-line run using a two-character delimiter.
+         *
+         * @param start the inclusive start offset
+         * @param end the inclusive end offset
+         * @throws BadLocationException if either offset is invalid
+         */
         public MultiLineRun(int start, int end) throws BadLocationException {
             this(start, end, 2);
         }
 
+        /**
+         * Creates a multi-line run with the supplied delimiter size.
+         *
+         * @param start the inclusive start offset
+         * @param end the inclusive end offset
+         * @param delimiterSize the delimiter width in characters
+         * @throws BadLocationException if either offset is invalid
+         */
         public MultiLineRun(int start, int end, int delimiterSize) throws BadLocationException {
             if (start > end) {
                 String msg = "Start offset is after end: ";
@@ -504,6 +561,11 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
             this.delimiterSize = delimiterSize;
         }
 
+        /**
+         * Returns the delimiter width used by this run.
+         *
+         * @return the delimiter size in characters
+         */
         public int getDelimiterSize() {
             return delimiterSize;
         }
@@ -516,18 +578,38 @@ public class StructuredSyntaxDocumentFilter extends DocumentFilter {
             return getDelimiterSize();
         }
 
+        /**
+         * Returns the inclusive end offset.
+         *
+         * @return the end offset
+         */
         public int end() {
             return end.getOffset();
         }
 
+        /**
+         * Returns the run length.
+         *
+         * @return the number of characters in the run
+         */
         public int length() {
             return end.getOffset() - start.getOffset();
         }
 
+        /**
+         * Returns the inclusive start offset.
+         *
+         * @return the start offset
+         */
         public int start() {
             return start.getOffset();
         }
 
+        /**
+         * Returns a textual description of the run bounds.
+         *
+         * @return the start and end positions
+         */
         @Override
         public String toString() {
             return start.toString() + " " + end.toString();
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxHandler.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxHandler.java
index 2f811acfb9..6b05b1af72 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxHandler.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxHandler.java
@@ -23,44 +23,149 @@ import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 import org.xml.sax.helpers.DefaultHandler;
 
+/**
+ * SAX handler that reads structured syntax definitions into a document filter.
+ */
 public class StructuredSyntaxHandler extends DefaultHandler {
 
     //StyleConstants.
+    /**
+     * XML element name for regular expression entries.
+     */
     public static final String REGEXP = "regexp";
+    /**
+     * XML element name for style entries.
+     */
     public static final String STYLE = "style";
 
+    /**
+     * Alignment value name for centered text.
+     */
     public static final String ALIGN_CENTER = "ALIGN_CENTER";
+    /**
+     * Alignment value name for justified text.
+     */
     public static final String ALIGN_JUSTIFIED = "ALIGN_JUSTIFIED";
+    /**
+     * Alignment value name for left-aligned text.
+     */
     public static final String ALIGN_LEFT = "ALIGN_LEFT";
+    /**
+     * Alignment value name for right-aligned text.
+     */
     public static final String ALIGN_RIGHT = "ALIGN_RIGHT";
 
+    /**
+     * Style attribute name for alignment.
+     */
     public static final String ALIGNMENT = "alignment";
+    /**
+     * Style attribute name for background color.
+     */
     public static final String BACKGROUND = "background";
+    /**
+     * Style attribute name for bidirectional text level.
+     */
     public static final String BIDI_LEVEL = "bidiLevel";
+    /**
+     * Style attribute name for bold text.
+     */
     public static final String BOLD = "bold";
+    /**
+     * Style attribute name for embedded components.
+     */
     public static final String COMPONENT_ATTRIBUTE = "componentAttribute";
+    /**
+     * Style attribute name for component element names.
+     */
     public static final String COMPONENT_ELEMENT_NAME = "componentElementName";
+    /**
+     * Style attribute name for composed text.
+     */
     public static final String COMPOSED_TEXT_ATTRIBUTE = "composedTextAttribute";
+    /**
+     * Style attribute name for first-line indentation.
+     */
     public static final String FIRST_LINE_INDENT = "firstLineIndent";
+    /**
+     * Style attribute name for font family.
+     */
     public static final String FONT_FAMILY = "fontFamily";
+    /**
+     * Style attribute name for font size.
+     */
     public static final String FONT_SIZE = "fontSize";
+    /**
+     * Style attribute name for foreground color.
+     */
     public static final String FOREGROUND = "foreground";
+    /**
+     * Style attribute name for embedded icons.
+     */
     public static final String ICON_ATTRIBUTE = "iconAttribute";
+    /**
+     * Style attribute name for icon element names.
+     */
     public static final String ICON_ELEMENT_NAME = "iconElementName";
+    /**
+     * Style attribute name for italic text.
+     */
     public static final String ITALIC = "italic";
+    /**
+     * Style attribute name for left indentation.
+     */
     public static final String LEFT_INDENT = "leftIndent";
+    /**
+     * Style attribute name for line spacing.
+     */
     public static final String LINE_SPACING = "lineSpacing";
+    /**
+     * Style attribute name for model attributes.
+     */
     public static final String MODEL_ATTRIBUTE = "modelAttribute";
+    /**
+     * Style attribute name for named attributes.
+     */
     public static final String NAME_ATTRIBUTE = "nameAttribute";
+    /**
+     * Style attribute name for orientation.
+     */
     public static final String ORIENTATION = "orientation";
+    /**
+     * Style attribute name for resolve attributes.
+     */
     public static final String RESOLVE_ATTRIBUTE = "resolveAttribute";
+    /**
+     * Style attribute name for right indentation.
+     */
     public static final String RIGHT_INDENT = "rightIndent";
+    /**
+     * Style attribute name for space above paragraphs.
+     */
     public static final String SPACE_ABOVE = "spaceAbove";
+    /**
+     * Style attribute name for space below paragraphs.
+     */
     public static final String SPACE_BELOW = "spaceBelow";
+    /**
+     * Style attribute name for strike-through text.
+     */
     public static final String STRIKE_THROUGH = "strikeThrough";
+    /**
+     * Style attribute name for subscript text.
+     */
     public static final String SUBSCRIPT = "subscript";
+    /**
+     * Style attribute name for superscript text.
+     */
     public static final String SUPERSCRIPT = "superscript";
+    /**
+     * Style attribute name for tab sets.
+     */
     public static final String TAB_SET = "tabSet";
+    /**
+     * Style attribute name for underlined text.
+     */
     public static final String UNDERLINE = "underline";
 
     private StructuredSyntaxDocumentFilter.LexerNode currentNode;
@@ -68,40 +173,58 @@ public class StructuredSyntaxHandler extends DefaultHandler {
     private final StructuredSyntaxDocumentFilter filter;
 
     /**
-     * Creates a new instance of MasterFrameHandler
+     * Creates a handler for the supplied syntax filter.
      *
-     * @param filter
+     * @param filter the filter receiving parsed syntax definitions
      */
     public StructuredSyntaxHandler(StructuredSyntaxDocumentFilter filter) {
         this.filter = filter;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void characters(char[] ch, int start, int length) {
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void endDocument() throws SAXException {
         super.endDocument();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void endElement(String uri,
                            String localName,
                            String qName) throws SAXException {
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void error(SAXParseException e) throws SAXException {
         throw new SAXException("Line: " + e.getLineNumber() + " message: " + e.getMessage());
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void startDocument() throws SAXException {
         super.startDocument();
         currentNode = filter.getRootNode();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void startElement(String uri,
                              String localName,
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxResources.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxResources.java
index f2061d8508..a5ca160473 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxResources.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/StructuredSyntaxResources.java
@@ -32,6 +32,9 @@ public final class StructuredSyntaxResources {
     // ClipBoard
     // ==================================================
 
+    /**
+     * Shared clipboard used by the console text components.
+     */
     public static final Clipboard SYSTEM_CLIPBOARD = getSystemOrAppLevelClipboard();
 
     private static Clipboard getSystemOrAppLevelClipboard() {
@@ -62,21 +65,51 @@ public final class StructuredSyntaxResources {
     // STANDARD FONTS
     // =====================================================
 
+    /**
+     * Large UI font used by legacy console components.
+     */
     public static final Font LARGE_FONT = Font.decode("Arial-24");
+    /**
+     * Medium UI font used by legacy console components.
+     */
     public static final Font MEDIUM_FONT = Font.decode("Arial-18");
+    /**
+     * Small UI font used by legacy console components.
+     */
     public static final Font SMALL_FONT = Font.decode("Arial-12");
 
+    /**
+     * Default monospaced font for editors.
+     */
     public static final Font EDITOR_FONT = Font.decode("Monospaced-12");
 
     // =====================================================
     // UNDO/REDO NAMES
     // =====================================================
 
+    /**
+     * Presentation name for undo actions.
+     */
     public static final String UNDO = "Undo";
+    /**
+     * Presentation name for redo actions.
+     */
     public static final String REDO = "Redo";
+    /**
+     * Presentation name for print actions.
+     */
     public static final String PRINT = "Print";
+    /**
+     * Presentation name for find actions.
+     */
     public static final String FIND = "Find";
+    /**
+     * Presentation name for find-next actions.
+     */
     public static final String FIND_NEXT = "Find Next";
+    /**
+     * Presentation name for replace actions.
+     */
     public static final String REPLACE = "Replace";
 
     // singleton
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextEditor.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextEditor.java
index 332c1b5415..d9aa201bcb 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextEditor.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextEditor.java
@@ -68,11 +68,29 @@ import java.util.regex.Pattern;
 public class TextEditor extends JTextPane implements Pageable, Printable {
     @Serial private static final long serialVersionUID = 8478062945229999402L;
 
+    /**
+     * Action name for opening the find dialog.
+     */
     public static final String FIND = "Find...";
+    /**
+     * Action name for repeating the next find.
+     */
     public static final String FIND_NEXT = "Find Next";
+    /**
+     * Action name for repeating the previous find.
+     */
     public static final String FIND_PREVIOUS = "Find Previous";
+    /**
+     * Action name for opening the replace dialog.
+     */
     public static final String REPLACE = "Replace...";
+    /**
+     * Action name for automatic indentation.
+     */
     public static final String AUTO_INDENT = "AutoIndent";
+    /**
+     * Action name for backspace deletion.
+     */
     public static final String DELETE = "delete";
 
     private static final String TABBED_SPACES = "    ";
@@ -131,6 +149,8 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
 
     /**
      * Creates a new instance of TextEditor
+     *
+     * @param tabsAsSpaces whether typed tabs should be converted to spaces
      */
     public TextEditor(boolean tabsAsSpaces) {
         this(tabsAsSpaces, false);
@@ -138,6 +158,9 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
 
     /**
      * Creates a new instance of TextEditor
+     *
+     * @param tabsAsSpaces whether typed tabs should be converted to spaces
+     * @param multiLineTab whether tab actions should affect all selected lines
      */
     public TextEditor(boolean tabsAsSpaces, boolean multiLineTab) {
         this(tabsAsSpaces, multiLineTab, false);
@@ -145,6 +168,10 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
 
     /**
      * Creates a new instance of TextEditor
+     *
+     * @param tabsAsSpaces whether typed tabs should be converted to spaces
+     * @param multiLineTab whether tab actions should affect all selected lines
+     * @param unwrapped whether long lines should avoid viewport wrapping
      */
     public TextEditor(boolean tabsAsSpaces, boolean multiLineTab, boolean unwrapped) {
         this.tabsAsSpaces = tabsAsSpaces;
@@ -213,6 +240,9 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
         overtypeCaret.setBlinkRate(defaultCaret.getBlinkRate());
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void addNotify() {
         super.addNotify();
@@ -220,6 +250,9 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
         FindReplaceUtility.registerTextComponent(this);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public int getNumberOfPages() {
         Paper paper = PAGE_FORMAT.getPaper();
@@ -227,16 +260,25 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
         return numPages;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
         return PAGE_FORMAT;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public Printable getPrintable(int param) throws IndexOutOfBoundsException {
         return this;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public int print(Graphics graphics, PageFormat pageFormat, int page)
             throws PrinterException {
@@ -301,6 +343,9 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
         return Printable.NO_SUCH_PAGE;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public boolean getScrollableTracksViewportWidth() {
         boolean bool = super.getScrollableTracksViewportWidth();
@@ -343,6 +388,9 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
         return unwrapped;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     protected void processKeyEvent(KeyEvent e) {
         super.processKeyEvent(e);
@@ -357,6 +405,9 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void removeNotify() {
         super.removeNotify();
@@ -364,6 +415,9 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
         FindReplaceUtility.unregisterTextComponent(this);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void replaceSelection(String text) {
         //  Implement overtype mode by selecting the character at the current
@@ -377,6 +431,9 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
         super.replaceSelection(text);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void setBounds(int x, int y, int width, int height) {
         if (unwrapped) {
@@ -390,6 +447,8 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
     }
 
     /**
+     * Enables or disables indenting all selected lines when tabbing.
+     *
      * @param multiLineTab the new multiLine tab value
      */
     public void isMultiLineTabbed(boolean multiLineTab) {
@@ -397,6 +456,8 @@ public class TextEditor extends JTextPane implements Pageable, Printable {
     }
 
     /**
+     * Enables or disables replacing typed tab characters with spaces.
+     *
      * @param tabsAsSpaces whether tabs are converted to spaces
      */
     public void isTabsAsSpaces(boolean tabsAsSpaces) {
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextUndoManager.java b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextUndoManager.java
index 5a83a9e20e..45108e694d 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextUndoManager.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/text/TextUndoManager.java
@@ -60,10 +60,18 @@ public class TextUndoManager extends UndoManager {
         this.recording = recording;
     }
 
+    /**
+     * Registers a listener for undo/redo state changes.
+     *
+     * @param pcl the listener to add
+     */
     public void addPropertyChangeListener(PropertyChangeListener pcl) {
         propChangeSupport.addPropertyChangeListener(pcl);
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void die() {
         boolean undoable = canUndo();
@@ -71,6 +79,9 @@ public class TextUndoManager extends UndoManager {
         firePropertyChangeEvent(UndoManager.UndoName, undoable, canUndo());
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void discardAllEdits() {
         boolean undoable = canUndo();
@@ -84,16 +95,31 @@ public class TextUndoManager extends UndoManager {
         firePropertyChangeEvent(UndoManager.UndoName, redoable, canRedo());
     }
 
+    /**
+     * Fires an undo-state property change event.
+     *
+     * @param name the property name
+     * @param oldValue the previous value
+     * @param newValue the new value
+     */
     protected void firePropertyChangeEvent(String name,
                                            boolean oldValue,
                                            boolean newValue) {
         propChangeSupport.firePropertyChange(name, oldValue, newValue);
     }
 
+    /**
+     * Indicates whether the document differs from the last reset point.
+     *
+     * @return {@code true} if undo history contains unreset edits
+     */
     public boolean hasChanged() {
         return modificationMarker != editToBeUndone();
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void redo() throws javax.swing.undo.CannotRedoException {
         compoundEdit.end();
@@ -110,6 +136,9 @@ public class TextUndoManager extends UndoManager {
         firePropertyChangeEvent(UndoManager.UndoName, undoable, canUndo());
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     protected void redoTo(UndoableEdit edit) {
         compoundEdit.end();
@@ -127,10 +156,18 @@ public class TextUndoManager extends UndoManager {
 
     }
 
+    /**
+     * Removes a listener for undo/redo state changes.
+     *
+     * @param pcl the listener to remove
+     */
     public void removePropertyChangeListener(PropertyChangeListener pcl) {
         propChangeSupport.removePropertyChangeListener(pcl);
     }
 
+    /**
+     * Marks the current undo position as the unmodified state.
+     */
     public void reset() {
         boolean changed = modificationMarker != editToBeUndone();
         if (changed) {
@@ -138,6 +175,9 @@ public class TextUndoManager extends UndoManager {
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     protected void trimEdits(int from, int to) {
         boolean undoable = canUndo();
@@ -150,6 +190,9 @@ public class TextUndoManager extends UndoManager {
         firePropertyChangeEvent(UndoManager.RedoName, redoable, canRedo());
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void undo() throws javax.swing.undo.CannotUndoException {
         compoundEdit.end();
@@ -168,6 +211,9 @@ public class TextUndoManager extends UndoManager {
         firePropertyChangeEvent(UndoManager.RedoName, redoable, canRedo());
     }
 
+    /**
+     * {@inheritDoc}
+     */
     @Override
     public void undoableEditHappened(UndoableEditEvent uee) {
         if (!recording) {
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicContentPane.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicContentPane.groovy
index c1fe372586..32a4c44d3c 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicContentPane.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicContentPane.groovy
@@ -44,10 +44,13 @@ import static javax.swing.JSplitPane.VERTICAL_SPLIT
 
 Preferences prefs = Preferences.userNodeForPackage(Console)
 def detachedOutputFlag = prefs.getBoolean('detachedOutput', false)
+/** Detached output frame shown when console output is separated from the main window. */
 outputWindow = frame(visible: false, defaultCloseOperation: WindowConstants.HIDE_ON_CLOSE) {
+    /** Placeholder component swapped in while the output area is detached. */
     blank = glue()
     blank.preferredSize = [0, 0] as Dimension
 }
+/** Split pane that hosts the editor and the attached output area. */
 splitPane = splitPane(resizeWeight: 0.5, orientation:
         prefs.getBoolean('orientationVertical', true) ? VERTICAL_SPLIT : HORIZONTAL_SPLIT) {
     def editor = new ConsoleTextEditor()
@@ -55,12 +58,15 @@ splitPane = splitPane(resizeWeight: 0.5, orientation:
     if (smartHighlighterEnabled) {
         editor.enableHighLighter(SmartDocumentFilter)
     }
+    /** Editor wrapper used for script input. */
     inputEditor = widget(editor, border: emptyBorder(0))
     buildOutputArea(prefs)
 }
 
 private def buildOutputArea(prefs) {
+    /** Scroll pane that contains the console output component. */
     scrollArea = scrollPane(border: emptyBorder(0)) {
+        /** Read-only text pane used to render console output. */
         outputArea = textPane(
                 editable: false,
                 name: 'outputArea',
@@ -73,6 +79,7 @@ private def buildOutputArea(prefs) {
 }
 
 
+/** Text component backing the script input area. */
 inputArea = inputEditor.textEditor
 inputArea.background = ThemeManager.inputBackground
 // attach ctrl-enter to input area
@@ -102,21 +109,27 @@ def applyStyle = { Style style, values -> values.each { k, v -> style.addAttribu
 Style regular = doc.addStyle('regular', defStyle)
 applyStyle(regular, styles.regular)
 
+/** Style used for console prompts. */
 promptStyle = doc.addStyle('prompt', regular)
 applyStyle(promptStyle, styles.prompt)
 
+/** Style used for echoed commands. */
 commandStyle = doc.addStyle('command', regular)
 applyStyle(commandStyle, styles.command)
 
+/** Style used for standard output. */
 outputStyle = doc.addStyle('output', regular)
 applyStyle(outputStyle, styles.output)
 
+/** Style used for evaluation results. */
 resultStyle = doc.addStyle('result', regular)
 applyStyle(resultStyle, styles.result)
 
+/** Style used for stack traces. */
 stacktraceStyle = doc.addStyle('stacktrace', regular)
 applyStyle(stacktraceStyle, styles.stacktrace)
 
+/** Style used for hyperlinks in the output pane. */
 hyperlinkStyle = doc.addStyle('hyperlink', regular)
 applyStyle(hyperlinkStyle, styles.hyperlink)
 
@@ -158,6 +171,7 @@ inputEditor.preferredSize = [
         prefs.getInt('inputAreaHeight', (fm.getHeight() + fm.getLeading()) * 12)
 ] as Dimension
 
+/** Original split-pane divider size restored when output is reattached. */
 origDividerSize = -1
 if (detachedOutputFlag) {
     splitPane.add(blank, JSplitPane.BOTTOM)
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicMenuBar.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicMenuBar.groovy
index 8fa5045dfe..83ad4ec7ae 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicMenuBar.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicMenuBar.groovy
@@ -72,8 +72,11 @@ menuBar {
         separator()
         menu(text: 'Theme') {
             buttonGroup(id: 'themeGroup')
+            /** Menu item that selects the light theme. */
             lightThemeMenuItem = radioButtonMenuItem(lightThemeAction, buttonGroup: themeGroup, selected: controller.currentTheme == 'LIGHT')
+            /** Menu item that selects the dark theme. */
             darkThemeMenuItem = radioButtonMenuItem(darkThemeAction, buttonGroup: themeGroup, selected: controller.currentTheme == 'DARK')
+            /** Menu item that selects the system theme. */
             systemThemeMenuItem = radioButtonMenuItem(systemThemeAction, buttonGroup: themeGroup, selected: controller.currentTheme == 'SYSTEM')
         }
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicStatusBar.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicStatusBar.groovy
index 36c649be82..b205395d72 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicStatusBar.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicStatusBar.groovy
@@ -22,14 +22,17 @@ import javax.swing.SwingConstants
 import java.awt.BorderLayout
 import java.awt.GridBagConstraints
 
+/** Status bar panel shown at the bottom of the console window. */
 statusPanel = panel(constraints: BorderLayout.SOUTH) {
     gridBagLayout()
     separator(gridwidth: GridBagConstraints.REMAINDER, fill: GridBagConstraints.HORIZONTAL)
+    /** Label displaying the current console status message. */
     status = label("Welcome to Groovy ${GroovySystem.version}.",
             weightx: 1.0,
             anchor: GridBagConstraints.WEST,
             fill: GridBagConstraints.HORIZONTAL,
             insets: [1, 3, 1, 3])
     separator(orientation: SwingConstants.VERTICAL, fill: GridBagConstraints.VERTICAL)
+    /** Label displaying the current caret line and column. */
     rowNumAndColNum = label('1:1', insets: [1, 3, 1, 3])
 }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicToolBar.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicToolBar.groovy
index 07cd511532..559a117996 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicToolBar.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/BasicToolBar.groovy
@@ -26,6 +26,7 @@ import java.awt.BorderLayout
 // Toolbar buttons override each action's smallIcon with a resizable toolbar-only
 // icon — so View → Icon Size / Scale with Font affect toolbar icons only,
 // not the matching menu items (which keep the fixed-size menu icons).
+/** Toolbar shown above the editor and output area. */
 toolbar = toolBar(rollover: true, visible: controller.showToolbar, constraints: BorderLayout.NORTH) {
     button(newFileAction,      text: null, icon: Icons.toolbar('note_add'))
     button(openAction,         text: null, icon: Icons.toolbar('folder_open'))
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/GTKDefaults.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/GTKDefaults.groovy
index 16c88fbc79..3166d5e1d3 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/GTKDefaults.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/GTKDefaults.groovy
@@ -45,6 +45,7 @@ try {
     ps.isAttributeValueSupported(orient, docFlav, attrset)
 } catch (NullPointerException npe) {
     //print will bomb out... replace with disabled print action
+    /** Disabled print action used when native printing support is unavailable. */
     printAction = action(
         name: 'Print...',
         closure: controller.&print,
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/MacOSXDefaults.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/MacOSXDefaults.groovy
index 2bb5fe7ac4..5a7f10fafe 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/MacOSXDefaults.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/MacOSXDefaults.groovy
@@ -35,4 +35,5 @@ styles.regular[StyleConstants.FontFamily] = fontFamily
 styles[StyleContext.DEFAULT_STYLE] = styles[StyleContext.DEFAULT_STYLE] ?: [:]
 styles[StyleContext.DEFAULT_STYLE][StyleConstants.FontFamily] = fontFamily
 
-menuBarClass = MacOSXMenuBar
\ No newline at end of file
+/** Menu bar implementation used for macOS screen-menu integration. */
+menuBarClass = MacOSXMenuBar
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/MacOSXMenuBar.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/MacOSXMenuBar.groovy
index 3ef144cb8d..19db4d15bd 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/MacOSXMenuBar.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/view/MacOSXMenuBar.groovy
@@ -236,6 +236,12 @@ menuBar {
     }
 }
 
+/**
+ * Tests whether the current class loader can resolve the supplied class name.
+ *
+ * @param className the fully qualified class name to resolve
+ * @return {@code true} if the class is available
+ */
 static classExists(String className) {
     try {
         MacOSXMenuBar.class.classLoader.loadClass(className)
diff --git a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/FormatStringChecker.groovy b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/FormatStringChecker.groovy
index 6ab8f48c3c..e77bfca59c 100644
--- a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/FormatStringChecker.groovy
+++ b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/FormatStringChecker.groovy
@@ -72,7 +72,14 @@ class FormatStringChecker extends GroovyTypeCheckingExtensionSupport.TypeCheckin
     private static final ClassNode LOCALE_TYPE = makeCached(Locale)
     private static final ClassNode FORMATTER_TYPE = makeCached(Formatter)
 
+    /**
+     * Pattern used to extract {@link Formatter} conversion specifiers from constant format strings.
+     */
     private String formatSpecifier = /%(\d+\$)?([-#+ 0,(\<]*)?(\d+)?(\.\d+)?([tT])?([a-zA-Z%])/
+
+    /**
+     * AST patterns for formatter-style methods that this checker validates automatically.
+     */
     private List<ASTNode> formatMethods = [
         macro(CompilePhase.SEMANTIC_ANALYSIS) { String.format(a) }.withConstraints { varargPlaceholder a },
         macro { _.format(a) }.withConstraints { varargPlaceholder a },
@@ -83,6 +90,9 @@ class FormatStringChecker extends GroovyTypeCheckingExtensionSupport.TypeCheckin
         macro { _.formatted(a) }.withConstraints{ varargPlaceholder a }
     ]
 
+    /**
+     * Registers checks for built-in formatter calls and methods annotated with {@link FormatMethod}.
+     */
     @Override
     Object run() {
         afterMethodCall { call ->
diff --git a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/ModifiesChecker.groovy b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/ModifiesChecker.groovy
index 7412fc215c..87fcf24438 100644
--- a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/ModifiesChecker.groovy
+++ b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/ModifiesChecker.groovy
@@ -94,6 +94,9 @@ class ModifiesChecker extends GroovyTypeCheckingExtensionSupport.TypeCheckingDSL
     private static final Set<String> SIDE_EFFECT_FREE_ANNOS = Set.of('SideEffectFree')
     private static final Set<String> CONTRACT_ANNOS = Set.of('Contract')
 
+    /**
+     * Registers frame-condition checks for methods visited by the type checker.
+     */
     @Override
     Object run() {
         afterVisitMethod { MethodNode mn ->
diff --git a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/NullChecker.groovy b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/NullChecker.groovy
index 71ed0e24f6..e7ebb5a9c9 100644
--- a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/NullChecker.groovy
+++ b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/NullChecker.groovy
@@ -107,6 +107,9 @@ class NullChecker extends GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
     private static final Set<String> NONNULL_BY_DEFAULT_ANNOS = Set.of('NonNullByDefault', 'NonnullByDefault', 'NullMarked')
     private static final Set<String> NULL_UNMARKED_ANNOS = Set.of('NullUnmarked')
 
+    /**
+     * Registers null-safety checks for each visited method body.
+     */
     @Override
     Object run() {
         boolean strict = options?.strict ?: false
diff --git a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/PurityChecker.groovy b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/PurityChecker.groovy
index 198ca35d26..de9ceba61e 100644
--- a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/PurityChecker.groovy
+++ b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/PurityChecker.groovy
@@ -165,6 +165,9 @@ class PurityChecker extends GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
             'java.sql.',
     ]
 
+    /**
+     * Registers purity checks for annotated methods encountered during type checking.
+     */
     @Override
     Object run() {
         Set<String> baseAllows = parseAllows(options?.allows as String)
diff --git a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/RegexChecker.groovy b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/RegexChecker.groovy
index f53ef4f3ed..04d671a401 100644
--- a/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/RegexChecker.groovy
+++ b/subprojects/groovy-typecheckers/src/main/groovy/groovy/typecheckers/RegexChecker.groovy
@@ -107,6 +107,9 @@ class RegexChecker extends GroovyTypeCheckingExtensionSupport.TypeCheckingDSL {
     private static final String REGEX_GROUP_COUNT = RegexChecker.getSimpleName() + '_INFERRED_GROUP_COUNT'
     private static final String REGEX_MATCHER_RESULT_TYPE = RegexChecker.getSimpleName() + '_MATCHER_RESULT_INFERRED_TYPE'
 
+    /**
+     * Registers regex validation and matcher type-inference hooks for visited methods.
+     */
     @Override
     Object run() {
         beforeVisitMethod { MethodNode method ->
diff --git a/subprojects/groovy-typecheckers/src/main/groovy/org/apache/groovy/typecheckers/CheckingVisitor.groovy b/subprojects/groovy-typecheckers/src/main/groovy/org/apache/groovy/typecheckers/CheckingVisitor.groovy
index f7b285fc1d..7ab6430786 100644
--- a/subprojects/groovy-typecheckers/src/main/groovy/org/apache/groovy/typecheckers/CheckingVisitor.groovy
+++ b/subprojects/groovy-typecheckers/src/main/groovy/org/apache/groovy/typecheckers/CheckingVisitor.groovy
@@ -28,16 +28,35 @@ import org.codehaus.groovy.ast.expr.Expression
 import org.codehaus.groovy.ast.expr.VariableExpression
 import org.codehaus.groovy.control.SourceUnit
 
+/**
+ * Base visitor support for type-checker extensions that need lightweight constant propagation
+ * and access to the underlying variable represented by a {@link VariableExpression}.
+ */
 @AutoFinal @CompileStatic
 class CheckingVisitor extends ClassCodeVisitorSupport {
 
+    /**
+     * Returns no backing source unit because subclasses report errors through the enclosing
+     * type-checking extension rather than this visitor.
+     */
     @Override
     protected SourceUnit getSourceUnit() {
         null
     }
 
+    /**
+     * Tracks local variables whose values are known constant expressions during the current visit.
+     */
     protected final Map<Expression,Expression> localConstVars = [:]
 
+    /**
+     * Resolves a constant expression of the requested type from an expression, following tracked
+     * locals and field initializers when possible.
+     *
+     * @param exp expression to inspect
+     * @param type required runtime type for the constant value
+     * @return the matching constant expression, or {@code null} when none can be resolved
+     */
     protected Expression findConstExp(Expression exp, Class type) {
         if (exp instanceof ConstantExpression && type.isAssignableFrom(exp.value.getClass())) {
             return exp
@@ -54,6 +73,12 @@ class CheckingVisitor extends ClassCodeVisitorSupport {
         null
     }
 
+    /**
+     * Follows {@link VariableExpression#accessedVariable} links until the original variable or field is found.
+     *
+     * @param ve variable expression to resolve
+     * @return the underlying target variable
+     */
     protected Variable findTargetVariable(VariableExpression ve) {
         def accessedVariable = ve.accessedVariable
         if (accessedVariable != null && accessedVariable != ve) {