diff --git a/wire-java-generator/src/main/java/com/squareup/wire/java/JavaGenerator.java b/wire-java-generator/src/main/java/com/squareup/wire/java/JavaGenerator.java index 5c00bd2bfd..d4bc4eedac 100644 --- a/wire-java-generator/src/main/java/com/squareup/wire/java/JavaGenerator.java +++ b/wire-java-generator/src/main/java/com/squareup/wire/java/JavaGenerator.java @@ -58,7 +58,7 @@ import com.squareup.wire.schema.Service; import com.squareup.wire.schema.Type; import java.io.IOException; -import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -1500,14 +1500,10 @@ private CodeBlock fieldInitializer(ProtoType type, Object value) { return CodeBlock.of("$L", value != null ? value : false); } else if (javaType.equals(TypeName.INT.box())) { - return CodeBlock.of("$L", value != null - ? new BigDecimal(String.valueOf(value)).intValue() - : 0); + return CodeBlock.of("$L", valueToInt(value)); } else if (javaType.equals(TypeName.LONG.box())) { - return CodeBlock.of("$LL", value != null - ? Long.toString(new BigDecimal(String.valueOf(value)).longValue()) - : 0L); + return CodeBlock.of("$LL", Long.toString(valueToLong(value))); } else if (javaType.equals(TypeName.FLOAT.box())) { return CodeBlock.of("$Lf", value != null ? String.valueOf(value) : 0f); @@ -1533,4 +1529,30 @@ private CodeBlock fieldInitializer(ProtoType type, Object value) { throw new IllegalStateException(type + " is not an allowed scalar type"); } } + + static int valueToInt(Object value) { + if (value == null) return 0; + + String string = String.valueOf(value); + if (string.startsWith("0x") || string.startsWith("0X")) { + return Integer.valueOf(string.substring("0x".length()), 16); // Hexadecimal. + } else if (string.startsWith("0") && !string.equals("0")) { + throw new IllegalStateException("Octal literal unsupported: " + value); // Octal. + } else { + return new BigInteger(string).intValue(); // Decimal. + } + } + + static long valueToLong(Object value) { + if (value == null) return 0L; + + String string = String.valueOf(value); + if (string.startsWith("0x") || string.startsWith("0X")) { + return Long.valueOf(string.substring("0x".length()), 16); // Hexadecimal. + } else if (string.startsWith("0") && !string.equals("0")) { + throw new IllegalStateException("Octal literal unsupported: " + value); // Octal. + } else { + return new BigInteger(string).longValue(); // Decimal. + } + } } diff --git a/wire-tests/src/test/java/com/squareup/wire/java/JavaGeneratorTest.java b/wire-tests/src/test/java/com/squareup/wire/java/JavaGeneratorTest.java index 58b7e88466..9a9f402c2a 100644 --- a/wire-tests/src/test/java/com/squareup/wire/java/JavaGeneratorTest.java +++ b/wire-tests/src/test/java/com/squareup/wire/java/JavaGeneratorTest.java @@ -24,6 +24,7 @@ import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; public final class JavaGeneratorTest { @Test public void sanitizeJavadocStripsTrailingWhitespace() { @@ -237,4 +238,36 @@ public final class JavaGeneratorTest { assertThat(repoBuilder.generateCode("A", "android")).contains("" + " public abstract static class AbstractBAdapter extends ProtoAdapter {\n"); } + + /** https://github.com/square/wire/issues/655 */ + @Test public void defaultValues() throws IOException { + RepoBuilder repoBuilder = new RepoBuilder() + .add("message.proto", "" + + "message Message {\n" + + " optional int32 a = 1 [default = 10 ];\n" + + " optional int32 b = 2 [default = 0x20 ];\n" + + " optional int64 c = 3 [default = 11 ];\n" + + " optional int64 d = 4 [default = 0x21 ];\n" + + "}\n"); + String code = repoBuilder.generateCode("Message"); + assertThat(code).contains(" public static final Integer DEFAULT_A = 10;"); + assertThat(code).contains(" public static final Integer DEFAULT_B = 32;"); + assertThat(code).contains(" public static final Long DEFAULT_C = 11L;"); + assertThat(code).contains(" public static final Long DEFAULT_D = 33L;"); + } + + @Test public void defaultValuesMustNotBeOctal() throws IOException { + RepoBuilder repoBuilder = new RepoBuilder() + .add("message.proto", "" + + "message Message {\n" + + " optional int32 a = 1 [default = 020 ];\n" + + " optional int64 b = 2 [default = 021 ];\n" + + "}\n"); + try { + repoBuilder.generateCode("Message"); + fail(); + } catch (IllegalStateException expected) { + assertThat(expected).hasMessage("Octal literal unsupported: 020"); + } + } }