From eedb63d655357db2acfe9e232fa8aecdd2c6d96d Mon Sep 17 00:00:00 2001 From: Googler Date: Tue, 17 Dec 2024 07:21:26 -0800 Subject: [PATCH] [J2KT] Add `Source.emptyIf()` and use it in places where double negation occurs. PiperOrigin-RevId: 707089461 --- .../backend/kotlin/ExpressionRenderer.kt | 2 +- .../backend/kotlin/JsInteropAnnotationRenderer.kt | 5 +++-- .../transpiler/backend/kotlin/MemberRenderer.kt | 10 +++++----- .../backend/kotlin/TypeDescriptorRenderer.kt | 2 +- .../transpiler/backend/kotlin/source/Source.kt | 14 ++++++++++---- .../transpiler/backend/kotlin/source/SourceTest.kt | 8 +++++++- 6 files changed, 27 insertions(+), 14 deletions(-) diff --git a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/ExpressionRenderer.kt b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/ExpressionRenderer.kt index 6c7f40a45e..10e3c07f83 100644 --- a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/ExpressionRenderer.kt +++ b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/ExpressionRenderer.kt @@ -508,7 +508,7 @@ internal data class ExpressionRenderer( dotSeparated( qualifierSource(expression), spaceSeparated( - Source.emptyUnless(expression.anonymousInnerClass != null) { + Source.emptyIf(expression.anonymousInnerClass == null) { spaceSeparated(OBJECT_KEYWORD, COLON) }, join( diff --git a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/JsInteropAnnotationRenderer.kt b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/JsInteropAnnotationRenderer.kt index 0ba9aaa18f..83b9a3a4fc 100644 --- a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/JsInteropAnnotationRenderer.kt +++ b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/JsInteropAnnotationRenderer.kt @@ -29,6 +29,7 @@ import com.google.j2cl.transpiler.backend.kotlin.KotlinSource.assignment import com.google.j2cl.transpiler.backend.kotlin.KotlinSource.literal import com.google.j2cl.transpiler.backend.kotlin.source.Source import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.dotSeparated +import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.emptyIf import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.emptyUnless import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.newLineSeparated import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.source @@ -189,7 +190,7 @@ internal data class JsInteropAnnotationRenderer(val nameRenderer: NameRenderer) companion object { private fun nameParameterSource(typeDeclaration: TypeDeclaration): Source = - emptyUnless(typeDeclaration.simpleJsName != typeDeclaration.simpleSourceName) { + emptyIf(typeDeclaration.simpleJsName == typeDeclaration.simpleSourceName) { nameParameterSource(typeDeclaration.simpleJsName) } @@ -203,7 +204,7 @@ internal data class JsInteropAnnotationRenderer(val nameRenderer: NameRenderer) name: String, value: Boolean, defaultValue: Boolean, - ): Source = emptyUnless(value != defaultValue) { assignment(source(name), literal(value)) } + ): Source = emptyIf(value == defaultValue) { assignment(source(name), literal(value)) } private val MethodDescriptor.hasJsConstructorAnnotation get() = originalJsInfo.hasJsMemberAnnotation && isJsConstructor diff --git a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/MemberRenderer.kt b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/MemberRenderer.kt index d72c7db2fb..48b10088ac 100644 --- a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/MemberRenderer.kt +++ b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/MemberRenderer.kt @@ -122,9 +122,9 @@ internal data class MemberRenderer(val nameRenderer: NameRenderer, val enclosing Source.emptyUnless(!isKtPrimaryConstructor(method) || statements.isNotEmpty()) { spaceSeparated( methodHeaderSource(method), - Source.emptyUnless(!method.isAbstract && !method.isNative) { + Source.emptyIf(method.isAbstract || method.isNative) { // Constructors with no statements can be rendered without curly braces. - Source.emptyUnless(!method.isConstructor || statements.isNotEmpty()) { + Source.emptyIf(method.isConstructor && statements.isEmpty()) { spaceSeparated( Source.emptyUnless(method.descriptor.isKtProperty) { join(GET_KEYWORD, inParentheses(Source.EMPTY)) @@ -219,7 +219,7 @@ internal data class MemberRenderer(val nameRenderer: NameRenderer, val enclosing private fun methodModifiersSource(method: Method): Source = spaceSeparated( memberDescriptorRenderer.visibilityModifierSource(method.descriptor), - Source.emptyUnless(!method.descriptor.enclosingTypeDescriptor.typeDeclaration.isInterface) { + Source.emptyIf(method.descriptor.enclosingTypeDescriptor.typeDeclaration.isInterface) { spaceSeparated( Source.emptyUnless(method.descriptor.isNative) { KotlinSource.EXTERNAL_KEYWORD }, method.inheritanceModifierSource, @@ -241,8 +241,8 @@ internal data class MemberRenderer(val nameRenderer: NameRenderer, val enclosing val parameterDescriptors = methodDescriptor.parameterDescriptors val parameters = method.parameters val renderWithNewLines = objCParameterNames != null && parameters.isNotEmpty() - val optionalNewLineSource = Source.emptyUnless(renderWithNewLines) { Source.NEW_LINE } - return Source.emptyUnless(!methodDescriptor.isKtProperty) { + val optionalNewLineSource = Source.emptyUnless(renderWithNewLines) { NEW_LINE } + return Source.emptyIf(methodDescriptor.isKtProperty) { inParentheses( join( indentedIf( diff --git a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/TypeDescriptorRenderer.kt b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/TypeDescriptorRenderer.kt index b4cc0e50ba..9494c2177b 100644 --- a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/TypeDescriptorRenderer.kt +++ b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/TypeDescriptorRenderer.kt @@ -116,7 +116,7 @@ internal data class TypeDescriptorRenderer( join( nameRenderer.qualifiedNameSource(arrayTypeDescriptor), arrayTypeDescriptor.componentTypeDescriptor.let { - Source.emptyUnless(!it.isPrimitive) { inAngleBrackets(child.source(it)) } + Source.emptyIf(it.isPrimitive) { inAngleBrackets(child.source(it)) } }, nullableSuffixSource(arrayTypeDescriptor), ) diff --git a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/source/Source.kt b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/source/Source.kt index b7ae472c94..f8b32c3c90 100644 --- a/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/source/Source.kt +++ b/transpiler/java/com/google/j2cl/transpiler/backend/kotlin/source/Source.kt @@ -42,7 +42,7 @@ private constructor( * source. */ operator fun plus(source: Source) = - emptyUnless(isNotEmpty() || source.isNotEmpty()) { + emptyIf(isEmpty() && source.isEmpty()) { Source { sourceBuilder -> sourceBuilder.append(this) sourceBuilder.append(source) @@ -95,7 +95,13 @@ private constructor( /** Returns a source containing the given string. */ fun source(string: String) = - emptyUnless(string.isNotEmpty()) { Source { sourceBuilder -> sourceBuilder.append(string) } } + emptyIf(string.isEmpty()) { Source { sourceBuilder -> sourceBuilder.append(string) } } + + /** + * Returns empty source if the condition is satisfied, otherwise source returned from the given + * function. + */ + inline fun emptyIf(condition: Boolean, fn: () -> Source) = if (condition) EMPTY else fn() /** * Returns source returned from the given function if the condition is satisfied, otherwise @@ -105,7 +111,7 @@ private constructor( /** Join given sources using given separator, skipping empty ones. */ fun join(sources: Iterable, separator: String = "") = - emptyUnless(sources.any(Source::isNotEmpty)) { + emptyIf(sources.all(Source::isEmpty)) { Source { sourceBuilder -> var first = true for (source in sources) { @@ -146,7 +152,7 @@ private constructor( spaceSeparated(LEFT_CURLY_BRACKET, source, RIGHT_CURLY_BRACKET) fun indented(source: Source) = - emptyUnless(source.isNotEmpty()) { + emptyIf(source.isEmpty()) { Source { sourceBuilder -> sourceBuilder.indent() sourceBuilder.append(source) diff --git a/transpiler/javatests/com/google/j2cl/transpiler/backend/kotlin/source/SourceTest.kt b/transpiler/javatests/com/google/j2cl/transpiler/backend/kotlin/source/SourceTest.kt index b89132abad..743621a7b1 100644 --- a/transpiler/javatests/com/google/j2cl/transpiler/backend/kotlin/source/SourceTest.kt +++ b/transpiler/javatests/com/google/j2cl/transpiler/backend/kotlin/source/SourceTest.kt @@ -160,7 +160,13 @@ class SourceTest { } @Test - fun sourceIf() { + fun sourceEmptyIf() { + Source.emptyIf(true) { sourceA }.assertBuilds("") + Source.emptyIf(false) { sourceA }.assertBuilds("a") + } + + @Test + fun sourceEmptyUnless() { Source.emptyUnless(true) { sourceA }.assertBuilds("a") Source.emptyUnless(false) { sourceA }.assertBuilds("") }