You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2022/07/08 12:56:26 UTC

[groovy] branch GROOVY_4_0_X updated (052892cd76 -> 3e285ec4ec)

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

paulk pushed a change to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


    from 052892cd76 GROOVY-10680: GroovyConsole should display record components
     new 4d7fefaf9f GROOVY-10684: Support opening the Object browser from within the AST browser
     new 3e285ec4ec GROOVY-10684: Support opening the Object browser from within the AST browser fix (streamline AST Browser interface now we have Object browser launching, there is less need to have as much noise in the hierarchy)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../src/main/groovy/groovy/console/TextNode.groovy |   4 +-
 .../groovy/groovy/console/TextTreeNodeMaker.groovy |   6 +-
 .../groovy/groovy/console/ui/AstBrowser.groovy     | 118 +++++++++---------
 .../console/ui/ScriptToTreeNodeAdapter.groovy      | 134 ++++++---------------
 .../groovy/console/ui/AstBrowserProperties.groovy  |  50 ++++----
 .../console/ui/ScriptToTreeNodeAdapterTest.groovy  | 130 ++++++++------------
 6 files changed, 177 insertions(+), 265 deletions(-)


[groovy] 01/02: GROOVY-10684: Support opening the Object browser from within the AST browser

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 4d7fefaf9f61d25be3751ce31e1a6e1ce5576dd2
Author: Paul King <pa...@asert.com.au>
AuthorDate: Fri Jul 8 01:39:22 2022 +1000

    GROOVY-10684: Support opening the Object browser from within the AST browser
---
 .../src/main/groovy/groovy/console/TextNode.groovy |   4 +-
 .../groovy/groovy/console/TextTreeNodeMaker.groovy |   6 +-
 .../groovy/groovy/console/ui/AstBrowser.groovy     | 110 +++++++++------------
 .../console/ui/ScriptToTreeNodeAdapter.groovy      |  20 ++--
 .../console/ui/ScriptToTreeNodeAdapterTest.groovy  |   2 +-
 5 files changed, 67 insertions(+), 75 deletions(-)

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 b61a748051..8621cf5284 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/TextNode.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/TextNode.groovy
@@ -26,7 +26,7 @@ import groovy.transform.CompileStatic
 @CompileStatic
 class TextNode {
     Object userObject
-    List<List<String>> properties
+    List<List<?>> properties
     TextNode parent
     List children
 
@@ -35,7 +35,7 @@ class TextNode {
         children = new ArrayList<TextNode>()
     }
 
-    TextNode(Object userObject, List<List<String>> properties) {
+    TextNode(Object userObject, List<List<?>> properties) {
         this(userObject)
         this.properties = properties
     }
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 3bc9ef0468..9b6cd46ada 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/TextTreeNodeMaker.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/TextTreeNodeMaker.groovy
@@ -17,7 +17,7 @@
  *  under the License.
  */
 /**
- * A factory class for plain text nodes for use in the AST tree made by ASTBrowser
+ * A factory class for text nodes for use in the AST tree made by ASTBrowser
  */
 package groovy.console
 
@@ -30,7 +30,7 @@ class TextTreeNodeMaker implements AstBrowserNodeMaker<TextNode> {
         new TextNode(userObject)
     }
 
-    TextNode makeNodeWithProperties(Object userObject, List<List<String>> properties) {
+    TextNode makeNodeWithProperties(Object userObject, List<List<?>> properties) {
         new TextNode(userObject, properties)
     }
-}
\ No newline at end of file
+}
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 df323db0ce..7f9a9a4055 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
@@ -32,7 +32,6 @@ import org.objectweb.asm.util.ASMifier
 import org.objectweb.asm.util.TraceClassVisitor
 
 import javax.swing.Action
-import javax.swing.JFrame
 import javax.swing.JSplitPane
 import javax.swing.KeyStroke
 import javax.swing.UIManager
@@ -43,10 +42,11 @@ import javax.swing.tree.DefaultMutableTreeNode
 import javax.swing.tree.DefaultTreeModel
 import javax.swing.tree.TreeNode
 import javax.swing.tree.TreeSelectionModel
-import java.awt.BorderLayout
 import java.awt.Cursor
 import java.awt.Font
 import java.awt.event.KeyEvent
+import java.awt.event.MouseAdapter
+import java.awt.event.MouseEvent
 import java.util.prefs.Preferences
 import java.util.regex.Pattern
 
@@ -56,6 +56,7 @@ import static java.awt.GridBagConstraints.NONE
 import static java.awt.GridBagConstraints.NORTHEAST
 import static java.awt.GridBagConstraints.NORTHWEST
 import static java.awt.GridBagConstraints.WEST
+import static javax.swing.ListSelectionModel.SINGLE_SELECTION
 
 /**
  * This object is a GUI for looking at the AST that Groovy generates.
@@ -193,13 +194,23 @@ class AstBrowser {
                                     model: new DefaultTreeModel(new DefaultMutableTreeNode('Loading...'))) {}
                         },
                         rightComponent: scrollPane {
-                            propertyTable = table {
+                            propertyTable = table(selectionMode: SINGLE_SELECTION) {
                                 tableModel(list: [[:]]) {
                                     propertyColumn(header: 'Name', propertyName: 'name')
-                                    propertyColumn(header: 'Value', propertyName: 'value')
+                                    propertyColumn(header: 'Value  (double-click to browse)', propertyName: 'value')
                                     propertyColumn(header: 'Type', propertyName: 'type')
+                                    propertyColumn(header: 'Raw', propertyName: 'raw')
                                 }
                             }
+                            propertyTable.columnModel.getColumn(3).with {
+                                minWidth = 0
+                                maxWidth = 0
+                                width = 0
+                            }
+                            propertyTable.addMouseListener(makeClickAdapter(propertyTable, 3) { row ->
+                                'Browsing ' + jTree.lastSelectedPathComponent.userObject + ": " + propertyTable.model.getValueAt(row, 0)
+                            })
+                            propertyTable.setDefaultEditor(Object, null)
                         }
                 ) {}
                 mainSplitter = splitPane(
@@ -225,51 +236,11 @@ class AstBrowser {
         jTree.addTreeSelectionListener({ TreeSelectionEvent e ->
 
             propertyTable.model.rows.clear()
-            propertyTable.columnModel.getColumn(1).cellRenderer = new ButtonOrDefaultRenderer()
-            propertyTable.columnModel.getColumn(1).cellEditor = new ButtonOrTextEditor()
             TreeNode node = jTree.lastSelectedPathComponent
             if (node instanceof TreeNodeWithProperties) {
-                def titleSuffix = node.properties.find { it[0] == 'text' }?.get(1)
-                for (it in node.properties) {
-                    def propList = it
-                    if (propList[2] == "ListHashMap" && propList[1] != 'null' && propList[1] != '[:]') {
-                        //If the class is a ListHashMap, make it accessible in a new frame through a button
-                        def kvPairs = propList[1].substring(1, propList[1].length() - 1).tokenize(',')
-                        def kvFirst = kvPairs.get(0)
-                        def btnPanel = swing.button(
-                                text: "Key/value pairs: [" + kvFirst.substring(0, Math.min(25, kvFirst.size())) + "...]",
-                                actionPerformed: {
-                                    def mapTable
-                                    String title = titleSuffix ? propList[0] + " (" + titleSuffix + ")" : propList[0]
-                                    def props = swing.frame(title: title, defaultCloseOperation: JFrame.DISPOSE_ON_CLOSE,
-                                            show: true, locationRelativeTo: null) {
-                                        lookAndFeel 'system'
-                                        borderLayout(vgap: 5)
-                                        panel(constraints: BorderLayout.CENTER) {
-                                            borderLayout()
-                                            scrollPane {
-                                                mapTable = swing.table {
-                                                    tableModel(list: [[:]]) {
-                                                        propertyColumn(header: 'Name', propertyName: 'name')
-                                                        propertyColumn(header: 'Value', propertyName: 'value')
-                                                    }
-                                                }
-                                            }
-                                        }
-                                    }
-                                    mapTable.model.rows.clear()
-                                    kvPairs.each {
-                                        def kv = it.tokenize(':')
-                                        if (kv)
-                                            mapTable.model.rows << ["name": kv[0], "value": kv[1]]
-                                    }
-                                    props.pack()
-                                })
-                        propertyTable.model.rows << ["name": propList[0], "value": btnPanel, "type": propList[2]]
-                        btnPanel.updateUI()
-                    } else {
-                        propertyTable.model.rows << ["name": it[0], "value": it[1], "type": it[2]]
-                    }
+                def titleSuffix = node.properties.find { list -> list[0] == 'text' }?.get(1)
+                for (list in node.properties) {
+                    propertyTable.model.rows << [name: list[0], value: list[1], type: list[2], raw: list[3]]
                 }
 
                 if (inputArea && rootElement) {
@@ -356,6 +327,22 @@ class AstBrowser {
         return sw.toString()
     }
 
+    def makeClickAdapter(table, int valueCol, Closure pathClosure) {
+        new MouseAdapter() {
+            void mouseClicked(MouseEvent e) {
+                if (e.clickCount == 2) {
+                    def selectedRow = table.selectedRow
+                    if (selectedRow != -1) {
+                        def value = table.model.getValueAt(selectedRow, valueCol)
+                        if (value != null) {
+                            ObjectBrowser.inspect(value, pathClosure(selectedRow))
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private void showSource(view, String source, boolean showOnlyMethodCode, boolean isMethodNameAndMethodDescriptorAvailable, getPatternStr) {
         swing.doLater {
             view.textEditor.text = source
@@ -401,7 +388,7 @@ class AstBrowser {
 
     void showAbout(EventObject evt) {
         def pane = swing.optionPane()
-        def version = GroovySystem.getVersion()
+        def version = GroovySystem.version
         pane.setMessage('An interactive GUI to explore AST capabilities\nVersion ' + version)
         def dialog = pane.createDialog(frame, 'About Groovy AST Browser')
         dialog.pack()
@@ -439,8 +426,7 @@ class AstBrowser {
     }
 
     void decompile(phaseId, source) {
-
-        decompiledSource.textEditor.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR))
+        decompiledSource.textEditor.cursor = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)
         decompiledSource.textEditor.text = 'Loading...'
 
         swing.doOutside {
@@ -449,14 +435,14 @@ class AstBrowser {
                 String result = new AstNodeToScriptAdapter().compileToScript(source, phaseId, classLoader, showScriptFreeForm, showScriptClass, config)
                 swing.doLater {
                     decompiledSource.textEditor.text = result
-                    decompiledSource.textEditor.setCaretPosition(0)
-                    decompiledSource.textEditor.setCursor(Cursor.defaultCursor)
+                    decompiledSource.textEditor.caretPosition = 0
+                    decompiledSource.textEditor.cursor = Cursor.defaultCursor
                 }
             } catch (Throwable t) {
                 swing.doLater {
                     decompiledSource.textEditor.text = t.getMessage()
-                    decompiledSource.textEditor.setCaretPosition(0)
-                    decompiledSource.textEditor.setCursor(Cursor.defaultCursor)
+                    decompiledSource.textEditor.caretPosition = 0
+                    decompiledSource.textEditor.cursor = Cursor.defaultCursor
                 }
                 throw t
             }
@@ -479,13 +465,13 @@ class AstBrowser {
                 classLoader.clearBytecodeTable()
                 def result = adapter.compile(script, compilePhase)
                 swing.doLater {
-                    model.setRoot(result)
+                    model.root = result
                     model.reload()
-                    jTree.setCursor(Cursor.defaultCursor)
+                    jTree.cursor = Cursor.defaultCursor
                 }
             } catch (Throwable t) {
                 swing.doLater {
-                    jTree.setCursor(Cursor.defaultCursor)
+                    jTree.cursor = Cursor.defaultCursor
                 }
                 throw t
             }
@@ -582,20 +568,20 @@ enum CompilePhaseAdapter {
 @CompileStatic
 class TreeNodeWithProperties extends DefaultMutableTreeNode {
 
-    List<List<String>> properties
+    List<List<?>> properties
 
     /**
      * Creates a tree node and attaches properties to it.
      * @param userObject same as a DefaultMutableTreeNode requires
      * @param properties a list of String lists
      */
-    TreeNodeWithProperties(userObject, List<List<String>> properties) {
+    TreeNodeWithProperties(userObject, List<List<?>> properties) {
         super(userObject)
         this.properties = properties
     }
 
     String getPropertyValue(String name) {
-        def match = properties.find { n, v, t -> name == n }
+        def match = properties.find { List list -> name == list[0] }
         return match != null ? match[1] : null
     }
 
@@ -615,7 +601,7 @@ class TreeNodeWithProperties extends DefaultMutableTreeNode {
 interface AstBrowserNodeMaker<T> {
     T makeNode(Object userObject)
 
-    T makeNodeWithProperties(Object userObject, List<List<String>> properties)
+    T makeNodeWithProperties(Object userObject, List<List<?>> properties)
 }
 
 /**
@@ -627,7 +613,7 @@ class SwingTreeNodeMaker implements AstBrowserNodeMaker<DefaultMutableTreeNode>
         new DefaultMutableTreeNode(userObject)
     }
 
-    DefaultMutableTreeNode makeNodeWithProperties(Object userObject, List<List<String>> properties) {
+    DefaultMutableTreeNode makeNodeWithProperties(Object userObject, List<List<?>> properties) {
         new TreeNodeWithProperties(userObject, properties)
     }
 }
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 411af2c354..17f91de468 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
@@ -195,45 +195,51 @@ class ScriptToTreeNodeAdapter {
     }
 
     def make(node) {
-        nodeMaker.makeNodeWithProperties(getStringForm(node), getPropertyTable(node))
+        makeWithTable(node, getPropertyTable(node))
     }
 
     def make(MethodNode node) {
         def table = getPropertyTable(node)
         extendMethodNodePropertyTable(table, node)
+        makeWithTable(node, table)
+    }
 
+    private makeWithTable(node, List<List<?>> table) {
         nodeMaker.makeNodeWithProperties(getStringForm(node), table)
     }
 
     /**
      * Extends the method node property table by adding custom properties.
      */
-    void extendMethodNodePropertyTable(List<List<String>> table, MethodNode node) {
-        table << ['descriptor', BytecodeHelper.getMethodDescriptor(node), 'String']
+    void extendMethodNodePropertyTable(List<List<?>> table, MethodNode node) {
+        def descriptor = BytecodeHelper.getMethodDescriptor(node)
+        table << ['descriptor', descriptor, 'String', descriptor]
     }
 
     /**
      * Creates the property table for the node so that the properties view can display nicely.
      */
-    private List<List<String>> getPropertyTable(node) {
+    private List<List<?>> getPropertyTable(node) {
         node.metaClass.properties.findResults { mp ->
             if (mp instanceof MetaBeanProperty && mp.getter) {
                 String name = mp.name, type = mp.type.simpleName
+                Object valueAsString = null
                 Object value = null
                 try {
                     // multiple assignment statements cannot be cast to VariableExpression so
                     // instead reference the value through the leftExpression property, which is the same
                     if (node instanceof DeclarationExpression && (name == 'variableExpression' || name == 'tupleExpression')) {
-                        value = toString(node.leftExpression)
+                        value = node.leftExpression
                     } else {
-                        value = toString(mp.getProperty(node))
+                        value = mp.getProperty(node)
                     }
+                    valueAsString = toString(value)
                 } catch (GroovyBugError ignore) {
                     // compiler throws error if it thinks a field is being accessed
                     // before it is set under certain conditions. It wasn't designed
                     // to be walked reflectively like this.
                 }
-                [name, value, type]
+                [name, valueAsString, type, value]
             }
         }.sort { list -> list[0] } // sort by name
     }
diff --git a/subprojects/groovy-console/src/test/groovy/groovy/console/ui/ScriptToTreeNodeAdapterTest.groovy b/subprojects/groovy-console/src/test/groovy/groovy/console/ui/ScriptToTreeNodeAdapterTest.groovy
index 6538e9e48a..20e3ee5b56 100644
--- a/subprojects/groovy-console/src/test/groovy/groovy/console/ui/ScriptToTreeNodeAdapterTest.groovy
+++ b/subprojects/groovy-console/src/test/groovy/groovy/console/ui/ScriptToTreeNodeAdapterTest.groovy
@@ -514,7 +514,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
         def methods = classNodeTest.children().find { it.toString() == 'Methods' }
         def methodNodeTest = methods.children().find { it.toString() == 'MethodNode - test' }
 
-        assert methodNodeTest.properties.any { name, value, type -> name == 'descriptor' && value == '()V' && type == 'String' }
+        assert methodNodeTest.properties.any { name, value, type, _ -> name == 'descriptor' && value == '()V' && type == 'String' }
     }
 
     void testScriptWithAdapterThatLoadsGeneratedClosureClass() {


[groovy] 02/02: GROOVY-10684: Support opening the Object browser from within the AST browser fix (streamline AST Browser interface now we have Object browser launching, there is less need to have as much noise in the hierarchy)

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 3e285ec4ec4111a9dd3d714d5039e6dfc1782a36
Author: Paul King <pa...@asert.com.au>
AuthorDate: Fri Jul 8 20:40:57 2022 +1000

    GROOVY-10684: Support opening the Object browser from within the AST browser fix (streamline AST Browser interface now we have Object browser launching, there is less need to have as much noise in the hierarchy)
---
 .../groovy/groovy/console/ui/AstBrowser.groovy     |  16 ++-
 .../console/ui/ScriptToTreeNodeAdapter.groovy      | 114 +++++-------------
 .../groovy/console/ui/AstBrowserProperties.groovy  |  50 ++++----
 .../console/ui/ScriptToTreeNodeAdapterTest.groovy  | 128 ++++++++-------------
 4 files changed, 114 insertions(+), 194 deletions(-)

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 7f9a9a4055..685ddb026a 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
@@ -202,10 +202,18 @@ class AstBrowser {
                                     propertyColumn(header: 'Raw', propertyName: 'raw')
                                 }
                             }
-                            propertyTable.columnModel.getColumn(3).with {
-                                minWidth = 0
-                                maxWidth = 0
-                                width = 0
+                            propertyTable.columnModel.with {
+                                // raw column hidden
+                                getColumn(3).with {
+                                    minWidth = 0
+                                    maxWidth = 0
+                                    width = 0
+                                    preferredWidth = 0
+                                }
+                                // allow more space for value column
+                                getColumn(0).preferredWidth = 100
+                                getColumn(1).preferredWidth = 400
+                                getColumn(2).preferredWidth = 100
                             }
                             propertyTable.addMouseListener(makeClickAdapter(propertyTable, 3) { row ->
                                 'Browsing ' + jTree.lastSelectedPathComponent.userObject + ": " + propertyTable.model.getValueAt(row, 0)
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 17f91de468..d6eab946eb 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
@@ -320,7 +320,6 @@ class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNode
         collectFieldData(child, 'Fields', classNode)
         collectPropertyData(child, 'Properties', classNode)
         collectRecordComponentData(child, 'Record Components', classNode)
-        collectAnnotationData(child, 'Annotations', classNode.annotations)
 
         if (showClosureClasses)  {
             makeClosureClassTreeNodes(classNode)
@@ -345,40 +344,28 @@ class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNode
             collectFieldData(child, 'Fields', innerClassNode)
             collectPropertyData(child, 'Properties', innerClassNode)
             collectRecordComponentData(child, 'Record Components', classNode)
-            collectAnnotationData(child, 'Annotations', innerClassNode.annotations)
-        }
-    }
-
-    private void collectAnnotationData(parent, String name, List<AnnotationNode> annotations) {
-        if (annotations) {
-            def header = nodeMaker.makeNode(name)
-            parent.add(header)
-            annotations?.each { AnnotationNode annotationNode ->
-                header.add(adapter.make(annotationNode))
-            }
         }
     }
 
     private void collectPropertyData(parent, String name, ClassNode classNode) {
-        def allProperties = nodeMaker.makeNode(name)
-        if (classNode.properties) parent.add(allProperties)
-        classNode.properties?.each {PropertyNode propertyNode ->
-            def ggrandchild = adapter.make(propertyNode)
-            allProperties.add(ggrandchild)
-            collectTypeData(ggrandchild, 'Type', propertyNode.type)
-            collectInitialValueData(ggrandchild, propertyNode.field?.initialValueExpression)
-            collectAnnotationData(ggrandchild, 'Annotations', propertyNode.annotations)
+        if (classNode.properties) {
+            def allProperties = nodeMaker.makeNode(name)
+            parent.add(allProperties)
+            classNode.properties.each { PropertyNode propertyNode ->
+                def ggrandchild = adapter.make(propertyNode)
+                allProperties.add(ggrandchild)
+            }
         }
     }
 
     private void collectRecordComponentData(parent, String name, ClassNode classNode) {
-        def allProperties = nodeMaker.makeNode(name)
-        if (classNode.properties) parent.add(allProperties)
-        classNode.recordComponents?.each { RecordComponentNode recordComponentNode ->
-            def ggrandchild = adapter.make(recordComponentNode)
-            allProperties.add(ggrandchild)
-            collectTypeData(ggrandchild, 'Type', recordComponentNode.type)
-            collectAnnotationData(ggrandchild, 'Annotations', recordComponentNode.annotations)
+        if (classNode.recordComponents) {
+            def allRecords = nodeMaker.makeNode(name)
+            parent.add(allRecords)
+            classNode.recordComponents.each { RecordComponentNode recordComponentNode ->
+                def ggrandchild = adapter.make(recordComponentNode)
+                allRecords.add(ggrandchild)
+            }
         }
     }
 
@@ -386,24 +373,9 @@ class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNode
         if (classNode.fields) {
             def allFields = nodeMaker.makeNode(name)
             parent.add(allFields)
-            classNode.fields?.each {FieldNode fieldNode ->
+            classNode.fields.each { FieldNode fieldNode ->
                 def ggrandchild = adapter.make(fieldNode)
                 allFields.add(ggrandchild)
-                collectTypeData(ggrandchild, 'Type', fieldNode.type)
-                collectInitialValueData(ggrandchild, fieldNode.initialValueExpression)
-                collectAnnotationData(ggrandchild, 'Annotations', fieldNode.annotations)
-            }
-        }
-    }
-
-    private void collectInitialValueData(parent, Expression init) {
-        if (init) {
-            TreeNodeBuildingVisitor visitor = new TreeNodeBuildingVisitor(adapter)
-            init.visit(visitor)
-            if (visitor.currentNode) {
-                def header = nodeMaker.makeNode('Initial Value')
-                header.add(visitor.currentNode)
-                parent.add(header)
             }
         }
     }
@@ -427,15 +399,8 @@ class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNode
         methods?.each { MethodNode methodNode ->
             def ggrandchild = adapter.make(methodNode)
             allMethods.add(ggrandchild)
-            collectTypeData(ggrandchild, 'Return Type', methodNode.returnType)
-
-            // print out parameters of method
-            methodNode.parameters?.each { Parameter parameter ->
-                collectParameterData(ggrandchild, parameter)
-            }
-
+            collectParametersData(ggrandchild, methodNode)
             collectBodyData(ggrandchild, methodNode.code)
-            collectAnnotationData(ggrandchild, 'Annotations', methodNode.annotations)
         }
     }
 
@@ -451,38 +416,25 @@ class TreeNodeBuildingNodeOperation implements CompilationUnit.IPrimaryClassNode
         }
     }
 
-    private void collectParameterData(parent, Parameter parameter) {
-        def paramChild = adapter.make(parameter)
-        collectTypeData(paramChild, 'Type', parameter.type)
-        collectInitialValueData(paramChild, parameter.initialExpression)
-        collectAnnotationData(paramChild, 'Annotations', parameter.annotations)
-        parent.add(paramChild)
-    }
-
-    private void collectTypeData(parent, String name, ClassNode type) {
-        if (type) {
-            def header = nodeMaker.makeNode(name)
-            def child = adapter.make(type)
-            header.add(child)
-            collectAnnotationData(child, 'Annotations', type.annotations)
-            collectAnnotationData(child, 'Type Annotations', type.typeAnnotations)
-            parent.add(header)
+    private void collectParametersData(parent, MethodNode methodNode) {
+        if (methodNode.parameters) {
+            def allParamNodes = nodeMaker.makeNode('Parameters')
+            parent.add(allParamNodes)
+            methodNode.parameters.each { Parameter parameter ->
+                def paramNode = adapter.make(parameter)
+                allParamNodes.add(paramNode)
+            }
         }
     }
 
     private void collectConstructorData(parent, String name, ClassNode classNode) {
         def allCtors = nodeMaker.makeNode(name)
         if (classNode.declaredConstructors) parent.add(allCtors)
-        classNode.declaredConstructors?.each {ConstructorNode ctorNode ->
-
+        classNode.declaredConstructors?.each { ConstructorNode ctorNode ->
             def ggrandchild = adapter.make(ctorNode)
             allCtors.add(ggrandchild)
-            ctorNode.parameters?.each { Parameter parameter ->
-                collectParameterData(ggrandchild, parameter)
-            }
-
+            collectParametersData(ggrandchild, ctorNode)
             collectBodyData(ggrandchild, ctorNode.code)
-            collectAnnotationData(ggrandchild, 'Annotations', ctorNode.annotations)
         }
 
     }
@@ -703,19 +655,7 @@ class TreeNodeBuildingVisitor extends CodeVisitorSupport {
      * Makes walking parameters look like others in the visitor.
      */
     void visitParameter(Parameter node) {
-        addNode(node, Parameter, {
-            if (node.type) {
-                def header = adapter.nodeMaker.makeNode('Type')
-                header.add(adapter.make(node.type))
-                currentNode.add(header)
-            }
-            if (node.initialExpression) {
-                def header = adapter.nodeMaker.makeNode('Initial Value')
-                currentNode.add(header)
-                currentNode = header
-                node.initialExpression?.visit(this)
-            }
-        })
+        addNode(node, Parameter, { })
     }
 
     @Override
diff --git a/subprojects/groovy-console/src/main/resources/groovy/console/ui/AstBrowserProperties.groovy b/subprojects/groovy-console/src/main/resources/groovy/console/ui/AstBrowserProperties.groovy
index ae090f2e9b..07bb9c221d 100644
--- a/subprojects/groovy-console/src/main/resources/groovy/console/ui/AstBrowserProperties.groovy
+++ b/subprojects/groovy-console/src/main/resources/groovy/console/ui/AstBrowserProperties.groovy
@@ -24,13 +24,13 @@ org {
             ast {
                 ClassNode           = "ClassNode - \$expression.name"
                 InnerClassNode      = "InnerClassNode - \$expression.name"
-                ConstructorNode     = "ConstructorNode - \$expression.name"
-                MethodNode          = "MethodNode - \$expression.name"
-                FieldNode           = "FieldNode - \$expression.name : \$expression.type"
-                PropertyNode        = "PropertyNode - \${expression.field?.name} : \${expression.field?.type}"
-                RecordComponentNode = "RecordComponentNode - \$expression.name : \$expression.type"
+                ConstructorNode     = "ConstructorNode - \$expression.name(\${expression.parameters*.type*.toString(false).join(', ')})"
+                MethodNode          = "MethodNode - \$expression.name(\${expression.parameters*.type*.toString(false).join(', ')})"
+                FieldNode           = "FieldNode - \${expression.type.toString(false)} \$expression.name\${expression.initialValueExpression ? ' = ' + expression.initialValueExpression.text : ''}"
+                PropertyNode        = "PropertyNode - \${expression.field?.type.toString(false)} \${expression.field?.name}\${expression.field?.initialValueExpression ? ' = ' + expression.field?.initialValueExpression.text : ''}"
+                RecordComponentNode = "RecordComponentNode - \${expression.type.toString(false)} \$expression.name"
                 AnnotationNode      = "AnnotationNode - \${expression.classNode?.name}"
-                Parameter           = "Parameter - \$expression.name"
+                Parameter           = "Parameter - \${expression.type.toString(false)} \$expression.name\${expression.initialExpression ? ' = ' + expression.initialExpression.text : ''}"
                 DynamicVariable     = "DynamicVariable - \$expression.name"
 
                 stmt {
@@ -41,25 +41,25 @@ org {
                     CatchStatement      = "CatchStatement - \$expression.exceptionType]"
                 }
                 expr {
-                    ConstructorCallExpression   = "ConstructorCall - \$expression.text"
-                    SpreadExpression        = "Spread - \$expression.text"
-                    ArgumentListExpression  = "ArgumentList - \$expression.text"
-                    MethodCallExpression    = "MethodCall - \$expression.text"
-                    GStringExpression       = "GString - \$expression.text"
-                    AttributeExpression     = "Attribute - \$expression.text"
-                    DeclarationExpression   = "Declaration - \$expression.text"
-                    VariableExpression      = "Variable - \$expression.name : \$expression.type"
-                    ConstantExpression      = "Constant - \$expression.value : \$expression.type"
-                    BinaryExpression        = "Binary - \$expression.text"
-                    ClassExpression         = "Class - \$expression.text"
-                    BooleanExpression       = "Boolean - \$expression.text"
-                    ArrayExpression         = "Array - \$expression.text"
-                    ListExpression          = "List - \$expression.text"
-                    TupleExpression         = "Tuple - \$expression.text"
-                    FieldExpression         = "Field - \$expression.text"
-                    PropertyExpression      = "Property - \$expression.propertyAsString"
-                    NotExpression           = "Not - \$expression.text"
-                    CastExpression          = "Cast - \$expression.text"
+                    ConstructorCallExpression = "ConstructorCall - \$expression.text"
+                    SpreadExpression          = "Spread - \$expression.text"
+                    ArgumentListExpression    = "ArgumentList - \$expression.text"
+                    MethodCallExpression      = "MethodCall - \$expression.text"
+                    GStringExpression         = "GString - \$expression.text"
+                    AttributeExpression       = "Attribute - \$expression.text"
+                    DeclarationExpression     = "Declaration - \$expression.text"
+                    VariableExpression        = "Variable - \${expression.type.toString(false)} \$expression.name"
+                    ConstantExpression        = "Constant - \${expression.type.toString(false)} \$expression.value"
+                    BinaryExpression          = "Binary - \$expression.text"
+                    ClassExpression           = "Class - \$expression.text"
+                    BooleanExpression         = "Boolean - \$expression.text"
+                    ArrayExpression           = "Array - \$expression.text"
+                    ListExpression            = "List - \$expression.text"
+                    TupleExpression           = "Tuple - \$expression.text"
+                    FieldExpression           = "Field - \$expression.text"
+                    PropertyExpression        = "Property - \$expression.propertyAsString"
+                    NotExpression             = "Not - \$expression.text"
+                    CastExpression            = "Cast - \$expression.text"
                 }
             }
         }
diff --git a/subprojects/groovy-console/src/test/groovy/groovy/console/ui/ScriptToTreeNodeAdapterTest.groovy b/subprojects/groovy-console/src/test/groovy/groovy/console/ui/ScriptToTreeNodeAdapterTest.groovy
index 20e3ee5b56..b63e878d08 100644
--- a/subprojects/groovy-console/src/test/groovy/groovy/console/ui/ScriptToTreeNodeAdapterTest.groovy
+++ b/subprojects/groovy-console/src/test/groovy/groovy/console/ui/ScriptToTreeNodeAdapterTest.groovy
@@ -133,7 +133,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         eq('BlockStatement - (1)'),
                         startsWith('ExpressionStatement'),
-                        startsWith('Constant - Hello World : java.lang.String')
+                        startsWith('Constant - java.lang.String Hello World')
                 ])
     }
 
@@ -143,7 +143,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         eq('ClassNode - Foo'),
                         eq('Fields'),
-                        startsWith('FieldNode - aField : java.lang.Object'),
+                        startsWith('FieldNode - java.lang.Object aField'),
                 ]
         )
     }
@@ -154,31 +154,22 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                     startsWith('ClassNode - script'),
                     eq('Methods'),
-                    eq('MethodNode - foo'),
-                    eq('Parameter - bar'),
+                    eq('MethodNode - foo(java.lang.String)'),
+                    eq('Parameters'),
+                    eq('Parameter - java.lang.String bar'),
                 ]
             )
     }
 
     void testMethodWithParameterAndInitialValue() {
         def script = ' def foo(String bar = "some_value") { println bar } '
-        // check Type path for bar
+        // check path for bar
         assertTreeStructure(script, [
                 startsWith('ClassNode - script'),
                 eq('Methods'),
-                eq('MethodNode - foo'),
-                eq('Parameter - bar'),
-                eq('Type'),
-                startsWith('ClassNode - java.lang.String'),
-        ])
-        // check Initial Value path for bar
-        assertTreeStructure(script, [
-                startsWith('ClassNode - script'),
-                eq('Methods'),
-                eq('MethodNode - foo'),
-                eq('Parameter - bar'),
-                eq('Initial Value'),
-                eq('Constant - some_value : java.lang.String'),
+                eq('MethodNode - foo(java.lang.String)'),
+                eq('Parameters'),
+                eq('Parameter - java.lang.String bar = some_value'),
         ])
     }
 
@@ -190,32 +181,20 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                         startsWith('ExpressionStatement'),
                         startsWith('Declaration - def x ='),
                         startsWith('ClosureExpression'),
-                        startsWith('Parameter - parm1'),
+                        startsWith('Parameter - java.lang.Object parm1'),
                 ]
         )
     }
 
     void testClosureParametersWithInitialValue() {
         def script = ' def x = { parm1 = "some_value" ->  println parm1 } '
-        // check Type path for parm1
-        assertTreeStructure(script, [
-                eq('BlockStatement - (1)'),
-                startsWith('ExpressionStatement'),
-                startsWith('Declaration - def x ='),
-                eq('ClosureExpression'),
-                startsWith('Parameter - parm1'),
-                eq('Type'),
-                startsWith('ClassNode - java.lang.Object'),
-        ])
-        // check Initial Value path for parm1
+        // check path for parm1
         assertTreeStructure(script, [
                 eq('BlockStatement - (1)'),
                 startsWith('ExpressionStatement'),
                 startsWith('Declaration - def x ='),
                 eq('ClosureExpression'),
-                startsWith('Parameter - parm1'),
-                eq('Initial Value'),
-                startsWith('Constant - some_value : java.lang.String'),
+                startsWith('Parameter - java.lang.Object parm1'),
         ])
     }
 
@@ -240,8 +219,8 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
         def children = namedArgList.children().toList()
         assertEquals('Wrong # named arguments', 2, children.size())
 
-        assertMapEntry(children[0], 'Constant - foo : java.lang.String', 'Constant - bar : java.lang.String')
-        assertMapEntry(children[1], 'Constant - baz : java.lang.String', 'Constant - qux : java.lang.String')
+        assertMapEntry(children[0], 'Constant - java.lang.String foo', 'Constant - java.lang.String bar')
+        assertMapEntry(children[1], 'Constant - java.lang.String baz', 'Constant - java.lang.String qux')
     }
 
     void testDynamicVariable() {
@@ -251,7 +230,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                         eq('BlockStatement - (1)'),
                         eq('ExpressionStatement - BinaryExpression'),
                         eq('Binary - (foo = bar)'),
-                        startsWith('Variable - foo : java.lang.Object'),
+                        startsWith('Variable - java.lang.Object foo'),
                         eq('DynamicVariable - foo'),
                 ]
             )
@@ -263,11 +242,11 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         startsWith('ClassNode'),
                         eq('Methods'),
-                        startsWith('MethodNode - run'),
+                        startsWith('MethodNode - run()'),
                         eq('Body'),
                         startsWith('BlockStatement'),
                         startsWith('ExpressionStatement'),
-                        startsWith('Constant - foo'),
+                        startsWith('Constant - java.lang.String foo'),
                 ]
         )
     }
@@ -293,7 +272,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         eq('ClassNode - MyEnum'),
                         eq('Fields'),
-                        startsWith('FieldNode - FOO : MyEnum'),
+                        startsWith('FieldNode - MyEnum FOO'),
                 ])
     }
 
@@ -303,7 +282,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         startsWith('ClassNode'),
                         eq('Methods'),
-                        eq('MethodNode - main'),
+                        eq('MethodNode - main(java.lang.String[])'),
                         eq('Body'),
                         startsWith('ExpressionStatement'),  //notice, there is only one ExpressionStatement
                         startsWith('StaticMethodCallExpression'),
@@ -337,7 +316,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         startsWith('InnerClassNode - Outer\$Inner'),
                         eq('Methods'),
-                        eq('MethodNode - someMethod'),
+                        eq('MethodNode - someMethod()'),
                         eq('Body'),
                         startsWith('BlockStatement'),
                 ]
@@ -354,22 +333,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         startsWith('InnerClassNode - Outer\$Inner'),
                         eq('Fields'),
-                        startsWith('FieldNode - field'),
-                ]
-        )
-    }
-
-    void testInnerClassWithAnnotations() {
-        assertTreeStructure(
-                '''class Outer {
-                    @Singleton
-                    private class Inner {
-                    }
-                }''',
-                [
-                        startsWith('InnerClassNode - Outer\$Inner'),
-                        eq('Annotations'),
-                        startsWith('AnnotationNode - groovy.lang.Singleton'),
+                        startsWith('FieldNode - java.lang.String field'),
                 ]
         )
     }
@@ -384,7 +348,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         startsWith('InnerClassNode - Outer\$Inner'),
                         eq('Properties'),
-                        startsWith('PropertyNode - property'),
+                        startsWith('PropertyNode - java.lang.Object property'),
                 ]
         )
     }
@@ -395,8 +359,9 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 'def foo(String bar) {}',
                 [
                     eq('Methods'),
-                    eq('MethodNode - foo'),
-                    eq('Parameter - bar'),
+                    eq('MethodNode - foo(java.lang.String)'),
+                    eq('Parameters'),
+                    eq('Parameter - java.lang.String bar'),
                 ]
             )
 
@@ -406,8 +371,9 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                     startsWith('ClassNode - script'),
                     eq('Methods'),
-                    eq('MethodNode - foo'),
-                    eq('Parameter - bar'),
+                    eq('MethodNode - foo(java.lang.String)'),
+                    eq('Parameters'),
+                    eq('Parameter - java.lang.String bar'),
                 ]
             )
     }
@@ -421,8 +387,9 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                     'def foo(String bar) {}',
                     [
                         eq('Methods'),
-                        eq('MethodNode - foo'),
-                        eq('Parameter - bar'),
+                        eq('MethodNode - foo(java.lang.String)'),
+                        eq('Parameters'),
+                        eq('Parameter - java.lang.String bar'),
                     ],
                     adapter
                 )
@@ -434,8 +401,9 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                     startsWith('ClassNode - script'),
                     eq('Methods'),
-                    eq('MethodNode - foo'),
-                    eq('Parameter - bar'),
+                    eq('MethodNode - foo(java.lang.String)'),
+                    eq('Parameters'),
+                    eq('Parameter - java.lang.String bar'),
                 ],
                 adapter
             )
@@ -449,8 +417,9 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 'def foo(String bar) {}',
                 [
                     eq('Methods'),
-                    eq('MethodNode - foo'),
-                    eq('Parameter - bar'),
+                    eq('MethodNode - foo(java.lang.String)'),
+                    eq('Parameters'),
+                    eq('Parameter - java.lang.String bar'),
                 ],
                 adapter
             )
@@ -462,8 +431,9 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                     [
                         startsWith('ClassNode - script'),
                         eq('Methods'),
-                        eq('MethodNode - foo'),
-                        eq('Parameter - bar'),
+                        eq('MethodNode - foo(java.lang.String)'),
+                        eq('Parameters'),
+                        eq('Parameter - java.lang.String bar'),
                     ],
                     adapter
                 )
@@ -479,7 +449,8 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                     'def foo(String bar) {}',
                     [
                         eq('Methods'),
-                        eq('MethodNode - foo'),
+                        eq('MethodNode - foo(String)'),
+                        eq('Parameters'),
                         eq('Parameter - bar'),
                     ],
                     adapter
@@ -493,7 +464,8 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                     [
                         startsWith('ClassNode - script'),
                         eq('Methods'),
-                        eq('MethodNode - foo'),
+                        eq('MethodNode - foo(String)'),
+                        eq('Parameters'),
                         eq('Parameter - bar'),
                     ],
                     adapter
@@ -512,7 +484,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
 
         def classNodeTest = root.children().find { it.toString() == 'ClassNode - Test' }
         def methods = classNodeTest.children().find { it.toString() == 'Methods' }
-        def methodNodeTest = methods.children().find { it.toString() == 'MethodNode - test' }
+        def methodNodeTest = methods.children().find { it.toString() == 'MethodNode - test()' }
 
         assert methodNodeTest.properties.any { name, value, type, _ -> name == 'descriptor' && value == '()V' && type == 'String' }
     }
@@ -525,7 +497,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                     contains('closure1'),
                     eq('Methods'),
-                    eq('MethodNode - doCall'),
+                    eq('MethodNode - doCall()'),
                 ],
                 adapter
             )
@@ -554,7 +526,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         contains('closure1'),
                         eq('Methods'),
-                        eq('MethodNode - doCall'),
+                        eq('MethodNode - doCall()'),
                 ],
                 adapter)
 
@@ -562,7 +534,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         contains('closure2'),
                         eq('Methods'),
-                        eq('MethodNode - doCall'),
+                        eq('MethodNode - doCall()'),
                 ],
                 adapter)
 
@@ -570,7 +542,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
                 [
                         contains('closure3'),
                         eq('Methods'),
-                        eq('MethodNode - doCall'),
+                        eq('MethodNode - doCall()'),
                 ],
                 adapter)
     }
@@ -637,7 +609,7 @@ final class ScriptToTreeNodeAdapterTest extends GroovyTestCase {
 
         def classNodeTest = root.children().find { it.toString() == 'ClassNode - Test' }
         def methods = classNodeTest.children().find { it.toString() == 'Methods' }
-        def methodNodeTest = methods.children().find { it.toString() == 'MethodNode - test' }
+        def methodNodeTest = methods.children().find { it.toString() == 'MethodNode - test()' }
 
         assert classNodeTest
         assert methods