From 3d33badd83277e0d468cbddf37f54e8fd681503f Mon Sep 17 00:00:00 2001 From: Ben Bader Date: Tue, 31 Jul 2018 15:54:05 -0700 Subject: [PATCH] Allow int literals for consts of type double (#195) --- .../ClientThriftTest.thrift | 2 ++ thrifty-integration-tests/build.gradle | 21 ++++++++++++--- .../thrifty/kgen/KotlinCodeGenerator.kt | 2 +- .../com/microsoft/thrifty/schema/Constant.kt | 27 ++++++++++++++++--- .../schema/parser/ConstValueElement.kt | 8 ++++-- .../microsoft/thrifty/schema/LoaderTest.kt | 9 +++++++ .../thrifty/schema/parser/ThriftParserTest.kt | 10 +++++++ 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/thrifty-integration-tests/ClientThriftTest.thrift b/thrifty-integration-tests/ClientThriftTest.thrift index eaee4e3..6aab17c 100644 --- a/thrifty-integration-tests/ClientThriftTest.thrift +++ b/thrifty-integration-tests/ClientThriftTest.thrift @@ -43,6 +43,8 @@ enum Numberz EIGHT = 8 } +const double ActualDouble = 42 + const Numberz myNumberz = Numberz.ONE; // the following is expected to fail: // const Numberz urNumberz = ONE; diff --git a/thrifty-integration-tests/build.gradle b/thrifty-integration-tests/build.gradle index 266a903..a9ad0f7 100644 --- a/thrifty-integration-tests/build.gradle +++ b/thrifty-integration-tests/build.gradle @@ -39,7 +39,7 @@ uploadArchives.enabled = false sourceSets { test { - java.srcDirs += ['build/generated-src/thrifty'] + java.srcDirs += ['build/generated-src/thrifty/java', 'build/generated-src/thrifty/kotlin'] } } @@ -54,19 +54,26 @@ mainClassName = 'com.microsoft.thrifty.compiler.ThriftyCompiler' task compileTestThrift(type: Exec) { def jarTask = project.tasks['shadowJar'] as Jar + inputs.file("$projectDir/ClientThriftTest.thrift") + outputs.dir("$projectDir/build/generated-src/thrifty/java") + dependsOn jarTask executable 'java' - args = ['-jar', jarTask.archivePath.absolutePath, "--out=$projectDir/build/generated-src/thrifty", "$projectDir/ClientThriftTest.thrift"] + args = ['-jar', jarTask.archivePath.absolutePath, "--out=$projectDir/build/generated-src/thrifty/java", "$projectDir/ClientThriftTest.thrift"] } + task kompileTestThrift(type: Exec) { def jarTask = project.tasks['shadowJar'] as Jar + inputs.file("$projectDir/ClientThriftTest.thrift") + outputs.dir("$projectDir/build/generated-src/thrifty/kotlin") + dependsOn jarTask executable 'java' - args = ['-jar', jarTask.archivePath.absolutePath, "--out=$projectDir/build/generated-src/thrifty", "--kotlin", "$projectDir/ClientThriftTest.thrift"] + args = ['-jar', jarTask.archivePath.absolutePath, "--out=$projectDir/build/generated-src/thrifty/kotlin", "--kotlin", "$projectDir/ClientThriftTest.thrift"] } compileTestKotlin { @@ -74,6 +81,14 @@ compileTestKotlin { dependsOn kompileTestThrift } +task cleanTestCode(type: Delete) { + delete "$projectDir/build/generated-src/thrifty" +} + +clean { + dependsOn cleanTestCode +} + compileTestJava { dependsOn compileTestThrift dependsOn kompileTestThrift diff --git a/thrifty-kotlin-codegen/src/main/kotlin/com/microsoft/thrifty/kgen/KotlinCodeGenerator.kt b/thrifty-kotlin-codegen/src/main/kotlin/com/microsoft/thrifty/kgen/KotlinCodeGenerator.kt index a802002..16164a3 100644 --- a/thrifty-kotlin-codegen/src/main/kotlin/com/microsoft/thrifty/kgen/KotlinCodeGenerator.kt +++ b/thrifty-kotlin-codegen/src/main/kotlin/com/microsoft/thrifty/kgen/KotlinCodeGenerator.kt @@ -951,7 +951,7 @@ class KotlinCodeGenerator( } override fun visitDouble(doubleType: BuiltinType) { - if (value.isDouble) { + if (value.isDouble || value.isInt) { block.add("%L", value.getAsDouble()) } else { constOrError("Invalid double constant") diff --git a/thrifty-schema/src/main/kotlin/com/microsoft/thrifty/schema/Constant.kt b/thrifty-schema/src/main/kotlin/com/microsoft/thrifty/schema/Constant.kt index e763c75..3c2b63b 100644 --- a/thrifty-schema/src/main/kotlin/com/microsoft/thrifty/schema/Constant.kt +++ b/thrifty-schema/src/main/kotlin/com/microsoft/thrifty/schema/Constant.kt @@ -106,12 +106,12 @@ class Constant internal constructor ( } private object Validators { - private val BOOL = BoolValidator() + private val BOOL = BoolValidator private val BYTE = IntegerValidator(java.lang.Byte.MIN_VALUE.toLong(), java.lang.Byte.MAX_VALUE.toLong()) private val I16 = IntegerValidator(java.lang.Short.MIN_VALUE.toLong(), java.lang.Short.MAX_VALUE.toLong()) private val I32 = IntegerValidator(Integer.MIN_VALUE.toLong(), Integer.MAX_VALUE.toLong()) private val I64 = IntegerValidator(java.lang.Long.MIN_VALUE, java.lang.Long.MAX_VALUE) - private val DOUBLE = BaseValidator(ConstValueElement.Kind.DOUBLE) + private val DOUBLE = DoubleValidator private val STRING = BaseValidator(ConstValueElement.Kind.STRING) private val ENUM = EnumValidator() @@ -157,7 +157,7 @@ class Constant internal constructor ( } } - private class BoolValidator : ConstValueValidator { + private object BoolValidator : ConstValueValidator { override fun validate(symbolTable: SymbolTable, expected: ThriftType, value: ConstValueElement) { if (value.kind === ConstValueElement.Kind.INTEGER) { val n = value.getAsInt() @@ -221,6 +221,27 @@ class Constant internal constructor ( } } + private object DoubleValidator : ConstValueValidator { + override fun validate(symbolTable: SymbolTable, expected: ThriftType, value: ConstValueElement) { + if (value.isInt || value.isDouble) { + // valid + } else if (value.isIdentifier) { + // maybe a const? + val id = value.value as String + val constant = symbolTable.lookupConst(id) + ?: throw IllegalStateException("Unrecognized const identifier: $id") + + if (constant.type().trueType != expected) { + throw IllegalStateException("Expected a value of type " + expected.name + + ", but got " + constant.type().name) + } + } else { + throw IllegalStateException( + "Expected a value of type DOUBLE but got " + value.value) + } + } + } + private class EnumValidator : ConstValueValidator { override fun validate(symbolTable: SymbolTable, expected: ThriftType, value: ConstValueElement) { if (!expected.isEnum) { diff --git a/thrifty-schema/src/main/kotlin/com/microsoft/thrifty/schema/parser/ConstValueElement.kt b/thrifty-schema/src/main/kotlin/com/microsoft/thrifty/schema/parser/ConstValueElement.kt index 6612727..d63c0e3 100644 --- a/thrifty-schema/src/main/kotlin/com/microsoft/thrifty/schema/parser/ConstValueElement.kt +++ b/thrifty-schema/src/main/kotlin/com/microsoft/thrifty/schema/parser/ConstValueElement.kt @@ -87,8 +87,12 @@ data class ConstValueElement( } fun getAsDouble(): Double { - check(isDouble) { "Cannot convert to double; kind=$kind" } - return value as Double + check(isInt || isDouble) { "Cannot convert to double; kind=$kind" } + return when { + isDouble -> value as Double + isInt -> getAsInt().toDouble() + else -> error("unpossible") + } } fun getAsString(): String { diff --git a/thrifty-schema/src/test/kotlin/com/microsoft/thrifty/schema/LoaderTest.kt b/thrifty-schema/src/test/kotlin/com/microsoft/thrifty/schema/LoaderTest.kt index c0107f6..0757dcc 100644 --- a/thrifty-schema/src/test/kotlin/com/microsoft/thrifty/schema/LoaderTest.kt +++ b/thrifty-schema/src/test/kotlin/com/microsoft/thrifty/schema/LoaderTest.kt @@ -1019,6 +1019,15 @@ class LoaderTest { } } + @Test + fun constDoubleWithIntLiteral() { + val thrift = """ + const double FOO = 2 + """.trimIndent() + + load(thrift) + } + private fun load(thrift: String): Schema { val f = tempDir.newFile() f.writeText(thrift) diff --git a/thrifty-schema/src/test/kotlin/com/microsoft/thrifty/schema/parser/ThriftParserTest.kt b/thrifty-schema/src/test/kotlin/com/microsoft/thrifty/schema/parser/ThriftParserTest.kt index eb3392a..49ec46a 100644 --- a/thrifty-schema/src/test/kotlin/com/microsoft/thrifty/schema/parser/ThriftParserTest.kt +++ b/thrifty-schema/src/test/kotlin/com/microsoft/thrifty/schema/parser/ThriftParserTest.kt @@ -1224,6 +1224,16 @@ class ThriftParserTest { assertThat(documentation, isEmptyString()) } + @Test + fun `double-valued consts can have integer literal values`() { + val thrift = """ + const double foo = 2 + """.trimIndent() + + val constants = parse(thrift).constants + assertThat(constants.single().value.getAsDouble(), equalTo(2.0)) + } + companion object { private val TEST_UUID = UUID.fromString("ecafa042-668a-4403-a6d3-70983866ffbe")