Skip to content

Commit

Permalink
fix(pretty-print): the annotation values are now pretty-printed in th…
Browse files Browse the repository at this point in the history
…e original order (#1067)

Closes #1066
  • Loading branch information
surli authored and monperrus committed Dec 21, 2016
1 parent adaa3f5 commit d026cbc
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/main/java/spoon/reflect/declaration/CtAnnotation.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public interface CtAnnotation<A extends Annotation> extends CtExpression<A>, CtS
/**
* Returns this annotation's elements and their values. This is returned in
* the form of a map that associates element names with their corresponding
* values.
* values. If you iterate over the map with entrySet(), the iteration order
* complies with the order of annotation values in the source code.
*
* @return this annotation's element names and their values, or an empty map
* if there are none
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import spoon.reflect.reference.CtTypeParameterReference;
import spoon.reflect.reference.CtTypeReference;
import spoon.reflect.visitor.CtVisitor;
import spoon.support.comparator.CtLineElementComparator;
import spoon.support.reflect.code.CtExpressionImpl;

import java.lang.annotation.Annotation;
Expand All @@ -53,10 +54,13 @@
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

/**
* The implementation for {@link spoon.reflect.declaration.CtAnnotation}.
Expand All @@ -68,7 +72,21 @@ public class CtAnnotationImpl<A extends Annotation> extends CtExpressionImpl<A>

CtTypeReference<A> annotationType;

private Map<String, CtExpression> elementValues = new TreeMap<>();
private Map<String, CtExpression> elementValues = new TreeMap() {
@Override
public Set<Entry<String, CtExpression>> entrySet() {
Set<Entry<String, CtExpression>> result = new TreeSet<Entry<String, CtExpression>>(new Comparator<Entry<String, CtExpression>>() {
final CtLineElementComparator comp = new CtLineElementComparator();
@Override
public int compare(Entry<String, CtExpression> o1, Entry<String, CtExpression> o2) {
return comp.compare(o1.getValue(), o2.getValue());
}
}
);
result.addAll(super.entrySet());
return result;
}
};

public CtAnnotationImpl() {
super();
Expand Down
19 changes: 19 additions & 0 deletions src/test/java/spoon/test/annotation/AnnotationValuesTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package spoon.test.annotation;

import org.junit.Test;
import spoon.Launcher;
import spoon.reflect.code.CtConstructorCall;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtFieldAccess;
Expand Down Expand Up @@ -118,6 +119,24 @@ public void testAnnotateWithEnum() throws Exception {
assertTrue(on(byteOrder).giveMeAnnotationValue("byteOrder").element instanceof CtFieldRead);
}

@Test
public void testAnnotationPrintAnnotation() throws Exception {
Launcher launcher = new Launcher();
launcher.addInputResource("src/test/resources/printer-test/spoon/test/AnnotationSpecTest.java");
launcher.getEnvironment().setNoClasspath(true);
launcher.buildModel();

assertEquals(strCtClassOracle,
launcher.getFactory().Class().getAll().get(0).getElements(new TypeFilter<>(CtClass.class)).get(2).toString());
}

private static final String nl = System.lineSeparator();

private static final String strCtClassOracle = "@com.squareup.javapoet.AnnotationSpecTest.HasDefaultsAnnotation(o = com.squareup.javapoet.AnnotationSpecTest.Breakfast.PANCAKES, p = 1701, f = 11.1, m = { 9 , 8 , 1 }, l = java.lang.Override.class, j = @com.squareup.javapoet.AnnotationSpecTest.AnnotationA" + nl +
", q = @com.squareup.javapoet.AnnotationSpecTest.AnnotationC(value = \"bar\")" + nl +
", r = { java.lang.Float.class , java.lang.Double.class })" + nl +
"public class IsAnnotated {}";

static class Request {
private static Request myself = new Request();
private static CtElement element;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
import spoon.SpoonAPI;
import spoon.reflect.code.CtConstructorCall;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtField;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.ModifierKind;
import spoon.reflect.visitor.filter.AbstractFilter;
import spoon.reflect.visitor.filter.TypeFilter;

import java.util.List;
import java.util.TreeSet;

import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -52,12 +54,14 @@ public void noTreeSetInSpoon() throws Exception {
spoon.addInputResource("src/main/java/");
spoon.buildModel();

assertEquals(0, spoon.getFactory().Package().getRootPackage().getElements(new AbstractFilter<CtConstructorCall>() {
List<CtConstructorCall> treeSetWithoutComparators = spoon.getFactory().Package().getRootPackage().filterChildren(new AbstractFilter<CtConstructorCall>() {
@Override
public boolean matches(CtConstructorCall element) {
return element.getType().getActualClass().equals(TreeSet.class);
};
}).size());
return element.getType().getActualClass().equals(TreeSet.class) && element.getArguments().size() == 0;
}
}).list();

assertEquals(0, treeSetWithoutComparators.size());
}

@Test
Expand Down
104 changes: 104 additions & 0 deletions src/test/resources/printer-test/spoon/test/AnnotationSpecTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.squareup.javapoet;

import com.google.testing.compile.CompilationRule;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.lang.model.element.TypeElement;
import org.junit.Rule;
import org.junit.Test;

import static com.google.common.truth.Truth.assertThat;

public final class AnnotationSpecTest {

@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationA {
}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationB {
}

@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationC {
String value();
}

public enum Breakfast {
WAFFLES, PANCAKES;
public String toString() { return name() + " with cherries!"; };
}

@Retention(RetentionPolicy.RUNTIME)
public @interface HasDefaultsAnnotation {

byte a() default 5;

short b() default 6;

int c() default 7;

long d() default 8;

float e() default 9.0f;

double f() default 10.0;

char[] g() default {0, 0xCAFE, 'z', '€', 'ℕ', '"', '\'', '\t', '\n'};

boolean h() default true;

Breakfast i() default Breakfast.WAFFLES;

AnnotationA j() default @AnnotationA();

String k() default "maple";

Class<? extends Annotation> l() default AnnotationB.class;

int[] m() default {1, 2, 3};

Breakfast[] n() default {Breakfast.WAFFLES, Breakfast.PANCAKES};

Breakfast o();

int p();

AnnotationC q() default @AnnotationC("foo");

Class<? extends Number>[] r() default {Byte.class, Short.class, Integer.class, Long.class};

}

@HasDefaultsAnnotation(
o = Breakfast.PANCAKES,
p = 1701,
f = 11.1,
m = {9, 8, 1},
l = Override.class,
j = @AnnotationA,
q = @AnnotationC("bar"),
r = {Float.class, Double.class})
public class IsAnnotated {
// empty
}

}

0 comments on commit d026cbc

Please sign in to comment.