Repository: SpoonLabs/gumtree-spoon-ast-diff
Pull request #118 (2019-12-04 18:32:57)

option for include/exclude the Comments in the metadata. If included,
comments have as label the comment itself (before it put an empty
string).


Patch:
diff --git a/src/main/java/gumtree/spoon/AstComparator.java b/src/main/java/gumtree/spoon/AstComparator.java
index e9f0761..fe33db2 100644
--- a/src/main/java/gumtree/spoon/AstComparator.java
+++ b/src/main/java/gumtree/spoon/AstComparator.java
@@ -1,6 +1,7 @@
 package gumtree.spoon;
 
 import java.io.File;
+import java.util.Map;
 
 import gumtree.spoon.builder.SpoonGumTreeBuilder;
 import gumtree.spoon.diff.Diff;
@@ -58,15 +59,31 @@ public class AstComparator {
 		// System.setProperty("gumtree.match.bu.size","10");
 		// System.setProperty("gt.bum.szt", "1000");
 	}
+	/**
+	 * By default, comments are ignored
+	 */
+	private boolean includeComments = false;
 
 	public AstComparator() {
 		super();
 	}
 
+	public AstComparator(boolean includeComments) {
+		super();
+		this.includeComments = includeComments;
+	}
+
+	public AstComparator(Map<String, String> configuration) {
+		super();
+		for (String k : configuration.keySet()) {
+			System.setProperty(k, configuration.get(k));
+		}
+	}
+
 	protected Factory createFactory() {
 		Factory factory = new FactoryImpl(new DefaultCoreFactory(), new StandardEnvironment());
 		factory.getEnvironment().setNoClasspath(true);
-		factory.getEnvironment().setCommentEnabled(false);
+		factory.getEnvironment().setCommentEnabled(includeComments);
 		return factory;
 	}
 
diff --git a/src/main/java/gumtree/spoon/builder/LabelFinder.java b/src/main/java/gumtree/spoon/builder/LabelFinder.java
index 603879e..1feffcc 100644
--- a/src/main/java/gumtree/spoon/builder/LabelFinder.java
+++ b/src/main/java/gumtree/spoon/builder/LabelFinder.java
@@ -5,6 +5,7 @@ import spoon.reflect.code.CtAssignment;
 import spoon.reflect.code.CtBinaryOperator;
 import spoon.reflect.code.CtBlock;
 import spoon.reflect.code.CtBreak;
+import spoon.reflect.code.CtComment;
 import spoon.reflect.code.CtConstructorCall;
 import spoon.reflect.code.CtContinue;
 import spoon.reflect.code.CtIf;
@@ -42,9 +43,10 @@ class LabelFinder extends CtInheritanceScanner {
 			CtTypeReference decl = invocation.getExecutable().getDeclaringType();
 			// label =
 			// (decl!=null?decl.getQualifiedName():"")+"#"+invocation.getExecutable().getSignature();
-			//label = (decl != null ? decl.getQualifiedName() : "") + "#" + invocation.getExecutable().getSimpleName();
+			// label = (decl != null ? decl.getQualifiedName() : "") + "#" +
+			// invocation.getExecutable().getSimpleName();
 			label = invocation.getExecutable().getSimpleName();
-			
+
 		}
 	}
 
@@ -137,4 +139,9 @@ class LabelFinder extends CtInheritanceScanner {
 			label = typeAccess.getAccessedType().getQualifiedName();
 		}
 	}
+
+	@Override
+	public void visitCtComment(CtComment comment) {
+		label = comment.getContent();
+	}
 }
diff --git a/src/main/java/gumtree/spoon/builder/TreeScanner.java b/src/main/java/gumtree/spoon/builder/TreeScanner.java
index a0cd23b..7ba4074 100644
--- a/src/main/java/gumtree/spoon/builder/TreeScanner.java
+++ b/src/main/java/gumtree/spoon/builder/TreeScanner.java
@@ -1,7 +1,10 @@
 package gumtree.spoon.builder;
 
+import java.util.Stack;
+
 import com.github.gumtreediff.tree.ITree;
 import com.github.gumtreediff.tree.TreeContext;
+
 import spoon.reflect.code.CtBlock;
 import spoon.reflect.code.CtCase;
 import spoon.reflect.code.CtStatementList;
@@ -10,8 +13,6 @@ import spoon.reflect.path.CtRole;
 import spoon.reflect.reference.CtReference;
 import spoon.reflect.visitor.CtScanner;
 
-import java.util.Stack;
-
 public class TreeScanner extends CtScanner {
 	public static final String NOTYPE = "<notype>";
 	private final TreeContext treeContext;
@@ -75,9 +76,9 @@ public class TreeScanner extends CtScanner {
 			return true;
 		}
 
-        if (element instanceof CtReference && element.getRoleInParent() == CtRole.SUPER_TYPE) {
-            return false;
-        }
+		if (element instanceof CtReference && element.getRoleInParent() == CtRole.SUPER_TYPE) {
+			return false;
+		}
 
 		return element.isImplicit() || element instanceof CtReference;
 	}
@@ -105,11 +106,6 @@ public class TreeScanner extends CtScanner {
 		}
 	}
 
-	private ITree createNode(CtElement element, String label) {
-		String nodeTypeName = getNodeType(element);
-		return createNode(nodeTypeName, element, label);
-	}
-
 	private String getNodeType(CtElement element) {
 		String nodeTypeName = NOTYPE;
 		if (element != null) {


Test patch:
diff --git a/src/test/java/gumtree/spoon/AstComparatorTest.java b/src/test/java/gumtree/spoon/AstComparatorTest.java
index a132156..46c5db8 100644
--- a/src/test/java/gumtree/spoon/AstComparatorTest.java
+++ b/src/test/java/gumtree/spoon/AstComparatorTest.java
@@ -28,6 +28,7 @@ import gumtree.spoon.diff.operations.UpdateOperation;
 import spoon.Launcher;
 import spoon.SpoonModelBuilder;
 import spoon.reflect.code.CtBinaryOperator;
+import spoon.reflect.code.CtComment;
 import spoon.reflect.code.CtConstructorCall;
 import spoon.reflect.code.CtIf;
 import spoon.reflect.code.CtInvocation;
@@ -1089,7 +1090,8 @@ public class AstComparatorTest {
 	@Test
 	public void test_t_225391() throws Exception {
 		AstComparator diff = new AstComparator();
-		// meld src/test/resources/examples/t_225391/left_IndexHTML_1.4.java src/test/resources/examples/t_225391/right_IndexHTML_1.5.java
+		// meld src/test/resources/examples/t_225391/left_IndexHTML_1.4.java
+		// src/test/resources/examples/t_225391/right_IndexHTML_1.5.java
 		File fl = new File("src/test/resources/examples/t_225391/left_IndexHTML_1.4.java");
 		File fr = new File("src/test/resources/examples/t_225391/right_IndexHTML_1.5.java");
 		Diff result = diff.compare(fl, fr);
@@ -1099,7 +1101,8 @@ public class AstComparatorTest {
 		assertEquals(2, actions.size());
 		assertTrue(result.containsOperation(OperationKind.Delete, "Assignment"));
 		assertTrue(result.containsOperation(OperationKind.Insert, "Invocation", "setMaxFieldLength"));
-		//assertTrue(result.containsOperation(OperationKind.Move, "FieldRead", "writer"));
+		// assertTrue(result.containsOperation(OperationKind.Move, "FieldRead",
+		// "writer"));
 	}
 
 	@Test
@@ -1535,7 +1538,8 @@ public class AstComparatorTest {
 
 		assertEquals(1, actions.size());
 		assertTrue(result.containsOperation(OperationKind.Insert, "Parameter", "call"));
-		//assertTrue(result.containsOperation(OperationKind.Update, "SUPER_TYPE", "Callback<T>"));
+		// assertTrue(result.containsOperation(OperationKind.Update, "SUPER_TYPE",
+		// "Callback<T>"));
 	}
 
 	@Test
@@ -1727,7 +1731,8 @@ public class AstComparatorTest {
 		assertEquals(1, actions.size());
 
 		assertTrue(resulta.containsOperation(OperationKind.Insert, "Parameter", "call"));
-		//assertTrue(resulta.containsOperation(OperationKind.Update, "SUPER_TYPE", "Callback<T>"));
+		// assertTrue(resulta.containsOperation(OperationKind.Update, "SUPER_TYPE",
+		// "Callback<T>"));
 
 		DiffImpl idiff = (DiffImpl) resulta;
 
@@ -1788,7 +1793,9 @@ public class AstComparatorTest {
 	@Test
 	public void testD4JLang57() throws Exception {
 		AstComparator diff = new AstComparator();
-		// meld src/test/resources/examples/d4j/Lang_57/LocaleUtils/Lang_57_LocaleUtils_s.java src/test/resources/examples/d4j/Lang_57/LocaleUtils/Lang_57_LocaleUtils_t.java
+		// meld
+		// src/test/resources/examples/d4j/Lang_57/LocaleUtils/Lang_57_LocaleUtils_s.java
+		// src/test/resources/examples/d4j/Lang_57/LocaleUtils/Lang_57_LocaleUtils_t.java
 		File fl = new File("src/test/resources/examples/d4j/Lang_57/LocaleUtils/Lang_57_LocaleUtils_s.java");
 		File fr = new File("src/test/resources/examples/d4j/Lang_57/LocaleUtils/Lang_57_LocaleUtils_t.java");
 
@@ -1813,4 +1820,74 @@ public class AstComparatorTest {
 
 	}
 
+	@Test
+	public void testDiff1Comment() throws Exception {
+		File s = new File("src/test/resources/examples/diffcomment1/1205753_EmbedPooledConnection_0_s.java");
+		File t = new File("src/test/resources/examples/diffcomment1/1205753_EmbedPooledConnection_0_t.java");
+		boolean includeComments = true;
+		AstComparator r = new AstComparator(includeComments);
+		Diff diffOut = r.compare(s, t);
+		System.out.println("Output: " + diffOut);
+		Assert.assertEquals(1, diffOut.getRootOperations().size());
+		Operation op = diffOut.getRootOperations().get(0);
+		Assert.assertTrue(op.getSrcNode().getComments().size() > 0);
+
+		List<Operation> allop = diffOut.getAllOperations();
+		boolean hasComment = false;
+		for (Operation operation : allop) {
+			hasComment = hasComment || (operation.getSrcNode() instanceof CtComment);
+		}
+		assertTrue(hasComment);
+
+	}
+
+	@Test
+	public void testDiff2Comment() throws Exception {
+		File s = new File("src/test/resources/examples/diffcomment2/1205753_EmbedPooledConnection_0_s.java");
+		File t = new File("src/test/resources/examples/diffcomment2/1205753_EmbedPooledConnection_0_t.java");
+		boolean includeComments = true;
+		AstComparator r = new AstComparator(includeComments);
+
+		Diff diffOut = r.compare(s, t);
+		System.out.println("Output: " + diffOut);
+		Assert.assertEquals(1, diffOut.getRootOperations().size());
+		Operation op = diffOut.getRootOperations().get(0);
+		// Assert.assertTrue(op.getSrcNode().getComments().size() > 0);
+
+		List<Operation> allop = diffOut.getAllOperations();
+		boolean hasComment = false;
+		for (Operation operation : allop) {
+			hasComment = hasComment || (operation.getSrcNode() instanceof CtComment);
+		}
+		assertTrue(hasComment);
+
+	}
+
+	@Test
+	public void testDiff3Comment() throws Exception {
+		File s = new File("src/test/resources/examples/diffcomment3/RectangularCholeskyDecomposition_s.java");
+		File t = new File("src/test/resources/examples/diffcomment3/RectangularCholeskyDecomposition_t.java");
+		boolean includeComments = true;
+		AstComparator r = new AstComparator(includeComments);
+
+		Diff diffOut = r.compare(s, t);
+		System.out.println("Output: " + diffOut);
+		Assert.assertEquals(1, diffOut.getRootOperations().size());
+		Operation op = diffOut.getRootOperations().get(0);
+		Assert.assertTrue(op.getSrcNode().getComments().size() > 0);
+
+		assertFalse(op.getSrcNode() instanceof CtComment);
+
+		List<Operation> allop = diffOut.getAllOperations();
+		boolean hasComment = false;
+		for (Operation operation : allop) {
+			if ((operation.getSrcNode() instanceof CtComment)) {
+				hasComment = true;
+				System.out.println(operation.getSrcNode());
+			}
+		}
+		assertTrue(hasComment);
+
+	}
+
 }
diff --git a/src/test/java/gumtree/spoon/TreeTest.java b/src/test/java/gumtree/spoon/TreeTest.java
index ac4db1d..b7cdba7 100644
--- a/src/test/java/gumtree/spoon/TreeTest.java
+++ b/src/test/java/gumtree/spoon/TreeTest.java
@@ -29,6 +29,8 @@ import gumtree.spoon.diff.operations.UpdateOperation;
 import spoon.Launcher;
 import spoon.compiler.SpoonResourceHelper;
 import spoon.reflect.code.CtStatement;
+import spoon.reflect.cu.SourcePosition;
+import spoon.reflect.cu.position.NoSourcePosition;
 import spoon.reflect.declaration.CtElement;
 import spoon.reflect.declaration.CtMethod;
 import spoon.reflect.declaration.CtType;
@@ -190,7 +192,10 @@ public class TreeTest {
 	public void test_JSON_manual_generation_2() throws Exception {
 
 		Launcher spoon = new Launcher();
+
+		spoon.getFactory().getEnvironment().setCommentEnabled(false);
 		Factory factory = spoon.createFactory();
+		factory.getEnvironment().setCommentEnabled(false);
 		spoon.createCompiler(factory,
 				SpoonResourceHelper.resources("src/test/resources/examples/roots/test8/right_QuickNotepad_1.14.java"))
 				.build();
@@ -455,4 +460,55 @@ public class TreeTest {
 		assertEquals("protected", ((CtWrapper) op1.getDstNode()).getValue().toString());
 
 	}
+
+	@Test
+	public void test_bug_Possition() throws Exception {
+		AstComparator comparator = new AstComparator();
+		File fl = new File("src/test/resources/examples/roots/test8/left_QuickNotepad_1.13.java");
+		File fr = new File("src/test/resources/examples/roots/test8/right_QuickNotepad_1.14.java");
+
+		CtType<?> astLeft = comparator.getCtType(fl);
+
+		assertNotNull(astLeft);
+
+		CtType<?> astRight = comparator.getCtType(fr);
+		assertNotNull(astRight);
+
+		Diff diffResult = comparator.compare(astLeft, astRight);
+		List<Operation> rootOperations = diffResult.getRootOperations();
+		getPaths(rootOperations);
+		List<Operation> allOperations = diffResult.getAllOperations();
+		getPaths(allOperations);
+
+		assertEquals(1, rootOperations.size());
+
+		SourcePosition position = rootOperations.get(0).getSrcNode().getPosition();
+		assertTrue(position.getLine() > 0);
+		assertEquals(113, position.getLine());
+
+		assertTrue(!(position instanceof NoSourcePosition));
+
+	}
+
+	@Test
+	public void test_bug_Possition_from_String() {
+		String c1 = "" + "class X {\n" + "public void foo() {\n" + " int x = 0;\n" + "}" + "};";
+
+		String c2 = "" + "class X {\n" + "public void foo() {\n" + " int x = 1;\n" + "}" + "};";
+
+		AstComparator diff = new AstComparator();
+		Diff editScript = diff.compare(c1, c2);
+		assertTrue(editScript.getRootOperations().size() == 1);
+
+		List<Operation> rootOperations = editScript.getRootOperations();
+
+		assertEquals(1, rootOperations.size());
+
+		SourcePosition position = rootOperations.get(0).getSrcNode().getPosition();
+		assertTrue(!(position instanceof NoSourcePosition));
+
+		assertTrue(position.getLine() > 0);
+		assertEquals(3, position.getLine());
+
+	}
 }
diff --git a/src/test/resources/examples/diffcomment1/1205753_EmbedPooledConnection_0_s.java b/src/test/resources/examples/diffcomment1/1205753_EmbedPooledConnection_0_s.java
new file mode 100644
index 0000000..d9e07cb
--- /dev/null
+++ b/src/test/resources/examples/diffcomment1/1205753_EmbedPooledConnection_0_s.java
@@ -0,0 +1,76 @@
+ /*
+ 
+    Derby - Class org.apache.derby.jdbc.EmbedPooledConnection
+ 
+    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 org.apache.derby.jdbc;
+ 
+ import org.apache.derby.iapi.services.sanity.SanityManager;
+ import org.apache.derby.iapi.reference.Property;
+ import org.apache.derby.iapi.error.ExceptionSeverity;
+ import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+ 
+ /* import impl class */
+ import org.apache.derby.impl.jdbc.Util;
+ import org.apache.derby.impl.jdbc.EmbedConnection;
+ import org.apache.derby.iapi.jdbc.BrokeredConnection;
+ import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;
+ import org.apache.derby.iapi.jdbc.EngineConnection;
+ import org.apache.derby.impl.jdbc.EmbedPreparedStatement;
+ import org.apache.derby.impl.jdbc.EmbedCallableStatement;
+ 
+ 
+ import java.sql.Connection;
+ import java.sql.ResultSet;
+ import java.sql.SQLException;
+ import java.sql.Statement;
+ import java.sql.PreparedStatement;
+ import java.sql.CallableStatement;
+ 
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ 
+ /* -- New jdbc 20 extension types --- */
+ import javax.sql.ConnectionEventListener;
+ import javax.sql.ConnectionEvent;
+ 
+ /** 
+ 	A PooledConnection object is a connection object that provides hooks for
+ 	connection pool management.
+ 
+ 	<P>This is Derby's implementation of a PooledConnection for use in
+ 	the following environments:
+ 	<UL>
+ 	<LI> JDBC 3.0 - Java 2 - JDK 1.4, J2SE 5.0
+ 	<LI> JDBC 2.0 - Java 2 - JDK 1.2,1.3
+ 	</UL>
+ 
+  */
+ class EmbedPooledConnection implements javax.sql.PooledConnection, BrokeredConnectionControl
+ {
+     /** the connection string */
+     private String connString;
+ 
+     /**
+      * The list of {@code ConnectionEventListener}s. It is initially {@code
+      * null} and will be initialized lazily when the first listener is added.
+      */
+     private ArrayList eventListener;
+ 
+ }
diff --git a/src/test/resources/examples/diffcomment1/1205753_EmbedPooledConnection_0_t.java b/src/test/resources/examples/diffcomment1/1205753_EmbedPooledConnection_0_t.java
new file mode 100644
index 0000000..b38fea0
--- /dev/null
+++ b/src/test/resources/examples/diffcomment1/1205753_EmbedPooledConnection_0_t.java
@@ -0,0 +1,83 @@
+ /*
+ 
+    Derby - Class org.apache.derby.jdbc.EmbedPooledConnection
+ 
+    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 org.apache.derby.jdbc;
+ 
+ import org.apache.derby.iapi.services.sanity.SanityManager;
+ import org.apache.derby.iapi.reference.Property;
+ import org.apache.derby.iapi.error.ExceptionSeverity;
+ import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+ 
+ /* import impl class */
+ import org.apache.derby.impl.jdbc.Util;
+ import org.apache.derby.impl.jdbc.EmbedConnection;
+ import org.apache.derby.iapi.jdbc.BrokeredConnection;
+ import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;
+ import org.apache.derby.iapi.jdbc.EngineConnection;
+ import org.apache.derby.impl.jdbc.EmbedPreparedStatement;
+ import org.apache.derby.impl.jdbc.EmbedCallableStatement;
+ 
+ 
+ import java.sql.Connection;
+ import java.sql.ResultSet;
+ import java.sql.SQLException;
+ import java.sql.Statement;
+ import java.sql.PreparedStatement;
+ import java.sql.CallableStatement;
+ 
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ 
+ /* -- New jdbc 20 extension types --- */
+ import javax.sql.ConnectionEventListener;
+ import javax.sql.ConnectionEvent;
+ 
+ /** 
+ 	A PooledConnection object is a connection object that provides hooks for
+ 	connection pool management.
+ 
+ 	<P>This is Derby's implementation of a PooledConnection for use in
+ 	the following environments:
+ 	<UL>
+ 	<LI> JDBC 3.0 - Java 2 - JDK 1.4, J2SE 5.0
+ 	<LI> JDBC 2.0 - Java 2 - JDK 1.2,1.3
+ 	</UL>
+ 
+  */
+ class EmbedPooledConnection implements javax.sql.PooledConnection, BrokeredConnectionControl
+ {
+     /** the connection string */
+     private String connString;
+ 
+     /**
+      * The list of {@code ConnectionEventListener}s. It is initially {@code
+      * null} and will be initialized lazily when the first listener is added.
+      */
+     private ArrayList eventListener;
+ 
+     
+     /**
+      * This is another
+      *
+      **/
+     private ArrayList anotherListener;
+     
+ }
diff --git a/src/test/resources/examples/diffcomment2/1205753_EmbedPooledConnection_0_s.java b/src/test/resources/examples/diffcomment2/1205753_EmbedPooledConnection_0_s.java
new file mode 100644
index 0000000..d9e07cb
--- /dev/null
+++ b/src/test/resources/examples/diffcomment2/1205753_EmbedPooledConnection_0_s.java
@@ -0,0 +1,76 @@
+ /*
+ 
+    Derby - Class org.apache.derby.jdbc.EmbedPooledConnection
+ 
+    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 org.apache.derby.jdbc;
+ 
+ import org.apache.derby.iapi.services.sanity.SanityManager;
+ import org.apache.derby.iapi.reference.Property;
+ import org.apache.derby.iapi.error.ExceptionSeverity;
+ import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+ 
+ /* import impl class */
+ import org.apache.derby.impl.jdbc.Util;
+ import org.apache.derby.impl.jdbc.EmbedConnection;
+ import org.apache.derby.iapi.jdbc.BrokeredConnection;
+ import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;
+ import org.apache.derby.iapi.jdbc.EngineConnection;
+ import org.apache.derby.impl.jdbc.EmbedPreparedStatement;
+ import org.apache.derby.impl.jdbc.EmbedCallableStatement;
+ 
+ 
+ import java.sql.Connection;
+ import java.sql.ResultSet;
+ import java.sql.SQLException;
+ import java.sql.Statement;
+ import java.sql.PreparedStatement;
+ import java.sql.CallableStatement;
+ 
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ 
+ /* -- New jdbc 20 extension types --- */
+ import javax.sql.ConnectionEventListener;
+ import javax.sql.ConnectionEvent;
+ 
+ /** 
+ 	A PooledConnection object is a connection object that provides hooks for
+ 	connection pool management.
+ 
+ 	<P>This is Derby's implementation of a PooledConnection for use in
+ 	the following environments:
+ 	<UL>
+ 	<LI> JDBC 3.0 - Java 2 - JDK 1.4, J2SE 5.0
+ 	<LI> JDBC 2.0 - Java 2 - JDK 1.2,1.3
+ 	</UL>
+ 
+  */
+ class EmbedPooledConnection implements javax.sql.PooledConnection, BrokeredConnectionControl
+ {
+     /** the connection string */
+     private String connString;
+ 
+     /**
+      * The list of {@code ConnectionEventListener}s. It is initially {@code
+      * null} and will be initialized lazily when the first listener is added.
+      */
+     private ArrayList eventListener;
+ 
+ }
diff --git a/src/test/resources/examples/diffcomment2/1205753_EmbedPooledConnection_0_t.java b/src/test/resources/examples/diffcomment2/1205753_EmbedPooledConnection_0_t.java
new file mode 100644
index 0000000..cc6f273
--- /dev/null
+++ b/src/test/resources/examples/diffcomment2/1205753_EmbedPooledConnection_0_t.java
@@ -0,0 +1,77 @@
+ /*
+ 
+    Derby - Class org.apache.derby.jdbc.EmbedPooledConnection
+ 
+    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 org.apache.derby.jdbc;
+ 
+ import org.apache.derby.iapi.services.sanity.SanityManager;
+ import org.apache.derby.iapi.reference.Property;
+ import org.apache.derby.iapi.error.ExceptionSeverity;
+ import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
+ 
+ /* import impl class */
+ import org.apache.derby.impl.jdbc.Util;
+ import org.apache.derby.impl.jdbc.EmbedConnection;
+ import org.apache.derby.iapi.jdbc.BrokeredConnection;
+ import org.apache.derby.iapi.jdbc.BrokeredConnectionControl;
+ import org.apache.derby.iapi.jdbc.EngineConnection;
+ import org.apache.derby.impl.jdbc.EmbedPreparedStatement;
+ import org.apache.derby.impl.jdbc.EmbedCallableStatement;
+ 
+ 
+ import java.sql.Connection;
+ import java.sql.ResultSet;
+ import java.sql.SQLException;
+ import java.sql.Statement;
+ import java.sql.PreparedStatement;
+ import java.sql.CallableStatement;
+ 
+ import java.util.ArrayList;
+ import java.util.Iterator;
+ 
+ /* -- New jdbc 20 extension types --- */
+ import javax.sql.ConnectionEventListener;
+ import javax.sql.ConnectionEvent;
+ 
+ /** 
+ 	A PooledConnection object is a connection object that provides hooks for
+ 	connection pool management.
+ 
+ 	<P>This is Derby's implementation of a PooledConnection for use in
+ 	the following environments:
+ 	<UL>
+ 	<LI> JDBC 3.0 - Java 2 - JDK 1.4, J2SE 5.0
+ 	<LI> JDBC 2.0 - Java 2 - JDK 1.2,1.3
+ 	</UL>
+ 
+  */
+ class EmbedPooledConnection implements javax.sql.PooledConnection, BrokeredConnectionControl
+ {
+     /** the connection string */
+     private String connString;
+ 
+     /**
+      * The list of UPDATED commented {@code ConnectionEventListener}s. It is initially {@code
+      * null} and will be initialized lazily when the first listener is added.
+      */
+     private ArrayList eventListener;
+
+     
+ }
diff --git a/src/test/resources/examples/diffcomment3/RectangularCholeskyDecomposition_s.java b/src/test/resources/examples/diffcomment3/RectangularCholeskyDecomposition_s.java
new file mode 100644
index 0000000..676b09e
--- /dev/null
+++ b/src/test/resources/examples/diffcomment3/RectangularCholeskyDecomposition_s.java
@@ -0,0 +1,175 @@
+/*
+ * 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 org.apache.commons.math3.linear;
+
+import org.apache.commons.math3.util.FastMath;
+
+/**
+ * Calculates the rectangular Cholesky decomposition of a matrix.
+ * <p>The rectangular Cholesky decomposition of a real symmetric positive
+ * semidefinite matrix A consists of a rectangular matrix B with the same
+ * number of rows such that: A is almost equal to BB<sup>T</sup>, depending
+ * on a user-defined tolerance. In a sense, this is the square root of A.</p>
+ * <p>The difference with respect to the regular {@link CholeskyDecomposition}
+ * is that rows/columns may be permuted (hence the rectangular shape instead
+ * of the traditional triangular shape) and there is a threshold to ignore
+ * small diagonal elements. This is used for example to generate {@link
+ * org.apache.commons.math3.random.CorrelatedRandomVectorGenerator correlated
+ * random n-dimensions vectors} in a p-dimension subspace (p < n).
+ * In other words, it allows generating random vectors from a covariance
+ * matrix that is only positive semidefinite, and not positive definite.</p>
+ * <p>Rectangular Cholesky decomposition is <em>not</em> suited for solving
+ * linear systems, so it does not provide any {@link DecompositionSolver
+ * decomposition solver}.</p>
+ *
+ * @see <a href="http://mathworld.wolfram.com/CholeskyDecomposition.html">MathWorld</a>
+ * @see <a href="http://en.wikipedia.org/wiki/Cholesky_decomposition">Wikipedia</a>
+ * @version $Id$
+ * @since 2.0 (changed to concrete class in 3.0)
+ */
+public class RectangularCholeskyDecomposition {
+
+    /** Permutated Cholesky root of the symmetric positive semidefinite matrix. */
+    private final RealMatrix root;
+
+    /** Rank of the symmetric positive semidefinite matrix. */
+    private int rank;
+
+    /**
+     * Decompose a symmetric positive semidefinite matrix.
+     *
+     * @param matrix Symmetric positive semidefinite matrix.
+     * @param small Diagonal elements threshold under which  column are
+     * considered to be dependent on previous ones and are discarded.
+     * @exception NonPositiveDefiniteMatrixException if the matrix is not
+     * positive semidefinite.
+     */
+    public RectangularCholeskyDecomposition(RealMatrix matrix, double small)
+        throws NonPositiveDefiniteMatrixException {
+
+        final int order = matrix.getRowDimension();
+        final double[][] c = matrix.getData();
+        final double[][] b = new double[order][order];
+
+        int[] swap  = new int[order];
+        int[] index = new int[order];
+        for (int i = 0; i < order; ++i) {
+            index[i] = i;
+        }
+
+        int r = 0;
+        for (boolean loop = true; loop;) {
+
+            // find maximal diagonal element
+            swap[r] = r;
+            for (int i = r + 1; i < order; ++i) {
+                int ii  = index[i];
+                int isi = index[swap[i]];
+                if (c[ii][ii] > c[isi][isi]) {
+                    swap[r] = i;
+                }
+            }
+
+
+            // swap elements
+            if (swap[r] != r) {
+                int tmp = index[r];
+                index[r] = index[swap[r]];
+                index[swap[r]] = tmp;
+            }
+
+            // check diagonal element
+            int ir = index[r];
+            if (c[ir][ir] < ir) {
+
+                if (r == 0) {
+                    throw new NonPositiveDefiniteMatrixException(c[ir][ir], 3.0d, small);
+                }
+
+                // check remaining diagonal elements
+                for (int i = r; i < order; ++i) {
+                    if (c[index[i]][index[i]] < -small) {
+                        // there is at least one sufficiently negative diagonal element,
+                        // the symmetric positive semidefinite matrix is wrong
+                        throw new NonPositiveDefiniteMatrixException(c[index[i]][index[i]], i, small);
+                    }
+                }
+
+                // all remaining diagonal elements are close to zero, we consider we have
+                // found the rank of the symmetric positive semidefinite matrix
+                ++r;
+                if(r>0)
+                	loop = false;
+
+            } else {
+
+                // transform the matrix
+                final double sqrt = FastMath.sqrt(c[ir][ir]);
+                b[r][r] = sqrt;
+                final double inverse  = 1 / sqrt;
+                for (int i = r + 1; i < order; ++i) {
+                    final int ii = index[i];
+                    final double e = inverse * c[ii][ir];
+                    b[i][r] = e;
+                    c[ii][ii] -= e * e;
+                    for (int j = r + 1; j < i; ++j) {
+                        final int ij = index[j];
+                        final double f = c[ii][ij] - e * b[j][r];
+                        c[ii][ij] = f;
+                        c[ij][ii] = f;
+                    }
+                }
+
+                // prepare next iteration
+                loop = ++r < order;
+            }
+        }
+
+        // build the root matrix
+        rank = r;
+        root = MatrixUtils.createRealMatrix(order, r);
+        for (int i = 0; i < order; ++i) {
+            for (int j = 0; j < r; ++j) {
+                root.setEntry(index[i], j, b[i][j]);
+            }
+        }
+
+    }
+
+    /** Get the root of the covariance matrix.
+     * The root is the rectangular matrix <code>B</code> such that
+     * the covariance matrix is equal to <code>B.B<sup>T</sup></code>
+     * @return root of the square matrix
+     * @see #getRank()
+     */
+    public RealMatrix getRootMatrix() {
+        return root;
+    }
+
+    /** Get the rank of the symmetric positive semidefinite matrix.
+     * The r is the number of independent rows in the symmetric positive semidefinite
+     * matrix, it is also the number of columns of the rectangular
+     * matrix of the decomposition.
+     * @return r of the square matrix.
+     * @see #getRootMatrix()
+     */
+    public int getRank() {
+        return rank;
+    }
+
+}
diff --git a/src/test/resources/examples/diffcomment3/RectangularCholeskyDecomposition_t.java b/src/test/resources/examples/diffcomment3/RectangularCholeskyDecomposition_t.java
new file mode 100644
index 0000000..ff91d8c
--- /dev/null
+++ b/src/test/resources/examples/diffcomment3/RectangularCholeskyDecomposition_t.java
@@ -0,0 +1,177 @@
+/*
+ * 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 org.apache.commons.math3.linear;
+
+import org.apache.commons.math3.util.FastMath;
+
+/**
+ * Calculates the rectangular Cholesky decomposition of a matrix.
+ * <p>The rectangular Cholesky decomposition of a real symmetric positive
+ * semidefinite matrix A consists of a rectangular matrix B with the same
+ * number of rows such that: A is almost equal to BB<sup>T</sup>, depending
+ * on a user-defined tolerance. In a sense, this is the square root of A.</p>
+ * <p>The difference with respect to the regular {@link CholeskyDecomposition}
+ * is that rows/columns may be permuted (hence the rectangular shape instead
+ * of the traditional triangular shape) and there is a threshold to ignore
+ * small diagonal elements. This is used for example to generate {@link
+ * org.apache.commons.math3.random.CorrelatedRandomVectorGenerator correlated
+ * random n-dimensions vectors} in a p-dimension subspace (p < n).
+ * In other words, it allows generating random vectors from a covariance
+ * matrix that is only positive semidefinite, and not positive definite.</p>
+ * <p>Rectangular Cholesky decomposition is <em>not</em> suited for solving
+ * linear systems, so it does not provide any {@link DecompositionSolver
+ * decomposition solver}.</p>
+ *
+ * @see <a href="http://mathworld.wolfram.com/CholeskyDecomposition.html">MathWorld</a>
+ * @see <a href="http://en.wikipedia.org/wiki/Cholesky_decomposition">Wikipedia</a>
+ * @version $Id$
+ * @since 2.0 (changed to concrete class in 3.0)
+ */
+public class RectangularCholeskyDecomposition {
+
+    /** Permutated Cholesky root of the symmetric positive semidefinite matrix. */
+    private final RealMatrix root;
+
+    /** Rank of the symmetric positive semidefinite matrix. */
+    private int rank;
+
+    /**
+     * Decompose a symmetric positive semidefinite matrix.
+     *
+     * @param matrix Symmetric positive semidefinite matrix.
+     * @param small Diagonal elements threshold under which  column are
+     * considered to be dependent on previous ones and are discarded.
+     * @exception NonPositiveDefiniteMatrixException if the matrix is not
+     * positive semidefinite.
+     */
+    public RectangularCholeskyDecomposition(RealMatrix matrix, double small)
+        throws NonPositiveDefiniteMatrixException {
+
+        final int order = matrix.getRowDimension();
+        final double[][] c = matrix.getData();
+        final double[][] b = new double[order][order];
+
+        int[] swap  = new int[order];
+        int[] index = new int[order];
+        for (int i = 0; i < order; ++i) {
+            index[i] = i;
+        }
+
+        int r = 0;
+        for (boolean loop = true; loop;) {
+
+            // find maximal diagonal element
+            swap[r] = r;
+            for (int i = r + 1; i < order; ++i) {
+                int ii  = index[i];
+                int isi = index[swap[i]];
+                if (c[ii][ii] > c[isi][isi]) {
+                    swap[r] = i;
+                }
+            }
+
+
+            // swap elements
+            if (swap[r] != r) {
+                int tmp = index[r];
+                index[r] = index[swap[r]];
+                index[swap[r]] = tmp;
+            }
+
+            // check diagonal element
+            int ir = index[r];
+            if (c[ir][ir] < ir) {
+
+                if (r == 0) {
+                    throw new NonPositiveDefiniteMatrixException(c[ir][ir], 3.0d, small);
+                }
+
+                // check remaining diagonal elements
+                for (int i = r; i < order; ++i) {
+                    if (c[index[i]][index[i]] < -small) {
+                        // there is at least one sufficiently negative diagonal element,
+                        // the symmetric positive semidefinite matrix is wrong
+                        throw new NonPositiveDefiniteMatrixException(c[index[i]][index[i]], i, small);
+                    }
+                }
+
+                // all remaining diagonal elements are close to zero, we consider we have
+                // found the rank of the symmetric positive semidefinite matrix
+                ++r;
+                if(r>0)
+                	loop = false;
+
+            } else {
+
+                // transform the matrix
+                final double sqrt = FastMath.sqrt(c[ir][ir]);
+                b[r][r] = sqrt;
+                final double inverse  = 1 / sqrt;
+                for (int i = r + 1; i < order; ++i) {
+                    final int ii = index[i];
+                    final double e = inverse * c[ii][ir];
+                    b[i][r] = e;
+                    c[ii][ii] -= e * e;
+                    for (int j = r + 1; j < i; ++j) {
+                        final int ij = index[j];
+                        final double f = c[ii][ij] - e * b[j][r];
+                        c[ii][ij] = f;
+                        c[ij][ii] = f;
+                    }
+                }
+
+                // prepare next iteration
+                loop = ++r < order;
+            }
+        }
+
+        // build the root matrix
+        rank = r;
+        root = MatrixUtils.createRealMatrix(order, r);
+        for (int i = 0; i < order; ++i) {
+            for (int j = 0; j < r; ++j) {
+                root.setEntry(index[i], j, b[i][j]);
+            }
+        }
+
+    }
+
+    /** Get the root of the covariance matrix.
+     * The root is the rectangular matrix <code>B</code> such that
+     * the covariance matrix is equal to <code>B.B<sup>T</sup></code>
+     * @return root of the square matrix
+     * @see #getRank()
+     */
+    public RealMatrix getRootMatrix() {
+    	//See output
+    	System.out.println("Test");
+        return root;
+    }
+
+    /** Get the rank of the symmetric positive semidefinite matrix.
+     * The r is the number of independent rows in the symmetric positive semidefinite
+     * matrix, it is also the number of columns of the rectangular
+     * matrix of the decomposition.
+     * @return r of the square matrix.
+     * @see #getRootMatrix()
+     */
+    public int getRank() {
+        return rank;
+    }
+
+}
diff --git a/src/test/resources/examples/spoon.json b/src/test/resources/examples/spoon.json
index a0df3b7..34e83bb 100644
--- a/src/test/resources/examples/spoon.json
+++ b/src/test/resources/examples/spoon.json
@@ -62,11 +62,6 @@
               "label": "6412255692894321789L",
               "type": "Literal",
               "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -934,32 +929,6 @@
                   "children": []
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "JavaDoc",
-              "children": [
-                {
-                  "label": "",
-                  "type": "JavaDocTag",
-                  "children": []
-                },
-                {
-                  "label": "",
-                  "type": "JavaDocTag",
-                  "children": []
-                }
-              ]
             }
           ]
         },
@@ -999,21 +968,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -1053,16 +1007,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -1135,21 +1079,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -1440,16 +1369,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -1505,26 +1424,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -1591,16 +1490,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -1835,21 +1724,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -2071,16 +1945,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -2171,16 +2035,6 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
             }
           ]
         },
@@ -2613,48 +2467,8 @@
                   ]
                 }
               ]
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "Comment",
-              "children": []
-            },
-            {
-              "label": "",
-              "type": "JavaDoc",
-              "children": []
             }
           ]
-        },
-        {
-          "label": "",
-          "type": "Comment",
-          "children": []
-        },
-        {
-          "label": "",
-          "type": "Comment",
-          "children": []
-        },
-        {
-          "label": "",
-          "type": "JavaDoc",
-          "children": []
-        },
-        {
-          "label": "",
-          "type": "Comment",
-          "children": []
-        },
-        {
-          "label": "",
-          "type": "Comment",
-          "children": []
         }
       ]
     }