Skip to content

Commit

Permalink
Merge 26922ae into f19bb67
Browse files Browse the repository at this point in the history
  • Loading branch information
jlerbsc authored Nov 7, 2020
2 parents f19bb67 + 26922ae commit d32d621
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2007-2010 Júlio Vilmar Gesser.
* Copyright (C) 2011, 2013-2019 The JavaParser Team.
*
* This file is part of JavaParser.
*
* JavaParser can be used either under the terms of
* a) the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* b) the terms of the Apache License
*
* You should have received a copy of both licenses in LICENCE.LGPL and
* LICENCE.APACHE. Please refer to those files for details.
*
* JavaParser is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

package com.github.javaparser.printer.lexicalpreservation;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.List;

import org.junit.jupiter.api.Test;

import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.stmt.ExpressionStmt;

public class Issue2290Test extends AbstractLexicalPreservingTest {

@Test
public void test() {

ParserConfiguration config = new ParserConfiguration()
.setLexicalPreservationEnabled(true)
.setStoreTokens(true);
StaticJavaParser.setConfiguration(config);

String s =
"public class Clone1 {\n" +
" public static void main(String[] args) {\n" +
" System.out.println(\"I'm a clone10\");\n" +
" System.out.println(\"I'm not a clone!\");\n" +
" System.out.println(\"I'm a clone10\");\n" +
" }\n" +
"}";
CompilationUnit cu = StaticJavaParser.parse(s);
List<ExpressionStmt> exprs = cu.findAll(ExpressionStmt.class);
ExpressionStmt es = exprs.get(exprs.size()-1);
es.getParentNode().get().remove(es);
exprs = cu.findAll(ExpressionStmt.class);
// verify that one statement is removed
assertTrue(exprs.size()==2);
// verify that the first statement is not removed
assertEquals("System.out.println(\"I'm a clone10\");",exprs.get(0).toString());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,48 @@

package com.github.javaparser.printer.lexicalpreservation;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.VariableDeclarator;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.printer.concretesyntaxmodel.*;
import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
import com.github.javaparser.printer.concretesyntaxmodel.CsmIndent;
import com.github.javaparser.printer.concretesyntaxmodel.CsmMix;
import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
import com.github.javaparser.printer.concretesyntaxmodel.CsmUnindent;
import com.github.javaparser.printer.lexicalpreservation.LexicalDifferenceCalculator.CsmChild;

import java.util.*;

class DifferenceElementCalculator {

// internally keep track of a node position in a List<CsmElement>
public static class ChildPositionInfo {
Node node;
Integer position;
ChildPositionInfo(Node node, Integer position) {
this.node = node;
this.position = position;
}
@Override
public boolean equals(Object other) {
if ( other == null || !(other instanceof ChildPositionInfo))
return false;
ChildPositionInfo cpi = (ChildPositionInfo)other;
// verify that the node content and the position are equal
// because we can have nodes with the same content but in different lines
// in this case we consider that nodes are not equals
return this.node.equals(cpi.node)
&& this.node.getRange().isPresent() && cpi.node.getRange().isPresent()
&& this.node.getRange().get().contains(cpi.node.getRange().get());
}
@Override
public int hashCode() {
return node.hashCode() + position.hashCode();
}
}

static boolean matching(CsmElement a, CsmElement b) {
if (a instanceof CsmChild) {
if (b instanceof CsmChild) {
Expand Down Expand Up @@ -100,12 +133,12 @@ private static boolean replacement(CsmElement a, CsmElement b) {
/**
* Find the positions of all the given children.
*/
private static Map<Node, Integer> findChildrenPositions(LexicalDifferenceCalculator.CalculatedSyntaxModel calculatedSyntaxModel) {
Map<Node, Integer> positions = new HashMap<>();
private static List<ChildPositionInfo> findChildrenPositions(LexicalDifferenceCalculator.CalculatedSyntaxModel calculatedSyntaxModel) {
List<ChildPositionInfo> positions = new ArrayList<>();
for (int i=0;i<calculatedSyntaxModel.elements.size();i++) {
CsmElement element = calculatedSyntaxModel.elements.get(i);
if (element instanceof CsmChild) {
positions.put(((CsmChild)element).getChild(), i);
positions.add(new ChildPositionInfo(((CsmChild)element).getChild(), i));
}
}
return positions;
Expand All @@ -128,26 +161,28 @@ static List<DifferenceElement> calculate(LexicalDifferenceCalculator.CalculatedS
// We would calculate the Difference between "qwerty" and "qwer" then we know the A is kept, and then we
// would calculate the difference between "uiop" and "uiop"

Map<Node, Integer> childrenInOriginal = findChildrenPositions(original);
Map<Node, Integer> childrenInAfter = findChildrenPositions(after);
List<ChildPositionInfo> childrenInOriginal = findChildrenPositions(original);
List<ChildPositionInfo> childrenInAfter = findChildrenPositions(after);

List<Node> commonChildren = new LinkedList<>(childrenInOriginal.keySet());
commonChildren.retainAll(childrenInAfter.keySet());
commonChildren.sort(Comparator.comparingInt(childrenInOriginal::get));
List<ChildPositionInfo> commonChildren = new ArrayList<>(childrenInOriginal);
commonChildren.retainAll(childrenInAfter);

List<DifferenceElement> elements = new LinkedList<>();

int originalIndex = 0;
int afterIndex = 0;
int commonChildrenIndex = 0;
while (commonChildrenIndex < commonChildren.size()) {
Node child = commonChildren.get(commonChildrenIndex++);
int posOfNextChildInOriginal = childrenInOriginal.get(child);
int posOfNextChildInAfter = childrenInAfter.get(child);
ChildPositionInfo child = commonChildren.get(commonChildrenIndex++);
// search the position of the node "child" in the original list of cms element
int posOfNextChildInOriginal = childrenInOriginal.stream().filter(i->i.equals(child)).map(i->i.position).findFirst().get();
// search the position of the node "child" in the modified list of cms element
int posOfNextChildInAfter = childrenInAfter.stream().filter(i->i.equals(child)).map(i->i.position).findFirst().get();

if (originalIndex < posOfNextChildInOriginal || afterIndex < posOfNextChildInAfter) {
elements.addAll(calculateImpl(original.sub(originalIndex, posOfNextChildInOriginal), after.sub(afterIndex, posOfNextChildInAfter)));
}
elements.add(new Kept(new CsmChild(child)));
elements.add(new Kept(new CsmChild(child.node)));
originalIndex = posOfNextChildInOriginal + 1;
afterIndex = posOfNextChildInAfter + 1;
}
Expand Down

0 comments on commit d32d621

Please sign in to comment.