Home | History | Annotate | Download | only in lexicalpreservation
      1 package com.github.javaparser.printer.lexicalpreservation;
      2 
      3 import com.github.javaparser.GeneratedJavaParserConstants;
      4 import com.github.javaparser.ast.Modifier;
      5 import com.github.javaparser.ast.Node;
      6 import com.github.javaparser.ast.PackageDeclaration;
      7 import com.github.javaparser.ast.body.AnnotationDeclaration;
      8 import com.github.javaparser.ast.body.EnumConstantDeclaration;
      9 import com.github.javaparser.ast.body.EnumDeclaration;
     10 import com.github.javaparser.ast.body.MethodDeclaration;
     11 import com.github.javaparser.ast.comments.JavadocComment;
     12 import com.github.javaparser.ast.expr.*;
     13 import com.github.javaparser.ast.observer.ObservableProperty;
     14 import com.github.javaparser.ast.stmt.BlockStmt;
     15 import com.github.javaparser.ast.stmt.ExpressionStmt;
     16 import com.github.javaparser.ast.stmt.Statement;
     17 import com.github.javaparser.printer.ConcreteSyntaxModel;
     18 import com.github.javaparser.printer.concretesyntaxmodel.CsmElement;
     19 import com.github.javaparser.printer.concretesyntaxmodel.CsmToken;
     20 import org.junit.Test;
     21 
     22 import java.io.IOException;
     23 import java.util.EnumSet;
     24 
     25 import static com.github.javaparser.TokenTypes.eolTokenKind;
     26 import static com.github.javaparser.TokenTypes.spaceTokenKind;
     27 import static org.junit.Assert.assertEquals;
     28 import static org.junit.Assert.assertTrue;
     29 
     30 public class LexicalDifferenceCalculatorTest extends AbstractLexicalPreservingTest {
     31 
     32     @Test
     33     public void compilationUnitExampleOriginal() {
     34         considerCode("class A {}");
     35         CsmElement element = ConcreteSyntaxModel.forClass(cu.getClass());
     36         LexicalDifferenceCalculator.CalculatedSyntaxModel csmOriginal = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, cu);
     37         assertEquals(2, csmOriginal.elements.size());
     38         assertEquals(new LexicalDifferenceCalculator.CsmChild(cu.getType(0)), csmOriginal.elements.get(0));
     39         assertEquals(new CsmToken(eolTokenKind()), csmOriginal.elements.get(1));
     40     }
     41 
     42     @Test
     43     public void compilationUnitExampleWithPackageSet() {
     44         considerCode("class A {}");
     45         CsmElement element = ConcreteSyntaxModel.forClass(cu.getClass());
     46         PackageDeclaration packageDeclaration = new PackageDeclaration(new Name(new Name("foo"), "bar"));
     47         LexicalDifferenceCalculator.CalculatedSyntaxModel csmChanged = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, cu, ObservableProperty.PACKAGE_DECLARATION, null, packageDeclaration);
     48         assertEquals(3, csmChanged.elements.size());
     49         assertEquals(new LexicalDifferenceCalculator.CsmChild(packageDeclaration), csmChanged.elements.get(0));
     50         assertEquals(new LexicalDifferenceCalculator.CsmChild(cu.getType(0)), csmChanged.elements.get(1));
     51         assertEquals(new CsmToken(eolTokenKind()), csmChanged.elements.get(2));
     52     }
     53 
     54     @Test
     55     public void annotationDeclarationModifiersExampleOriginal() throws IOException {
     56         considerExample("AnnotationDeclaration_Example1_original");
     57         AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
     58         CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
     59         LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
     60         csm.removeIndentationElements();
     61         int i = 0;
     62         assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
     63         assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
     64         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
     65         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
     66         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
     67         assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
     68         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
     69         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
     70         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
     71         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
     72         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
     73         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
     74         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
     75         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
     76         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
     77         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
     78         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
     79         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
     80         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
     81         assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
     82         assertEquals(i, csm.elements.size());
     83     }
     84 
     85     @Test
     86     public void annotationDeclarationModifiersExampleModified() throws IOException {
     87         considerExample("AnnotationDeclaration_Example1_original");
     88         AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
     89         CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
     90         LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.MODIFIERS, EnumSet.noneOf(Modifier.class), EnumSet.of(Modifier.PUBLIC));
     91         csm.removeIndentationElements();
     92         int i = 0;
     93         assertEquals(new CsmToken(GeneratedJavaParserConstants.PUBLIC), csm.elements.get(i++));
     94         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
     95         assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
     96         assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
     97         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
     98         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
     99         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    100         assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
    101         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    102         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
    103         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    104         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
    105         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    106         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
    107         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    108         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
    109         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    110         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
    111         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    112         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
    113         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    114         assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
    115         assertEquals(i, csm.elements.size());
    116     }
    117 
    118     @Test
    119     public void annotationDeclarationNameExampleModified() throws IOException {
    120         considerExample("AnnotationDeclaration_Example1_original");
    121         AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
    122         CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
    123         SimpleName newName = new SimpleName("NewName");
    124         LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.NAME,
    125                 annotationDeclaration.getName(), newName);
    126         csm.removeIndentationElements();
    127         int i = 0;
    128         assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
    129         assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
    130         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    131         assertEquals(new LexicalDifferenceCalculator.CsmChild(newName), csm.elements.get(i++));
    132         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    133         assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
    134         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    135         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
    136         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    137         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
    138         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    139         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
    140         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    141         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
    142         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    143         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
    144         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    145         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
    146         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    147         assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
    148         assertEquals(i, csm.elements.size());
    149     }
    150 
    151     @Test
    152     public void annotationDeclaratioJavadocExampleOriginal() throws IOException {
    153         considerExample("AnnotationDeclaration_Example3_original");
    154         AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
    155         CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
    156         LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(element, annotationDeclaration);
    157         csm.removeIndentationElements();
    158         int i = 0;
    159         assertEquals(new CsmToken(GeneratedJavaParserConstants.PUBLIC), csm.elements.get(i++));
    160         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    161         assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
    162         assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
    163         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    164         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
    165         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    166         assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
    167         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    168         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
    169         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    170         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
    171         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    172         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
    173         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    174         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
    175         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    176         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
    177         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    178         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
    179         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    180         assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
    181         assertEquals(i, csm.elements.size());
    182     }
    183 
    184     @Test
    185     public void annotationDeclaratioJavadocExampleAddingJavadoc() throws IOException {
    186         considerExample("AnnotationDeclaration_Example3_original");
    187         AnnotationDeclaration annotationDeclaration = (AnnotationDeclaration)cu.getType(0);
    188         CsmElement element = ConcreteSyntaxModel.forClass(annotationDeclaration.getClass());
    189         JavadocComment comment = new JavadocComment("Cool this annotation!");
    190         LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelAfterPropertyChange(element, annotationDeclaration, ObservableProperty.COMMENT, null, comment);
    191         csm.removeIndentationElements();
    192         int i = 0;
    193         assertEquals(new CsmToken(GeneratedJavaParserConstants.PUBLIC), csm.elements.get(i++));
    194         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    195         assertEquals(new CsmToken(GeneratedJavaParserConstants.AT), csm.elements.get(i++));
    196         assertEquals(new CsmToken(GeneratedJavaParserConstants.INTERFACE), csm.elements.get(i++));
    197         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    198         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getName()), csm.elements.get(i++));
    199         assertEquals(new CsmToken(spaceTokenKind()), csm.elements.get(i++));
    200         assertEquals(new CsmToken(GeneratedJavaParserConstants.LBRACE), csm.elements.get(i++));
    201         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    202         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(0)), csm.elements.get(i++));
    203         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    204         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(1)), csm.elements.get(i++));
    205         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    206         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(2)), csm.elements.get(i++));
    207         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    208         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(3)), csm.elements.get(i++));
    209         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    210         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(4)), csm.elements.get(i++));
    211         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    212         assertEquals(new LexicalDifferenceCalculator.CsmChild(annotationDeclaration.getMember(5)), csm.elements.get(i++));
    213         assertEquals(new CsmToken(eolTokenKind()), csm.elements.get(i++));
    214         assertEquals(new CsmToken(GeneratedJavaParserConstants.RBRACE), csm.elements.get(i++));
    215         assertEquals(i, csm.elements.size());
    216     }
    217 
    218     @Test
    219     public void simpleEnumConstantDeclaration() throws IOException {
    220         EnumConstantDeclaration ecd = considerEcd("A");
    221         LexicalDifferenceCalculator.CalculatedSyntaxModel csm = new LexicalDifferenceCalculator().calculatedSyntaxModelForNode(ecd);
    222 
    223         int i = 0;
    224         assertEquals(new LexicalDifferenceCalculator.CsmChild(ecd.getName()), csm.elements.get(i++));
    225         assertEquals(i, csm.elements.size());
    226     }
    227 
    228     @Test
    229     public void csmModelAfterAddingStatementToEmptyBlock() throws IOException {
    230         LexicalDifferenceCalculator ldc = new LexicalDifferenceCalculator();
    231         considerExample("ASimpleClassWithMoreFormatting_step3");
    232 
    233         MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
    234                 .getMethodsByName("setAField").get(0);
    235         Statement assignStatement = new ExpressionStmt(
    236                 new AssignExpr(
    237                         new FieldAccessExpr(new ThisExpr(),"aField"),
    238                         new NameExpr("aField"),
    239                         AssignExpr.Operator.ASSIGN
    240                 ));
    241         LexicalDifferenceCalculator.CalculatedSyntaxModel calculatedSyntaxModel =
    242                 ldc.calculatedSyntaxModelAfterListAddition(
    243                         ConcreteSyntaxModel.forClass(BlockStmt.class),
    244                         ObservableProperty.STATEMENTS,
    245                         setter.getBody().get().getStatements(),
    246                         0,
    247                         assignStatement);
    248         int index = 0;
    249         assertEquals(CsmElement.token(GeneratedJavaParserConstants.LBRACE), calculatedSyntaxModel.elements.get(index++));
    250         assertEquals(CsmElement.newline(), calculatedSyntaxModel.elements.get(index++));
    251         assertEquals(CsmElement.indent(), calculatedSyntaxModel.elements.get(index++));
    252         assertTrue(isChild(calculatedSyntaxModel.elements.get(index++), ExpressionStmt.class));
    253         assertEquals(CsmElement.newline(), calculatedSyntaxModel.elements.get(index++));
    254         assertEquals(CsmElement.unindent(), calculatedSyntaxModel.elements.get(index++));
    255         assertEquals(CsmElement.token(GeneratedJavaParserConstants.RBRACE), calculatedSyntaxModel.elements.get(index++));
    256         assertEquals(index, calculatedSyntaxModel.elements.size());
    257     }
    258 
    259     @Test
    260     public void differenceAfterddingStatementToEmptyBlock() throws IOException {
    261         LexicalDifferenceCalculator ldc = new LexicalDifferenceCalculator();
    262         considerExample("ASimpleClassWithMoreFormatting_step3");
    263 
    264         MethodDeclaration setter = cu.getClassByName("MyRenamedClass").get()
    265                 .getMethodsByName("setAField").get(0);
    266         Statement assignStatement = new ExpressionStmt(
    267                 new AssignExpr(
    268                         new FieldAccessExpr(new ThisExpr(),"aField"),
    269                         new NameExpr("aField"),
    270                         AssignExpr.Operator.ASSIGN
    271                 ));
    272         Difference diff = ldc.calculateListAdditionDifference(
    273                 ObservableProperty.STATEMENTS,
    274                 setter.getBody().get().getStatements(),
    275                 0,
    276                 assignStatement);
    277         int index = 0;
    278         assertEquals(Difference.DifferenceElement.kept(CsmElement.token(GeneratedJavaParserConstants.LBRACE)), diff.getElements().get(index++));
    279         assertEquals(Difference.DifferenceElement.kept(CsmElement.newline()), diff.getElements().get(index++));
    280         assertEquals(Difference.DifferenceElement.added(CsmElement.indent()), diff.getElements().get(index++));
    281         assertTrue(isAddedChild(diff.getElements().get(index++), ExpressionStmt.class));
    282         assertEquals(Difference.DifferenceElement.added(CsmElement.newline()), diff.getElements().get(index++));
    283         assertEquals(Difference.DifferenceElement.added(CsmElement.unindent()), diff.getElements().get(index++));
    284         assertEquals(Difference.DifferenceElement.kept(CsmElement.token(GeneratedJavaParserConstants.RBRACE)), diff.getElements().get(index++));
    285         assertEquals(index, diff.getElements().size());
    286     }
    287 
    288     private boolean isAddedChild(Difference.DifferenceElement element, Class<? extends Node> childClass) {
    289         return element.isAdded() && isChild(element.getElement(), childClass);
    290     }
    291 
    292     private boolean isChild(CsmElement element, Class<? extends Node> childClass) {
    293         return element instanceof LexicalDifferenceCalculator.CsmChild && childClass.isInstance(((LexicalDifferenceCalculator.CsmChild)element).getChild());
    294     }
    295 
    296     protected EnumConstantDeclaration considerEcd(String code) {
    297         considerCode("enum A { " + code + " }");
    298         return ((EnumDeclaration)cu.getType(0)).getEntries().get(0);
    299     }
    300 }
    301