A much-improved implementation of asXML(); thx to Wim Deblauwe for coordinating and coding this up!

git-svn-id: https://pmd.svn.sourceforge.net/svnroot/pmd/trunk@3531 51baf565-9d33-0410-a72c-fc3788e3496d
This commit is contained in:
Tom Copeland
2005-06-02 02:21:13 +00:00
parent 6857df0422
commit acc1d13915
7 changed files with 192 additions and 132 deletions

View File

@ -395,5 +395,3 @@ Added new HTML report format
June 25 2002 - 0.1:
Initial release

View File

@ -1,7 +1,5 @@
package test.net.sourceforge.pmd.ast;
import net.sourceforge.pmd.ast.ASTAnnotation;
import net.sourceforge.pmd.ast.ASTAnnotationTypeDeclaration;
import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.ast.ASTCompilationUnit;
import net.sourceforge.pmd.ast.ASTEqualityExpression;
@ -10,8 +8,14 @@ import net.sourceforge.pmd.ast.ASTModifiers;
import net.sourceforge.pmd.ast.ASTRelationalExpression;
import net.sourceforge.pmd.ast.ASTTypeDeclaration;
import net.sourceforge.pmd.ast.DiscardableNodeCleaner;
import net.sourceforge.pmd.ast.ASTImplementsList;
import net.sourceforge.pmd.ast.ASTAnnotation;
import net.sourceforge.pmd.ast.ASTAnnotationTypeDeclaration;
import net.sourceforge.pmd.PMD;
import test.net.sourceforge.pmd.testframework.ParserTst;
import java.util.List;
public class DiscardableNodeCleanerTest extends ParserTst {
public void testRemoveDiscardNodes() throws Throwable {

View File

@ -1,30 +1,17 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
*/
package test.net.sourceforge.pmd.ast;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.ast.ASTAssignmentOperator;
import net.sourceforge.pmd.ast.ASTBlock;
import net.sourceforge.pmd.ast.ASTBlockStatement;
import net.sourceforge.pmd.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.ast.ASTCompilationUnit;
import net.sourceforge.pmd.ast.ASTEqualityExpression;
import net.sourceforge.pmd.ast.ASTExpression;
import net.sourceforge.pmd.ast.ASTExtendsList;
import net.sourceforge.pmd.ast.ASTFieldDeclaration;
import net.sourceforge.pmd.ast.ASTImplementsList;
import net.sourceforge.pmd.ast.ASTInstanceOfExpression;
import net.sourceforge.pmd.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.ast.ASTName;
import net.sourceforge.pmd.ast.ASTRelationalExpression;
import net.sourceforge.pmd.ast.ASTReturnStatement;
import net.sourceforge.pmd.ast.ASTStatement;
import net.sourceforge.pmd.ast.ASTVariableInitializer;
import net.sourceforge.pmd.ast.Node;
import net.sourceforge.pmd.ast.SimpleNode;
import net.sourceforge.pmd.ast.*;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.w3c.dom.Document;
import test.net.sourceforge.pmd.testframework.ParserTst;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -51,25 +38,25 @@ public class SimpleNodeTest extends ParserTst {
public void testHasExplicitExtends() throws Throwable {
String code = HAS_EXPLICIT_EXTENDS;
ASTClassOrInterfaceDeclaration ucd = (ASTClassOrInterfaceDeclaration)(getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next());
ASTClassOrInterfaceDeclaration ucd = (ASTClassOrInterfaceDeclaration) (getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next());
assertTrue(ucd.jjtGetChild(0) instanceof ASTExtendsList);
}
public void testNoExplicitExtends() throws Throwable {
String code = NO_EXPLICIT_EXTENDS;
ASTClassOrInterfaceDeclaration ucd = (ASTClassOrInterfaceDeclaration)(getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next());
ASTClassOrInterfaceDeclaration ucd = (ASTClassOrInterfaceDeclaration) (getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next());
assertFalse(ucd.jjtGetChild(0) instanceof ASTExtendsList);
}
public void testHasExplicitImplements() throws Throwable {
String code = HAS_EXPLICIT_IMPLEMENTS;
ASTClassOrInterfaceDeclaration ucd = (ASTClassOrInterfaceDeclaration)(getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next());
ASTClassOrInterfaceDeclaration ucd = (ASTClassOrInterfaceDeclaration) (getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next());
assertTrue(ucd.jjtGetChild(0) instanceof ASTImplementsList);
}
public void testNoExplicitImplements() throws Throwable {
String code = NO_EXPLICIT_IMPLEMENTS;
ASTClassOrInterfaceDeclaration ucd = (ASTClassOrInterfaceDeclaration)(getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next());
ASTClassOrInterfaceDeclaration ucd = (ASTClassOrInterfaceDeclaration) (getNodes(ASTClassOrInterfaceDeclaration.class, code).iterator().next());
assertFalse(ucd.jjtGetChild(0) instanceof ASTImplementsList);
}
@ -102,19 +89,19 @@ public class SimpleNodeTest extends ParserTst {
Set blocks = getNodes(ASTBlock.class, LINE_NUMBERS_ON_SIBLINGS);
Iterator i = blocks.iterator();
while (i.hasNext()) {
ASTBlock b = (ASTBlock)i.next();
ASTBlock b = (ASTBlock) i.next();
assertTrue(b.getBeginLine() > 0);
}
blocks = getNodes(ASTVariableInitializer.class, LINE_NUMBERS_ON_SIBLINGS);
i = blocks.iterator();
while (i.hasNext()) {
ASTVariableInitializer b = (ASTVariableInitializer)i.next();
ASTVariableInitializer b = (ASTVariableInitializer) i.next();
assertTrue(b.getBeginLine() > 0);
}
blocks = getNodes(ASTExpression.class, LINE_NUMBERS_ON_SIBLINGS);
i = blocks.iterator();
while (i.hasNext()) {
ASTExpression b = (ASTExpression)i.next();
ASTExpression b = (ASTExpression) i.next();
assertTrue(b.getBeginLine() > 0);
}
}
@ -200,33 +187,47 @@ public class SimpleNodeTest extends ParserTst {
assertEquals(x2, n);
}
public void testAsXml() {
ASTBlock b = new ASTBlock(1);
String x = b.asXml();
assertEquals("<ASTBlock id=\"1\"></ASTBlock>", x);
}
public void testContainsNoInner() throws Throwable {
ASTCompilationUnit c = (ASTCompilationUnit)getNodes(ASTCompilationUnit.class, CONTAINS_NO_INNER).iterator().next();
ASTCompilationUnit c = (ASTCompilationUnit) getNodes(ASTCompilationUnit.class, CONTAINS_NO_INNER).iterator().next();
List res = new ArrayList();
c.findChildrenOfType(ASTFieldDeclaration.class, res, false);
assertTrue(res.isEmpty());
String expectedXml = "<CompilationUnit BeginColumn=\"1\" BeginLine=\"5\" EndColumn=\"1\" EndLine=\"5\">" +
"<TypeDeclaration BeginColumn=\"1\" BeginLine=\"1\" EndColumn=\"1\" EndLine=\"5\">" +
"<ClassOrInterfaceDeclaration Abstract=\"false\" BeginColumn=\"8\" BeginLine=\"1\" EndColumn=\"1\" " +
"EndLine=\"5\" Final=\"false\" Image=\"Test\" Interface=\"false\" Native=\"false\" Nested=\"false\" PackagePrivate=\"false\" Private=\"false\" Protected=\"false\" Public=\"true\" Static=\"false\" Strictfp=\"false\" Synchronized=\"false\" Transient=\"false\" Volatile=\"false\">" +
"<ClassOrInterfaceBody BeginColumn=\"19\" BeginLine=\"1\" EndColumn=\"1\" EndLine=\"5\">" +
"<ClassOrInterfaceBodyDeclaration AnonymousInnerClass=\"false\" BeginColumn=\"3\" BeginLine=\"2\" EndColumn=\"3\" EndLine=\"4\">" +
"<ClassOrInterfaceDeclaration Abstract=\"false\" BeginColumn=\"10\" BeginLine=\"2\" EndColumn=\"3\" EndLine=\"4\" Final=\"false\" " +
"Image=\"Inner\" Interface=\"false\" Native=\"false\" Nested=\"true\" PackagePrivate=\"false\" Private=\"false\" Protected=\"false\" " +
"Public=\"true\" Static=\"false\" Strictfp=\"false\" Synchronized=\"false\" Transient=\"false\" Volatile=\"false\">" +
"<ClassOrInterfaceBody BeginColumn=\"22\" BeginLine=\"2\" EndColumn=\"3\" EndLine=\"4\">" +
"<ClassOrInterfaceBodyDeclaration AnonymousInnerClass=\"false\" BeginColumn=\"4\" BeginLine=\"3\" EndColumn=\"11\" EndLine=\"3\">" +
"<FieldDeclaration Abstract=\"false\" Array=\"false\" ArrayDepth=\"0\" BeginColumn=\"4\" BeginLine=\"3\" EndColumn=\"11\" EndLine=\"3\" Final=\"false\" Native=\"false\" PackagePrivate=\"true\" Private=\"false\" Protected=\"false\" Public=\"false\" Static=\"false\" Strictfp=\"false\" Synchronized=\"false\" Transient=\"false\" VariableName=\"foo\" Volatile=\"false\"><Type Array=\"false\" ArrayDepth=\"0\" BeginColumn=\"4\" BeginLine=\"3\" EndColumn=\"6\" EndLine=\"3\">" +
"<PrimitiveType Array=\"false\" ArrayDepth=\"0\" BeginColumn=\"4\" BeginLine=\"3\" Boolean=\"false\" EndColumn=\"6\" EndLine=\"3\" Image=\"int\"/>" +
"</Type>" +
"<VariableDeclarator BeginColumn=\"8\" BeginLine=\"3\" EndColumn=\"10\" EndLine=\"3\">" +
"<VariableDeclaratorId Array=\"false\" ArrayDepth=\"0\" BeginColumn=\"8\" BeginLine=\"3\" EndColumn=\"10\" EndLine=\"3\" ExceptionBlockParameter=\"false\" Image=\"foo\"/>" +
"</VariableDeclarator></FieldDeclaration></ClassOrInterfaceBodyDeclaration></ClassOrInterfaceBody>" +
"</ClassOrInterfaceDeclaration></ClassOrInterfaceBodyDeclaration></ClassOrInterfaceBody></ClassOrInterfaceDeclaration>" +
"</TypeDeclaration></CompilationUnit>";
assertEquals( expectedXml, getXmlString( c ) );
}
public void testContainsNoInnerWithAnonInner() throws Throwable {
ASTCompilationUnit c = (ASTCompilationUnit)getNodes(ASTCompilationUnit.class, CONTAINS_NO_INNER_WITH_ANON_INNER).iterator().next();
ASTCompilationUnit c = (ASTCompilationUnit) getNodes(ASTCompilationUnit.class, CONTAINS_NO_INNER_WITH_ANON_INNER).iterator().next();
List res = new ArrayList();
c.findChildrenOfType(ASTFieldDeclaration.class, res, false);
assertTrue(res.isEmpty());
}
public void testContainsChildOfType() throws Throwable {
ASTClassOrInterfaceDeclaration c = (ASTClassOrInterfaceDeclaration)getNodes(ASTClassOrInterfaceDeclaration.class, CONTAINS_CHILDREN_OF_TYPE).iterator().next();
ASTClassOrInterfaceDeclaration c = (ASTClassOrInterfaceDeclaration) getNodes(ASTClassOrInterfaceDeclaration.class, CONTAINS_CHILDREN_OF_TYPE).iterator().next();
assertTrue(c.containsChildOfType(ASTFieldDeclaration.class));
}
public void testXPathNodeSelect() throws Throwable {
ASTClassOrInterfaceDeclaration c = (ASTClassOrInterfaceDeclaration)getNodes(ASTClassOrInterfaceDeclaration.class, TEST_XPATH).iterator().next();
ASTClassOrInterfaceDeclaration c = (ASTClassOrInterfaceDeclaration) getNodes(ASTClassOrInterfaceDeclaration.class, TEST_XPATH).iterator().next();
List nodes = c.findChildNodesWithXPath("//FieldDeclaration");
assertEquals(2, nodes.size());
assertTrue(nodes.get(0) instanceof ASTFieldDeclaration);
@ -239,6 +240,25 @@ public class SimpleNodeTest extends ParserTst {
assertEquals("Unexpected ending column:", endCol, node.getEndColumn());
}
/**
* Returns an unformatted xml string (without the declaration)
*
* @param node
* @return
* @throws IOException
*/
private String getXmlString(SimpleNode node) throws IOException {
Document document = node.asXml();
StringWriter writer = new StringWriter();
OutputFormat outputFormat = new OutputFormat("XML", "UTF-8", false);
outputFormat.setOmitXMLDeclaration( true );
XMLSerializer xmlSerializer = new XMLSerializer(writer, outputFormat);
xmlSerializer.asDOMSerializer();
xmlSerializer.serialize(document);
String xmlString = writer.toString();
return xmlString;
}
private static final String HAS_EXPLICIT_EXTENDS =
"public class Test extends Foo {}";

View File

@ -3,15 +3,20 @@ package net.sourceforge.pmd.ast;
import net.sourceforge.pmd.IPositionProvider;
import net.sourceforge.pmd.dfa.IDataFlowNode;
import net.sourceforge.pmd.jaxen.Attribute;
import net.sourceforge.pmd.jaxen.DocumentNavigator;
import net.sourceforge.pmd.symboltable.Scope;
import org.apache.xerces.dom.DocumentImpl;
import org.jaxen.BaseXPath;
import org.jaxen.JaxenException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class SimpleNode implements Node , IPositionProvider {
public class SimpleNode implements Node, IPositionProvider {
protected Node parent;
protected Node[] children;
protected int id;
@ -38,7 +43,7 @@ public class SimpleNode implements Node , IPositionProvider {
public void discardIfNecessary() {
if (discardable) {
SimpleNode parent = (SimpleNode)this.jjtGetParent();
SimpleNode parent = (SimpleNode) this.jjtGetParent();
SimpleNode kid = (SimpleNode) this.jjtGetChild(0);
kid.jjtSetParent(parent);
parent.jjtReplaceChild(this, kid);
@ -187,11 +192,11 @@ public class SimpleNode implements Node , IPositionProvider {
}
if (!descendIntoNestedClasses) {
if (node instanceof ASTClassOrInterfaceDeclaration && ((ASTClassOrInterfaceDeclaration)node).isNested()) {
if (node instanceof ASTClassOrInterfaceDeclaration && ((ASTClassOrInterfaceDeclaration) node).isNested()) {
return;
}
if (node instanceof ASTClassOrInterfaceBodyDeclaration && ((ASTClassOrInterfaceBodyDeclaration)node).isAnonymousInnerClass()) {
if (node instanceof ASTClassOrInterfaceBodyDeclaration && ((ASTClassOrInterfaceBodyDeclaration) node).isAnonymousInnerClass()) {
return;
}
}
@ -278,32 +283,31 @@ public class SimpleNode implements Node , IPositionProvider {
return prefix + toString();
}
/**
*
* @return a String with an XML representation of this node and its children
*/
public String asXml() {
String cn = getClass().getName();
if (cn.indexOf('.') != -1) {
cn = cn.substring(cn.lastIndexOf('.')+1);
public Document asXml() {
Document document = new DocumentImpl();
appendElement(document);
return document;
}
final StringBuffer sb = new StringBuffer();
sb.append('<');
sb.append(cn);
sb.append(" id=\"");
sb.append(id);
sb.append("\">");
if (children!=null) {
for (int i=0;i<children.length;i++) {
sb.append(((SimpleNode) children[i]).asXml());
protected void appendElement(org.w3c.dom.Node parentNode) {
DocumentNavigator docNav = new DocumentNavigator();
Document ownerDocument = parentNode.getOwnerDocument();
if( ownerDocument == null )
{
//If the parentNode is a Document itself, it's ownerDocument is null
ownerDocument = (Document) parentNode;
}
String elementName = docNav.getElementName(this);
Element element = ownerDocument.createElement(elementName);
parentNode.appendChild( element );
for (Iterator iter = docNav.getAttributeAxisIterator(this); iter.hasNext();) {
Attribute attr = (Attribute) iter.next();
element.setAttribute(attr.getName(), attr.getValue());
}
for (Iterator iter = docNav.getChildAxisIterator(this); iter.hasNext();) {
SimpleNode child = (SimpleNode) iter.next();
child.appendElement(element);
}
sb.append("</");
sb.append(cn);
sb.append('>');
return sb.toString();
}
/* Override this method if you want to customize how the node dumps
@ -326,7 +330,7 @@ public class SimpleNode implements Node , IPositionProvider {
/**
*Traverses down the tree to find the first child instance of type childType
* Traverses down the tree to find the first child instance of type childType
*
* @param childType class which you want to find.
* @return Node of type childType. Returns <code>null</code> if none found.
@ -336,13 +340,13 @@ public class SimpleNode implements Node , IPositionProvider {
}
private Node getFirstChildOfType(Class childType, Node node) {
for (int i=0;i<node.jjtGetNumChildren();i++) {
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
Node n = node.jjtGetChild(i);
if (n!=null) {
if (n != null) {
if (n.getClass().equals(childType))
return n;
Node n2 = getFirstChildOfType(childType, n);
if (n2!=null)
if (n2 != null)
return n2;
}
}

View File

@ -45,6 +45,7 @@ public class CodeEditorTextPane extends JTextPane implements HasLines, ActionLis
if (fw != null)
fw.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}

View File

@ -17,6 +17,9 @@ import net.sourceforge.pmd.jaxen.DocumentNavigator;
import org.jaxen.BaseXPath;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.w3c.dom.Document;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import javax.swing.*;
import java.awt.BorderLayout;
@ -32,6 +35,8 @@ import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.StringReader;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.List;
@ -293,10 +298,38 @@ public class Designer implements ClipboardOwner {
private String getXml() {
ASTCompilationUnit cu = createParser().CompilationUnit();
String result;
if (cu!=null) {
return cu.asXml();
try {
result = getXmlString( cu );
} catch (IOException e) {
e.printStackTrace();
result = "Error trying to construct XML representation";
}
return "";
}
else
{
result = "";
}
return result;
}
/**
* Returns an unformatted xml string (without the declaration)
*
* @param node
* @return
* @throws java.io.IOException
*/
private String getXmlString(SimpleNode node) throws IOException {
Document document = node.asXml();
StringWriter writer = new StringWriter();
OutputFormat outputFormat = new OutputFormat("XML", "UTF-8", true);
XMLSerializer xmlSerializer = new XMLSerializer(writer, outputFormat);
xmlSerializer.asDOMSerializer();
xmlSerializer.serialize(document);
String xmlString = writer.toString();
return xmlString;
}
public void lostOwnership(Clipboard clipboard, Transferable contents) {

View File

@ -43,8 +43,8 @@
</subsection>
<subsection name="Contributors">
<ul>
<li>Wim Deblauwe - Coordinated and coded a much nicer asXML() implementation, suggested cleanup of UnusedFormalParameter, Javadoc patch, SystemPrintln bug report, helped get Ant task and CLI squared away with JDK 1.5 params, JDK 1.5-specific bug reports, suggested improvements for ExceptionSignatureDeclaration</li>
<li>Tom Parker - Found missed case in NullAssignment, suggested addition to UnnecessaryBooleanAssertion, suggested splitting up AvoidThrowingCertainExceptionTypes, AvoidInstantiatingObjectsInLoops bug report, AtLeastOneConstructor bug report</li>
<li>Wim Deblauwe - suggested cleanup of UnusedFormalParameter, Javadoc patch, SystemPrintln bug report, helped get Ant task and CLI squared away with JDK 1.5 params, JDK 1.5-specific bug reports, suggested improvements for ExceptionSignatureDeclaration</li>
<li>Glen Cordrey - Reported bug involved JavaCC string handling</li>
<li>Dave Brosius - a couple of nice patches to clean up some string handling inefficiencies, non-static class usages, and unclosed streams/readers - found with Findbugs, I daresay :-)</li>
<li>Oto 'tapik' Buchta - Patched XMLRenderer for UTF8 support</li>