diff --git a/checkstyleConfig.xml b/checkstyleConfig.xml
index 21058b3ae4..c46c3a475f 100644
--- a/checkstyleConfig.xml
+++ b/checkstyleConfig.xml
@@ -744,7 +744,7 @@
-
+
diff --git a/ide/org.codehaus.groovy.eclipse.astviews/plugin.xml b/ide/org.codehaus.groovy.eclipse.astviews/plugin.xml
index 19953701a4..43848c7a35 100644
--- a/ide/org.codehaus.groovy.eclipse.astviews/plugin.xml
+++ b/ide/org.codehaus.groovy.eclipse.astviews/plugin.xml
@@ -11,7 +11,11 @@
class="org.codehaus.groovy.eclipse.astviews.ASTView"
icon="platform:/plugin/org.codehaus.groovy.eclipse/$nl$/groovy16.png"
id="org.codehaus.groovy.eclipse.astviews.ASTView"
- name="Groovy AST Viewer">
+ name="Groovy AST Viewer"
+ restorable="false">
+
+ Inspect the Abstract Syntax Tree (AST) of a Groovy source
+
diff --git a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ASTView.groovy b/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ASTView.groovy
index e6cc7ac636..15df024738 100644
--- a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ASTView.groovy
+++ b/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ASTView.groovy
@@ -15,14 +15,16 @@
*/
package org.codehaus.groovy.eclipse.astviews
+import static java.beans.Introspector.decapitalize
+
import static org.eclipse.jdt.core.JavaCore.addElementChangedListener
import static org.eclipse.jdt.core.JavaCore.removeElementChangedListener
import static org.eclipse.swt.widgets.Display.getDefault as getDisplay
import groovy.transform.*
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.ModuleNode
+import org.codehaus.groovy.ast.*
+import org.codehaus.groovy.control.*
import org.codehaus.groovy.eclipse.editor.GroovyEditor
import org.codehaus.jdt.groovy.model.GroovyCompilationUnit
import org.eclipse.core.runtime.Adapters
@@ -31,12 +33,15 @@ import org.eclipse.jdt.core.ICompilationUnit
import org.eclipse.jdt.core.IElementChangedListener
import org.eclipse.jdt.core.IJavaElement
import org.eclipse.jdt.core.IJavaElementDelta
+import org.eclipse.jdt.groovy.core.util.GroovyUtils
+import org.eclipse.jface.action.MenuManager
import org.eclipse.jface.text.TextSelection
-import org.eclipse.jface.viewers.IStructuredContentProvider
import org.eclipse.jface.viewers.IStructuredSelection
import org.eclipse.jface.viewers.ITreeContentProvider
import org.eclipse.jface.viewers.LabelProvider
import org.eclipse.jface.viewers.TreeViewer
+import org.eclipse.jface.viewers.Viewer
+import org.eclipse.jface.viewers.ViewerFilter
import org.eclipse.swt.SWT
import org.eclipse.swt.widgets.Composite
import org.eclipse.ui.IEditorPart
@@ -47,7 +52,8 @@ import org.eclipse.ui.part.ViewPart
import org.eclipse.ui.texteditor.ITextEditor
/**
- * A view into the Groovy AST. Anyone who needs to manipulate the AST will find this useful for exploring various nodes.
+ * A view into the Groovy AST. Anyone who needs to manipulate the AST will find
+ * this useful for exploring various nodes.
*/
@AutoFinal @CompileStatic
class ASTView extends ViewPart {
@@ -58,43 +64,60 @@ class ASTView extends ViewPart {
private IPartListener partListener
- private IElementChangedListener listener
+ private IElementChangedListener reconcileListener
@Override
void createPartControl(Composite parent) {
- viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL)
- DrillDownAdapter drillDownAdapter = new DrillDownAdapter(viewer)
- viewer.contentProvider = new ViewContentProvider()
- viewer.labelProvider = new ViewLabelProvider()
- viewer.comparator = null
- viewer.input = null
+ viewer = new TreeViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL)
+ viewer.contentProvider = new TreeContentProvider()
+ viewer.labelProvider = new TreeLabelProvider()
+ viewer.addFilter(new TreeNodeFilter())
viewer.addDoubleClickListener { event ->
- def obj = ((IStructuredSelection) viewer.selection).firstElement
- def val = ((ITreeNode) obj)?.value
- if (val instanceof ASTNode) {
- ASTNode node = (ASTNode) val
- if (node.lineNumber > 0 && editor instanceof ITextEditor) {
- ((ITextEditor) editor).selectionProvider.selection = new TextSelection(node.start, node.length)
+ def element = ((IStructuredSelection) viewer.selection).firstElement
+ if (((TreeNode) element).value instanceof ASTNode) {
+ def astNode = (ASTNode) ((TreeNode) element).value
+ if (astNode.lineNumber > 0 && editor instanceof ITextEditor) {
+ ((ITextEditor) editor).selectionProvider.selection = new TextSelection(astNode.start, astNode.length)
}
}
}
- listener = { ElementChangedEvent event ->
- if (editor != null) {
- def unit = Adapters.adapt(editor.editorInput, GroovyCompilationUnit)
- if (isUnitInDelta(event.delta, unit)) {
- display.asyncExec { ->
- def treePaths =
- viewer.expandedElements
- viewer.input = unit.moduleNode
- viewer.expandedElements = treePaths
- }
+ // add tree navigation actions to toolbar
+ def downer = new DrillDownAdapter(viewer)
+ viewSite.actionBars.toolBarManager.with {
+ downer.addNavigationActions(it)
+ update(true)
+ }
+
+ // add tree navigation actions to context menu
+ viewer.tree.menu = new MenuManager('#PopupMenu').with {
+ viewSite.registerContextMenu(it, viewer)
+ downer.addNavigationActions(it)
+ createContextMenu(viewer.tree)
+ }
+
+ def resetTreeView = { root ->
+ viewer.input = root
+ downer.reset()
+ }
+
+ //
+
+ reconcileListener = { ElementChangedEvent event ->
+ def unit = Adapters.adapt(editor, GroovyCompilationUnit)
+ if (unit != null && isUnitInDelta(event.delta, unit)) {
+ display.asyncExec { ->
+ def ee = viewer.expandedElements
+ resetTreeView(unit.moduleNode)
+ viewer.setExpandedElements(ee)
}
}
}
- addElementChangedListener(listener, ElementChangedEvent.POST_RECONCILE)
+ addElementChangedListener(reconcileListener, ElementChangedEvent.POST_RECONCILE)
+
+ //
partListener = new IPartListener() {
@Override
@@ -103,35 +126,28 @@ class ASTView extends ViewPart {
@Override
void partBroughtToTop(IWorkbenchPart part) {
- try {
- if (part instanceof IEditorPart) {
- def unit = Adapters.adapt(part.editorInput, GroovyCompilationUnit)
- if (unit != null) {
- if (editor != part) {
- editor = part
- def treePaths =
- viewer.expandedElements
- viewer.input = unit.moduleNode
- viewer.expandedElements = treePaths
- }
+ if (part != editor && part instanceof IEditorPart) {
+ try {
+ def node = Adapters.adapt(part, ModuleNode)
+ if (node != null) {
+ resetTreeView(node)
+ editor = part
return
}
+ } catch (Throwable t) {
+ Activator.warn('Error updating AST Viewer', t)
}
- } catch (err) {
- Activator.warn('Error updating AST Viewer', err)
+ resetTreeView(null)
+ editor = null
}
- partClosed(part)
}
@Override
void partClosed(IWorkbenchPart part) {
- // This is a guard - the content provider should not be null, but sometimes this happens when the
- // part is disposed of for various reasons (unhandled exceptions AFAIK). Without this guard,
- // error message popups continue until Eclipse if forcefully killed.
- if (viewer.contentProvider != null) {
- viewer.input = null
+ if (part != null && part == editor) {
+ resetTreeView(null)
+ editor = null
}
- editor = null
}
@Override
@@ -156,11 +172,11 @@ class ASTView extends ViewPart {
@Override
void dispose() {
try {
+ removeElementChangedListener(reconcileListener)
site.page.removePartListener(partListener)
- removeElementChangedListener(listener)
} finally {
+ reconcileListener = null
partListener = null
- listener = null
super.dispose()
}
}
@@ -184,47 +200,191 @@ class ASTView extends ViewPart {
}
}
- @AutoImplement
- private static class ViewContentProvider implements IStructuredContentProvider, ITreeContentProvider {
- private ITreeNode root
+ private static class TreeContentProvider implements ITreeContentProvider {
+ @Override
+ Object[] getElements(Object input) {
+ getChildren(input instanceof ModuleNode ? new TreeNode(value: input) : input)
+ }
@Override
- Object getParent(Object child) {
- if (child instanceof ITreeNode) {
- child.parent
+ Object[] getChildren(Object node) {
+ def treeNode = (TreeNode) node
+ def nodeValue = treeNode.value
+
+ if (nodeValue instanceof ASTNode || nodeValue instanceof DynamicVariable || nodeValue instanceof VariableScope ||
+ nodeValue instanceof SourceUnit || nodeValue instanceof CompileUnit || nodeValue instanceof CompilerConfiguration) {
+ def methods = nodeValue.class.methods.findAll { method ->
+ method.parameterCount == 0 && method.name =~ /^(is|has(?!hCode$)|get(?!(Type)?Class$|(Static)?(Star)?Imports$)|redirect$)/
+ }
+ def results = methods.findResults { method ->
+ String name = method.name
+ if (name.startsWith('get')) {
+ name = decapitalize(name.substring(3))
+ }
+ try {
+ def value = method.invoke(nodeValue)
+ if ((name != 'text' && !nodeValue.is(value)) ||
+ (name == 'text' && !(value =~ /^
+ list << new TreeNode(label: "[$i]", value: e, parent: treeNode)
+ }
+ return list.toArray()
+ }
+
+ if (nodeValue instanceof Map) {
+ def list = ((Map) nodeValue).collect { k, v ->
+ new TreeNode(label: k instanceof String ? /"$k"/ : "[$k]", value: v, parent: treeNode)
+ }
+ return list.toArray()
}
}
@Override
- Object[] getElements(Object inputElement) {
- if (inputElement instanceof ModuleNode) {
- root = TreeNodeFactory.createTreeNode(null, inputElement, 'Module Nodes')
- return root.children
+ boolean hasChildren(Object node) {
+ def value = ((TreeNode) node).value
+
+ if (value instanceof Map || value instanceof Iterable || value instanceof Object[]) {
+ return value // false if empty
}
- return new Object[0]
+
+ (value instanceof ASTNode || value instanceof DynamicVariable || value instanceof VariableScope ||
+ value instanceof SourceUnit || value instanceof CompileUnit || value instanceof CompilerConfiguration)
}
@Override
- Object[] getChildren(Object parent) {
- if (parent instanceof ITreeNode) {
- parent.children
- }
+ Object getParent(Object node) {
+ ((TreeNode) node).parent
}
+ }
+ private static class TreeLabelProvider extends LabelProvider {
@Override
- boolean hasChildren(Object parent) {
- if (parent instanceof ITreeNode) {
- !parent.isLeaf()
+ String getText(Object node) {
+ def label = ((TreeNode) node).label
+ def value = ((TreeNode) node).value
+
+ switch (value) {
+ case Map:
+ case Iterable:
+ case Object[]:
+ return label
+ case Character:
+ return "$label : '$value'"
+ case CharSequence:
+ return "$label : \"$value\""
+ case stmt.Statement:
+ case expr.Expression:
+ def valueType = value.class.simpleName
+ return "$label : ${valueType - ~/(Expression|Statement)$/}"
+ case ClassNode:
+ def clazz = (ClassNode) value
+ return "$label : ${clazz.toString(false).replace(' ', '')}"
+ case MethodNode:
+ def descriptor = ((MethodNode) value).typeDescriptor.replace(
+ '', ((MethodNode) value).declaringClass.nameWithoutPackage)
+ return "$label : ${descriptor.substring(descriptor.indexOf(' ') + 1)}"
+ case Variable:
+ return "$label : ${value['name']}"
+ case ImportNode:
+ return "$label : ${value['text']}"
+ case ASTNode:
+ case SourceUnit:
+ case CompileUnit:
+ case VariableScope:
+ case CompilerConfiguration:
+ if (label.charAt(0) != '[') return label
+ default:
+ return "$label : $value"
}
}
}
- private static class ViewLabelProvider extends LabelProvider {
+ private static class TreeNodeFilter extends ViewerFilter {
@Override
- String getText(Object obj) {
- if (obj instanceof ITreeNode) {
- obj.displayName
+ boolean select(Viewer viewer, Object parent, Object node) {
+ def label = ((TreeNode) node).label
+ def value = ((TreeNode) node).value
+ def outer = parent instanceof TreeNode ? parent.value : parent
+
+ // filter redundant properties
+ if (outer instanceof ClassNode) {
+ if (label ==~ /abstractMethods|allDeclaredMethods|allInterfaces|declaredMethodsMap|fieldIndex|(hasP|p)ackageName|/ +
+ /isDerivedFromGroovyObject|isRedirectNode|module|name(WithoutPackage)?|outer(Most)?Class|plainNodeReference|text/) {
+ return false
+ }
+ } else if (outer instanceof Variable) { // FieldNode, PropertyNode, etc.
+ if (label ==~ /name|hasInitialExpression|initialValueExpression|is(Enum|Final|Private|Protected|Public|Static|Volatile)/) {
+ return false
+ }
+ } else if (outer instanceof MethodNode) {
+ if (label ==~ /firstStatement|is(Abstract|Default|Final|PackageScope|Private|Protected|Public|Static|VoidMethod)|name|typeDescriptor/) {
+ return false
+ }
+ } else if (outer instanceof ModuleNode) {
+ if (label ==~ /isEmpty|packageName|hasPackage(Name)?|scriptClassDummy/) {
+ return false
+ }
+ } else if (outer instanceof CompileUnit) {
+ if (label ==~ /(c|generatedInnerC|sortedC)lasses|hasClassNodeToCompile/) {
+ return false
+ }
+ } else if (outer instanceof ProcessingUnit) {
+ if (label ==~ /AST|CST|source/) {
+ return false
+ }
+ } else if (outer instanceof stmt.Statement) {
+ if (label ==~ /isEmpty|statementLabel/) {
+ return false
+ }
+ } else if (outer instanceof ImportNode || outer instanceof PackageNode) {
+ if (label == 'text') {
+ return false
+ }
+ }
+ if (outer instanceof ASTNode) {
+ if (label ==~ /instance|metaDataMap/) {
+ return false
+ }
+ if (label == 'groovydoc') {
+ return value['present']
+ }
}
+
+ if (value instanceof ClassNode && value['outerClass'] != null &&
+ parent['label'] == 'classes' && parent['parent']['value'] instanceof ModuleNode) {
+ return false
+ }
+
+ if (value instanceof Map || value instanceof Iterable || value instanceof Object[]) {
+ return value // false if empty
+ }
+
+ return true
+ }
+ }
+
+ @EqualsAndHashCode(includes='label,parent')
+ private static class TreeNode {
+ String label
+ Object value
+ TreeNode parent
+
+ void setValue(value) {
+ this.value = value instanceof Iterator ? value.collect() : value
}
}
}
diff --git a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ITreeNode.java b/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ITreeNode.java
deleted file mode 100644
index b4bf7e6ae0..0000000000
--- a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ITreeNode.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2009-2018 the original author or authors.
- *
- * Licensed 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 org.codehaus.groovy.eclipse.astviews;
-
-interface ITreeNode {
- /**
- * Gets the value this tree node represents. This is the wrapped value.
- */
- Object getValue();
-
- ITreeNode getParent();
-
- String getDisplayName();
-
- ITreeNode[] getChildren();
-
- boolean isLeaf();
-}
diff --git a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/MapTo.groovy b/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/MapTo.groovy
deleted file mode 100644
index ac3145124b..0000000000
--- a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/MapTo.groovy
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2009-2018 the original author or authors.
- *
- * Licensed 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 org.codehaus.groovy.eclipse.astviews
-
-import groovy.transform.PackageScope
-
-import org.codehaus.groovy.ast.*
-import org.codehaus.groovy.ast.expr.*
-import org.codehaus.groovy.ast.stmt.*
-
-@PackageScope class MapTo {
-
- private static final Map mapToNames = [
- (ModuleNode) : { it.description },
- (ClassNode) : { it.name },
- (FieldNode) : { it.name },
- (PropertyNode) : { it.name },
- (MethodNode) : { it.name },
- (Parameter) : { it.name },
- (Expression) : { it.class.canonicalName },
- (ExpressionStatement) : { "(${it.expression.class.canonicalName}) ${it.expression.text}" }
- ].asImmutable()
-
- @PackageScope static String names(value) {
- def cls = value.class
- def getter = mapToNames[cls]
- while (getter == null && cls != null) {
- cls = cls.superclass
- getter = mapToNames[cls]
- }
- return getter?.call(value)
- }
-}
diff --git a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/TreeNodeFactory.groovy b/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/TreeNodeFactory.groovy
deleted file mode 100644
index 0f0dae2925..0000000000
--- a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/TreeNodeFactory.groovy
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright 2009-2018 the original author or authors.
- *
- * Licensed 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 org.codehaus.groovy.eclipse.astviews
-
-import java.beans.Introspector
-import java.lang.reflect.Method
-
-import groovy.transform.PackageScope
-
-import org.codehaus.groovy.GroovyBugError
-import org.codehaus.groovy.ast.ASTNode
-import org.codehaus.groovy.ast.ClassNode
-import org.codehaus.groovy.ast.ModuleNode
-import org.codehaus.groovy.control.ProcessingUnit
-
-@PackageScope class TreeNodeFactory {
-
- private static final List forceDefaultNode = [
- org.codehaus.groovy.ast.CompileUnit,
- org.codehaus.groovy.ast.DynamicVariable,
- org.codehaus.groovy.ast.VariableScope,
- org.codehaus.groovy.control.CompilerConfiguration,
- org.codehaus.groovy.control.SourceUnit,
- org.codehaus.jdt.groovy.control.EclipseSourceUnit,
- ].asImmutable()
-
- private static final Object NULL_VALUE = new Object()
-
- @PackageScope static ITreeNode createTreeNode(ITreeNode parent, Object value, String displayName) {
- if (value == null) {
- value = NULL_VALUE
- }
- // The displayName attributes are set after the constructor in the code below because
- // displayName relies on the value object being set before it. Since groovy does not
- // honor the order of attributes in the constructor declaration, value is null when
- // setDisplayName() is called and the ASTViewer becomes frustrating.
- if (value instanceof ASTNode || value.class in forceDefaultNode) {
- def node = new DefaultTreeNode(parent: parent, value: value)
- node.displayName = displayName
- return node
- } else if (value instanceof Iterable || value instanceof Iterator || value instanceof Object[]) {
- def node = new CollectionTreeNode(parent: parent, value: value)
- node.displayName = displayName
- return node
- } else if (value instanceof Map) {
- def node = new MapTreeNode(parent: parent, value: value)
- node.displayName = displayName
- return node
- } else {
- def node = new AtomTreeNode(parent: parent, value: value)
- node.displayName = displayName
- return node
- }
- }
-}
-
-@PackageScope class StringUtil {
- @PackageScope static String toString(Object obj) {
- return TreeNodeFactory.NULL_VALUE.is(obj) ? 'null' : Objects.toString(obj)
- }
-
- @PackageScope static String toString(Class type) {
- // If o is Integer, then Integer.toString() tries to call either of the static toString() methods of Integer.
- // There may be other classes with static toString(args) methods. This is the same code as in Class.toString().
- return (type.isInterface() ? 'interface ' : (type.isPrimitive() ? '' : 'class ')) + type.name
- }
-}
-
-@PackageScope abstract class TreeNode implements ITreeNode {
- protected static final ITreeNode[] NO_CHILDREN = new ITreeNode[0]
-
- ITreeNode parent
- Object value
- String displayName
- Boolean leaf
- ITreeNode[] children
-
- void setDisplayName(String name) {
- def mappedName = MapTo.names(value)
- if (mappedName) {
- name = "$name - $mappedName"
- }
- displayName = name
- }
-
- @Override
- ITreeNode[] getChildren() {
- if (children == null) {
- children = loadChildren()
- if (children == null) {
- children = NO_CHILDREN
- }
- }
- return children
- }
-
- @Override
- boolean isLeaf() {
- if (leaf == null) {
- leaf = (getChildren().length == 0)
- }
- return leaf
- }
-
- abstract ITreeNode[] loadChildren()
-}
-
-@PackageScope class DefaultTreeNode extends TreeNode {
- @Override
- ITreeNode[] loadChildren() {
- List methods = value.class.methods.findAll { method ->
- method.parameterCount == 0 && method.name =~ /^(is|get|redirect)/ && method.declaringClass.name != 'java.lang.Object'
- }
- // remove some redundant methods
- if (value instanceof ClassNode) {
- methods = methods.findAll { method ->
- !(method.name ==~ /get(AbstractMethods|AllDeclaredMethods|AllInterfaces|DeclaredMethodsMap|FieldIndex|Module|NameWithoutPackage|PackageName|PlainNodeReference|Text)|isRedirectNode/)
- }
- } else if (value instanceof ModuleNode) {
- methods = methods.findAll { method ->
- !(method.name ==~ /get(PackageName|ScriptClassDummy)/)
- }
- } else if (value instanceof ProcessingUnit) {
- methods = methods.findAll { method ->
- !(method.name ==~ /get(AST|CST)/)
- }
- }
- if (value instanceof ASTNode) {
- methods = methods.findAll { method ->
- !(method.name ==~ /get(Instance|MetaDataMap)/)
- }
- }
-
- Collection children = methods.findResults { method ->
- String name = method.name
- if (name.startsWith('is')) {
- name = Introspector.decapitalize(name.substring(2))
- } else if (name.startsWith('get')) {
- name = Introspector.decapitalize(name.substring(3))
- }
- try {
- Object value = this.value."${method.name}"()
- if ((name != 'text' && !this.value.is(value)) ||
- (name == 'text' && !(value =~ /^
- TreeNodeFactory.createTreeNode(this, v, k as String)
- } as ITreeNode[]
- }
-}
-
-@PackageScope class AtomTreeNode implements ITreeNode {
- ITreeNode parent
- Object value
- String displayName
- final boolean leaf = true
- final ITreeNode[] children = TreeNode.NO_CHILDREN
-
- void setDisplayName(String name) {
- def mappedName = MapTo.names(value)
- if (mappedName) {
- name = "$name - $mappedName"
- }
- if (value instanceof String) {
- displayName = "$name : '$value'"
- } else {
- def valueString = StringUtil.toString(value)
- if (valueString.indexOf('@') != -1) {
- valueString = value.class.canonicalName
- }
- displayName = "$name : $valueString"
- }
- }
-}