aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Stein <sormuras@gmail.com>2016-01-14 08:16:20 +0100
committerChristian Stein <sormuras@gmail.com>2016-01-17 02:18:38 +0100
commitc810627978b07289c8481d368f501de19c38f598 (patch)
tree904bbbe693ca4c079942feb02cb6edab3be9bd4d /src
parent830751cdd5222d3f0d22e4d7ecc81904faaa73a2 (diff)
downloadjavapoet-c810627978b07289c8481d368f501de19c38f598.tar.gz
Literal conversion clean up.
Character and String literal conversion refactored. Made AnnotationSpec.Builder.addMemberForValue package private. Refactored and fixed bug in AnnotationSpec.get(AnnotationMirror). Removed redundant public modifiers from package private Util methods.
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/squareup/javapoet/AnnotationSpec.java49
-rw-r--r--src/main/java/com/squareup/javapoet/CodeWriter.java51
-rw-r--r--src/main/java/com/squareup/javapoet/Util.java64
-rw-r--r--src/test/java/com/squareup/javapoet/AnnotationSpecTest.java3
-rw-r--r--src/test/java/com/squareup/javapoet/UtilTest.java73
5 files changed, 148 insertions, 92 deletions
diff --git a/src/main/java/com/squareup/javapoet/AnnotationSpec.java b/src/main/java/com/squareup/javapoet/AnnotationSpec.java
index 082e49e..80dd28e 100644
--- a/src/main/java/com/squareup/javapoet/AnnotationSpec.java
+++ b/src/main/java/com/squareup/javapoet/AnnotationSpec.java
@@ -29,6 +29,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
+import static com.squareup.javapoet.Util.characterLiteralWithoutSingleQuotes;
import static com.squareup.javapoet.Util.checkNotNull;
import javax.lang.model.element.AnnotationMirror;
@@ -127,7 +128,7 @@ public final class AnnotationSpec {
}
if (value.getClass().isArray()) {
for (int i = 0; i < Array.getLength(value); i++) {
- builder.addValue(method.getName(), Array.get(value, i));
+ builder.addMemberForValue(method.getName(), Array.get(value, i));
}
continue;
}
@@ -135,7 +136,7 @@ public final class AnnotationSpec {
builder.addMember(method.getName(), "$L", get((Annotation) value));
continue;
}
- builder.addValue(method.getName(), value);
+ builder.addMemberForValue(method.getName(), value);
}
} catch (Exception e) {
throw new RuntimeException("Reflecting " + annotation + " failed!", e);
@@ -150,7 +151,7 @@ public final class AnnotationSpec {
for (ExecutableElement executableElement : annotation.getElementValues().keySet()) {
String name = executableElement.getSimpleName().toString();
AnnotationValue value = annotation.getElementValues().get(executableElement);
- value.accept(visitor, new Entry(name, value));
+ value.accept(visitor, name);
}
return builder.build();
}
@@ -221,7 +222,9 @@ public final class AnnotationSpec {
* depending on the given {@code value} object. Falls back to {@code "$L"} literal format if
* the class of the given {@code value} object is not supported.
*/
- private Builder addValue(String memberName, Object value) {
+ Builder addMemberForValue(String memberName, Object value) {
+ checkNotNull(memberName, "memberName == null");
+ checkNotNull(value, "value == null, constant non-null value expected for %s", memberName);
if (value instanceof Class<?>) {
return addMember(memberName, "$T.class", value);
}
@@ -235,11 +238,7 @@ public final class AnnotationSpec {
return addMember(memberName, "$Lf", value);
}
if (value instanceof Character) {
- String literal = CodeWriter.stringLiteral(value.toString(), "");
- literal = literal.substring(1, literal.length() - 1);
- if (literal.equals("\\\"")) literal = "\"";
- if (literal.equals("'")) literal = "\\'";
- return addMember(memberName, "'$L'", literal);
+ return addMember(memberName, "'$L'", characterLiteralWithoutSingleQuotes((char) value));
}
return addMember(memberName, "$L", value);
}
@@ -249,20 +248,10 @@ public final class AnnotationSpec {
}
}
- private static class Entry {
- final String name;
- final AnnotationValue value;
-
- Entry(String name, AnnotationValue value) {
- this.name = name;
- this.value = value;
- }
- }
-
/**
* Annotation value visitor adding members to the given builder instance.
*/
- private static class Visitor extends SimpleAnnotationValueVisitor7<Builder, Entry> {
+ private static class Visitor extends SimpleAnnotationValueVisitor7<Builder, String> {
final Builder builder;
Visitor(Builder builder) {
@@ -270,25 +259,25 @@ public final class AnnotationSpec {
this.builder = builder;
}
- @Override protected Builder defaultAction(Object o, Entry entry) {
- return builder.addMember(entry.name, "$L", entry.value);
+ @Override protected Builder defaultAction(Object o, String name) {
+ return builder.addMemberForValue(name, o);
}
- @Override public Builder visitAnnotation(AnnotationMirror a, Entry entry) {
- return builder.addMember(entry.name, "$L", get(a));
+ @Override public Builder visitAnnotation(AnnotationMirror a, String name) {
+ return builder.addMember(name, "$L", get(a));
}
- @Override public Builder visitEnumConstant(VariableElement c, Entry entry) {
- return builder.addMember(entry.name, "$T.$L", c.asType(), c.getSimpleName());
+ @Override public Builder visitEnumConstant(VariableElement c, String name) {
+ return builder.addMember(name, "$T.$L", c.asType(), c.getSimpleName());
}
- @Override public Builder visitType(TypeMirror t, Entry entry) {
- return builder.addMember(entry.name, "$T.class", t);
+ @Override public Builder visitType(TypeMirror t, String name) {
+ return builder.addMember(name, "$T.class", t);
}
- @Override public Builder visitArray(List<? extends AnnotationValue> values, Entry entry) {
+ @Override public Builder visitArray(List<? extends AnnotationValue> values, String name) {
for (AnnotationValue value : values) {
- value.accept(this, new Entry(entry.name, value));
+ value.accept(this, name);
}
return builder;
}
diff --git a/src/main/java/com/squareup/javapoet/CodeWriter.java b/src/main/java/com/squareup/javapoet/CodeWriter.java
index af3c906..d44719d 100644
--- a/src/main/java/com/squareup/javapoet/CodeWriter.java
+++ b/src/main/java/com/squareup/javapoet/CodeWriter.java
@@ -19,7 +19,6 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.Formatter;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@@ -35,6 +34,7 @@ import static com.squareup.javapoet.Util.checkArgument;
import static com.squareup.javapoet.Util.checkNotNull;
import static com.squareup.javapoet.Util.checkState;
import static com.squareup.javapoet.Util.join;
+import static com.squareup.javapoet.Util.stringLiteralWithDoubleQuotes;
/**
* Converts a {@link JavaFile} to a string suitable to both human- and javac-consumption. This
@@ -225,7 +225,7 @@ final class CodeWriter {
String string = (String) codeBlock.args.get(a++);
// Emit null as a literal null: no quotes.
emitAndIndent(string != null
- ? stringLiteral(string)
+ ? stringLiteralWithDoubleQuotes(string, indent)
: "null");
break;
@@ -476,51 +476,4 @@ final class CodeWriter {
result.keySet().removeAll(referencedNames);
return result;
}
-
- /** Returns the string literal representing {@code data}, including wrapping quotes. */
- String stringLiteral(String value) {
- return stringLiteral(value, indent);
- }
-
- static String stringLiteral(String value, String indent) {
- StringBuilder result = new StringBuilder();
- result.append('"');
- for (int i = 0; i < value.length(); i++) {
- char c = value.charAt(i);
- switch (c) {
- case '"':
- result.append("\\\"");
- break;
- case '\\':
- result.append("\\\\");
- break;
- case '\b':
- result.append("\\b");
- break;
- case '\t':
- result.append("\\t");
- break;
- case '\n':
- result.append("\\n");
- if (i + 1 < value.length()) {
- result.append("\"\n").append(indent).append(indent).append("+ \"");
- }
- break;
- case '\f':
- result.append("\\f");
- break;
- case '\r':
- result.append("\\r");
- break;
- default:
- if (Character.isISOControl(c)) {
- new Formatter(result).format("\\u%04x", (int) c);
- } else {
- result.append(c);
- }
- }
- }
- result.append('"');
- return result.toString();
- }
}
diff --git a/src/main/java/com/squareup/javapoet/Util.java b/src/main/java/com/squareup/javapoet/Util.java
index 2447739..864598e 100644
--- a/src/main/java/com/squareup/javapoet/Util.java
+++ b/src/main/java/com/squareup/javapoet/Util.java
@@ -15,6 +15,8 @@
*/
package com.squareup.javapoet;
+import static java.lang.Character.isISOControl;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -35,7 +37,7 @@ final class Util {
}
/** Modifier.DEFAULT doesn't exist until Java 8, but we want to run on earlier releases. */
- public static final Modifier DEFAULT;
+ static final Modifier DEFAULT;
static {
Modifier def = null;
try {
@@ -45,7 +47,7 @@ final class Util {
DEFAULT = def;
}
- public static <K, V> Map<K, List<V>> immutableMultimap(Map<K, List<V>> multimap) {
+ static <K, V> Map<K, List<V>> immutableMultimap(Map<K, List<V>> multimap) {
LinkedHashMap<K, List<V>> result = new LinkedHashMap<>();
for (Map.Entry<K, List<V>> entry : multimap.entrySet()) {
if (entry.getValue().isEmpty()) continue;
@@ -54,32 +56,32 @@ final class Util {
return Collections.unmodifiableMap(result);
}
- public static <K, V> Map<K, V> immutableMap(Map<K, V> map) {
+ static <K, V> Map<K, V> immutableMap(Map<K, V> map) {
return Collections.unmodifiableMap(new LinkedHashMap<>(map));
}
- public static void checkArgument(boolean condition, String format, Object... args) {
+ static void checkArgument(boolean condition, String format, Object... args) {
if (!condition) throw new IllegalArgumentException(String.format(format, args));
}
- public static <T> T checkNotNull(T reference, String format, Object... args) {
+ static <T> T checkNotNull(T reference, String format, Object... args) {
if (reference == null) throw new NullPointerException(String.format(format, args));
return reference;
}
- public static void checkState(boolean condition, String format, Object... args) {
+ static void checkState(boolean condition, String format, Object... args) {
if (!condition) throw new IllegalStateException(String.format(format, args));
}
- public static <T> List<T> immutableList(List<T> list) {
+ static <T> List<T> immutableList(List<T> list) {
return Collections.unmodifiableList(new ArrayList<>(list));
}
- public static <T> Set<T> immutableSet(Collection<T> set) {
+ static <T> Set<T> immutableSet(Collection<T> set) {
return Collections.unmodifiableSet(new LinkedHashSet<>(set));
}
- public static String join(String separator, List<String> parts) {
+ static String join(String separator, List<String> parts) {
if (parts.isEmpty()) return "";
StringBuilder result = new StringBuilder();
result.append(parts.get(0));
@@ -89,14 +91,14 @@ final class Util {
return result.toString();
}
- public static <T> Set<T> union(Set<T> a, Set<T> b) {
+ static <T> Set<T> union(Set<T> a, Set<T> b) {
Set<T> result = new LinkedHashSet<>();
result.addAll(a);
result.addAll(b);
return result;
}
- public static void requireExactlyOneOf(Set<Modifier> modifiers, Modifier... mutuallyExclusive) {
+ static void requireExactlyOneOf(Set<Modifier> modifiers, Modifier... mutuallyExclusive) {
int count = 0;
for (Modifier modifier : mutuallyExclusive) {
if (modifier == null && Util.DEFAULT == null) continue; // Skip 'DEFAULT' if it doesn't exist!
@@ -106,7 +108,45 @@ final class Util {
modifiers, Arrays.toString(mutuallyExclusive));
}
- public static boolean hasDefaultModifier(Collection<Modifier> modifiers) {
+ static boolean hasDefaultModifier(Collection<Modifier> modifiers) {
return DEFAULT != null && modifiers.contains(DEFAULT);
}
+
+ static String characterLiteralWithoutSingleQuotes(char c) {
+ // see https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6
+ switch (c) {
+ case '\b': return "\\b"; /* \u0008: backspace (BS) */
+ case '\t': return "\\t"; /* \u0009: horizontal tab (HT) */
+ case '\n': return "\\n"; /* \u000a: linefeed (LF) */
+ case '\f': return "\\f"; /* \u000c: form feed (FF) */
+ case '\r': return "\\r"; /* \u000d: carriage return (CR) */
+ case '\"': return "\""; /* \u0022: double quote (") */
+ case '\'': return "\\'"; /* \u0027: single quote (') */
+ case '\\': return "\\"; /* \u005c: backslash (\) */
+ default:
+ return isISOControl(c) ? String.format("\\u%04x", (int) c) : Character.toString(c);
+ }
+ }
+
+ /** Returns the string literal representing {@code value}, including wrapping double quotes. */
+ static String stringLiteralWithDoubleQuotes(String value, String indent) {
+ StringBuilder result = new StringBuilder(value.length() + 2);
+ result.append('"');
+ for (int i = 0; i < value.length(); i++) {
+ char c = value.charAt(i);
+ // trivial case: single quote must not be escaped
+ if (c == '\'') {
+ result.append("'");
+ continue;
+ }
+ // default case: just let character literal do its work
+ result.append(characterLiteralWithoutSingleQuotes(c));
+ // need to append indent after linefeed?
+ if (c == '\n' && i + 1 < value.length()) {
+ result.append("\"\n").append(indent).append(indent).append("+ \"");
+ }
+ }
+ result.append('"');
+ return result.toString();
+ }
}
diff --git a/src/test/java/com/squareup/javapoet/AnnotationSpecTest.java b/src/test/java/com/squareup/javapoet/AnnotationSpecTest.java
index 6e7f2df..a530111 100644
--- a/src/test/java/com/squareup/javapoet/AnnotationSpecTest.java
+++ b/src/test/java/com/squareup/javapoet/AnnotationSpecTest.java
@@ -62,7 +62,7 @@ public final class AnnotationSpecTest {
double f() default 10.0;
- char[] g() default {0, 0xCAFE, 'z', '€', '"', '\'', '\t', '\n'};
+ char[] g() default {0, 0xCAFE, 'z', '€', 'ℕ', '"', '\'', '\t', '\n'};
boolean h() default true;
@@ -318,6 +318,7 @@ public final class AnnotationSpecTest {
+ " '쫾',\n"
+ " 'z',\n"
+ " '€',\n"
+ + " 'ℕ',\n"
+ " '\"',\n"
+ " '\\'',\n"
+ " '\\t',\n"
diff --git a/src/test/java/com/squareup/javapoet/UtilTest.java b/src/test/java/com/squareup/javapoet/UtilTest.java
new file mode 100644
index 0000000..c80a45b
--- /dev/null
+++ b/src/test/java/com/squareup/javapoet/UtilTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 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 static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class UtilTest {
+ @Test public void characterLiteral() {
+ assertEquals("a", Util.characterLiteralWithoutSingleQuotes('a'));
+ assertEquals("b", Util.characterLiteralWithoutSingleQuotes('b'));
+ assertEquals("c", Util.characterLiteralWithoutSingleQuotes('c'));
+ assertEquals("%", Util.characterLiteralWithoutSingleQuotes('%'));
+ // common escapes
+ assertEquals("\\b", Util.characterLiteralWithoutSingleQuotes('\b'));
+ assertEquals("\\t", Util.characterLiteralWithoutSingleQuotes('\t'));
+ assertEquals("\\n", Util.characterLiteralWithoutSingleQuotes('\n'));
+ assertEquals("\\f", Util.characterLiteralWithoutSingleQuotes('\f'));
+ assertEquals("\\r", Util.characterLiteralWithoutSingleQuotes('\r'));
+ assertEquals("\"", Util.characterLiteralWithoutSingleQuotes('"'));
+ assertEquals("\\'", Util.characterLiteralWithoutSingleQuotes('\''));
+ assertEquals("\\", Util.characterLiteralWithoutSingleQuotes('\\'));
+ // octal escapes
+ assertEquals("\\u0000", Util.characterLiteralWithoutSingleQuotes('\0'));
+ assertEquals("\\u0007", Util.characterLiteralWithoutSingleQuotes('\7'));
+ assertEquals("?", Util.characterLiteralWithoutSingleQuotes('\77'));
+ assertEquals("\\u007f", Util.characterLiteralWithoutSingleQuotes('\177'));
+ assertEquals("¿", Util.characterLiteralWithoutSingleQuotes('\277'));
+ assertEquals("ÿ", Util.characterLiteralWithoutSingleQuotes('\377'));
+ // unicode escapes
+ assertEquals("\\u0000", Util.characterLiteralWithoutSingleQuotes('\u0000'));
+ assertEquals("\\u0001", Util.characterLiteralWithoutSingleQuotes('\u0001'));
+ assertEquals("\\u0002", Util.characterLiteralWithoutSingleQuotes('\u0002'));
+ assertEquals("€", Util.characterLiteralWithoutSingleQuotes('\u20AC'));
+ assertEquals("☃", Util.characterLiteralWithoutSingleQuotes('\u2603'));
+ assertEquals("♠", Util.characterLiteralWithoutSingleQuotes('\u2660'));
+ assertEquals("♣", Util.characterLiteralWithoutSingleQuotes('\u2663'));
+ assertEquals("♥", Util.characterLiteralWithoutSingleQuotes('\u2665'));
+ assertEquals("♦", Util.characterLiteralWithoutSingleQuotes('\u2666'));
+ assertEquals("✵", Util.characterLiteralWithoutSingleQuotes('\u2735'));
+ assertEquals("✺", Util.characterLiteralWithoutSingleQuotes('\u273A'));
+ assertEquals("/", Util.characterLiteralWithoutSingleQuotes('\uFF0F'));
+ }
+
+ @Test public void stringLiteral() {
+ stringLiteral("abc");
+ stringLiteral("♦♥♠♣");
+ stringLiteral("€\\t@\\t$", "€\t@\t$", " ");
+ stringLiteral("abc();\\n\"\n + \"def();", "abc();\ndef();", " ");
+ }
+
+ void stringLiteral(String string) {
+ stringLiteral(string, string, " ");
+ }
+
+ void stringLiteral(String expected, String value, String indent) {
+ assertEquals("\"" + expected + "\"", Util.stringLiteralWithDoubleQuotes(value, indent));
+ }
+}