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 2016/07/17 06:05:26 UTC

groovy git commit: GROOVY-5501: When inspecting the AST, it would be nice to have the node metadata properties listed too (based on PR 54 from the old repo)

Repository: groovy
Updated Branches:
  refs/heads/master 9efebf173 -> 5ec4de266


GROOVY-5501: When inspecting the AST, it would be nice to have the node metadata properties listed too (based on PR 54 from the old repo)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/5ec4de26
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/5ec4de26
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/5ec4de26

Branch: refs/heads/master
Commit: 5ec4de266b6511cf955e44f204499486f198db84
Parents: 9efebf1
Author: paulk <pa...@asert.com.au>
Authored: Sun Jul 17 16:05:10 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Sun Jul 17 16:05:10 2016 +1000

----------------------------------------------------------------------
 gradle/pomconfigurer.gradle                     |  3 +
 src/main/org/codehaus/groovy/ast/ASTNode.java   |  4 +
 .../groovy/inspect/swingui/AstBrowser.groovy    | 95 +++++++++++++-------
 .../swingui/ButtonOrDefaultRenderer.groovy      | 40 +++++++++
 .../inspect/swingui/ButtonOrTextEditor.groovy   | 62 +++++++++++++
 5 files changed, 171 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/5ec4de26/gradle/pomconfigurer.gradle
----------------------------------------------------------------------
diff --git a/gradle/pomconfigurer.gradle b/gradle/pomconfigurer.gradle
index ad92275..9495481 100644
--- a/gradle/pomconfigurer.gradle
+++ b/gradle/pomconfigurer.gradle
@@ -570,6 +570,9 @@ project.ext.pomConfigureClosureWithoutTweaks = {
             contributor {
                 name 'Pap L\u0151rinc'
             }
+            contributor {
+                name 'Guillaume Balaine'
+            }
         }
         mailingLists {
             mailingList {

http://git-wip-us.apache.org/repos/asf/groovy/blob/5ec4de26/src/main/org/codehaus/groovy/ast/ASTNode.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/ASTNode.java b/src/main/org/codehaus/groovy/ast/ASTNode.java
index 8874794..c6d238d 100644
--- a/src/main/org/codehaus/groovy/ast/ASTNode.java
+++ b/src/main/org/codehaus/groovy/ast/ASTNode.java
@@ -193,4 +193,8 @@ public class ASTNode {
         }
         return Collections.unmodifiableMap(metaDataMap);
     }
+
+    public ListHashMap getMetaDataMap() {
+        return metaDataMap;
+    }
 }

http://git-wip-us.apache.org/repos/asf/groovy/blob/5ec4de26/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstBrowser.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstBrowser.groovy b/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstBrowser.groovy
index 09fb6bb..5d83958 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstBrowser.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/AstBrowser.groovy
@@ -18,12 +18,16 @@
  */
 package groovy.inspect.swingui
 
+import groovy.lang.GroovyClassLoader.ClassCollector
 import groovy.swing.SwingBuilder
+import org.codehaus.groovy.ast.ClassNode
+import org.codehaus.groovy.control.CompilationUnit
+import org.codehaus.groovy.control.Phases
+import org.codehaus.groovy.control.SourceUnit
+import org.objectweb.asm.ClassReader
+import org.objectweb.asm.util.TraceClassVisitor
 
-import java.awt.Cursor
-import java.awt.Font
-import java.awt.event.KeyEvent
-import java.util.prefs.Preferences
+import javax.swing.JFrame
 import javax.swing.JSplitPane
 import javax.swing.KeyStroke
 import javax.swing.UIManager
@@ -34,27 +38,24 @@ import javax.swing.tree.DefaultMutableTreeNode
 import javax.swing.tree.DefaultTreeModel
 import javax.swing.tree.TreeNode
 import javax.swing.tree.TreeSelectionModel
-import org.codehaus.groovy.control.Phases
-
+import java.awt.Cursor
+import java.awt.Font
+import java.awt.event.KeyEvent
+import java.util.prefs.Preferences
 import java.util.regex.Pattern
 
-import static java.awt.GridBagConstraints.*
-import org.codehaus.groovy.ast.ClassNode
-import groovy.lang.GroovyClassLoader.ClassCollector
-import org.codehaus.groovy.control.CompilationUnit
-import org.codehaus.groovy.control.SourceUnit
-import org.objectweb.asm.ClassReader
-import org.objectweb.asm.util.TraceClassVisitor
+import static java.awt.GridBagConstraints.BOTH
+import static java.awt.GridBagConstraints.HORIZONTAL
+import static java.awt.GridBagConstraints.NONE
+import static java.awt.GridBagConstraints.NORTHEAST
+import static java.awt.GridBagConstraints.NORTHWEST
+import static java.awt.GridBagConstraints.WEST
 
 /**
  * This object is a GUI for looking at the AST that Groovy generates. 
  *
  * Usage: java groovy.inspect.swingui.AstBrowser [filename]
  *         where [filename] is an existing Groovy script. 
- *
- * @author Hamlet D'Arcy (hamletdrc@gmail.com)
- * @author Guillaume Laforge, highlighting the code corresponding to a node selected in the tree view
- * @author Roshan Dawrani - separated out the swing UI related code from the model part so model could be used for various UIs
  */
 
 class AstBrowser {
@@ -200,11 +201,46 @@ 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) {
-
-                node.properties.each {
-                    propertyTable.model.rows << ['name': it[0], 'value': it[1], 'type': it[2]]
+                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 btnPanel = swing.button(
+                            text: "See key/value pairs",
+                            actionPerformed: {
+                                def mapTable
+                                String title = titleSuffix ? propList[0] + " (" + titleSuffix + ")" : propList[0]
+                                swing.frame(title: title, defaultCloseOperation: JFrame.DISPOSE_ON_CLOSE,
+                                        size: [800, 600], show: true, locationRelativeTo: null  ) {
+                                    lookAndFeel("system")
+                                    panel {
+                                        scrollPane() {
+                                            mapTable = swing.table() {
+                                                tableModel(list: [[:]]) {
+                                                    propertyColumn(header: 'Name', propertyName: 'name')
+                                                    propertyColumn(header: 'Value', propertyName: 'value')
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                                mapTable.model.rows.clear()
+                                propList[1].substring(1, propList[1].length() - 1).tokenize(',').each {
+                                    def kv = it.tokenize(':')
+                                    if (kv)
+                                        mapTable.model.rows << ["name": kv[0], "value": kv[1]]
+                                }
+                            })
+                        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]]
+                    }
                 }
 
                 if (inputArea && rootElement) {
@@ -277,7 +313,8 @@ class AstBrowser {
         frame.size = prefs.frameSize
         splitterPane.dividerLocation = prefs.verticalDividerLocation
         mainSplitter.dividerLocation = prefs.horizontalDividerLocation
-        frame.show()
+        frame.pack()
+        frame.visible = true
 
         String source = script()
         decompile(phasePicker.selectedItem.phaseId, source)
@@ -317,9 +354,11 @@ class AstBrowser {
 
     void showAbout(EventObject evt) {
         def pane = swing.optionPane()
-        pane.setMessage('An interactive GUI to explore AST capabilities.')
+        def version = GroovySystem.getVersion()
+        pane.setMessage('An interactive GUI to explore AST capabilities\nVersion ' + version)
         def dialog = pane.createDialog(frame, 'About Groovy AST Browser')
-        dialog.show()
+        dialog.pack()
+        dialog.visible = true
     }
 
     void showScriptFreeForm(EventObject evt) {
@@ -401,8 +440,6 @@ class AstBrowser {
 
 /**
  * This class sets and restores control positions in the browser.
- *
- * @author Hamlet D'Arcy
  */
 class AstBrowserUiPreferences {
 
@@ -458,8 +495,6 @@ class AstBrowserUiPreferences {
 
 /**
  * An adapter for the CompilePhase enum that can be entered into a Swing combobox.
- *
- * @author Hamlet D'Arcy
  */
 enum CompilePhaseAdapter {
     INITIALIZATION(Phases.INITIALIZATION, 'Initialization'),
@@ -487,8 +522,6 @@ enum CompilePhaseAdapter {
 
 /**
  * This class is a TreeNode and you can store additional properties on it.
- *
- * @author Hamlet D'Arcy
  */
 class TreeNodeWithProperties extends DefaultMutableTreeNode {
 
@@ -520,8 +553,6 @@ class TreeNodeWithProperties extends DefaultMutableTreeNode {
 
 /**
  * This interface is used to create tree nodes of various types 
- *
- * @author Roshan Dawrani
  */
 interface AstBrowserNodeMaker<T> {
     T makeNode(Object userObject)
@@ -531,8 +562,6 @@ interface AstBrowserNodeMaker<T> {
 
 /**
  * Creates tree nodes for swing UI  
- *
- * @author Roshan Dawrani
  */
 class SwingTreeNodeMaker implements AstBrowserNodeMaker<DefaultMutableTreeNode> {
     DefaultMutableTreeNode makeNode(Object userObject) {

http://git-wip-us.apache.org/repos/asf/groovy/blob/5ec4de26/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ButtonOrDefaultRenderer.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ButtonOrDefaultRenderer.groovy b/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ButtonOrDefaultRenderer.groovy
new file mode 100644
index 0000000..00a7f0d
--- /dev/null
+++ b/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ButtonOrDefaultRenderer.groovy
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package groovy.inspect.swingui
+
+import javax.swing.JComponent
+import javax.swing.JTable
+import javax.swing.table.DefaultTableCellRenderer
+import java.awt.Component
+
+/**
+ * A table cell renderer that will return a component instead of drawing it,
+ * or call the default in the case of a non component object.
+ * This hack allows to render a button shape in a table cell.
+ */
+class ButtonOrDefaultRenderer extends DefaultTableCellRenderer {
+    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))
+            return value
+        }
+        return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column)
+    }
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/5ec4de26/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ButtonOrTextEditor.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ButtonOrTextEditor.groovy b/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ButtonOrTextEditor.groovy
new file mode 100644
index 0000000..6253f62
--- /dev/null
+++ b/subprojects/groovy-console/src/main/groovy/groovy/inspect/swingui/ButtonOrTextEditor.groovy
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package groovy.inspect.swingui
+
+import javax.swing.AbstractCellEditor
+import javax.swing.JButton
+import javax.swing.JComponent
+import javax.swing.JTable
+import javax.swing.JTextArea
+import javax.swing.table.TableCellEditor
+import java.awt.Component
+import java.awt.event.ActionListener
+import java.awt.event.FocusListener
+
+/**
+ * A table cell editor that will return a button automatically if it is the cell value,
+ * a text field if the value exists, or null otherwise (non editable cell).
+ * This hack allows to interact with buttons in a cell.
+ */
+class ButtonOrTextEditor extends AbstractCellEditor implements TableCellEditor {
+    /** The Swing component being edited. */
+    protected JComponent editorComponent
+
+    @Override
+    Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+        if (value instanceof JButton) {
+            editorComponent = value
+            editorComponent.addActionListener({ fireEditingStopped() } as ActionListener)
+        } else if (value instanceof JTextArea) {
+            editorComponent = value
+        } else if (value) {
+            editorComponent = new JTextArea(value.toString())
+            editorComponent.addFocusListener({ fireEditingCanceled() } as FocusListener)
+        } else {
+            editorComponent = null
+        }
+        editorComponent
+    }
+
+    @Override
+    Object getCellEditorValue() {
+        editorComponent
+    }
+}
+