Skip to content

Commit

Permalink
[J2KT] Extracts TypeRenderer out of Renderer.
Browse files Browse the repository at this point in the history
The follow-up CLs will cover the remaining parts:
- MemberRenderer,
- ExpressionRenderer,
- StatementRenderer.

PiperOrigin-RevId: 588002011
  • Loading branch information
Googler authored and copybara-github committed Dec 5, 2023
1 parent 73931e2 commit edbfe8a
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 350 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,5 @@ internal data class CompilationUnitRenderer(val nameRenderer: NameRenderer) {
?.let { spaceSeparated(PACKAGE_KEYWORD, qualifiedIdentifierSource(it)) }
.orEmpty()

private fun typeSource(type: Type): Source =
Renderer(nameRenderer, currentType = type).typeSource(type)
private fun typeSource(type: Type): Source = TypeRenderer(nameRenderer).typeSource(type)
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ private val Import.source: Source
join(dotSeparated(pathComponents.map(::identifierSource)), suffixOrNull?.source.orEmpty())
)

/** A source with import suffix. */
private val Import.Suffix.source: Source
get() =
when (this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,60 +31,62 @@ import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.dotSepa
import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.source
import com.google.j2cl.transpiler.backend.kotlin.source.orEmpty

internal fun Renderer.jsInteropAnnotationsSource(typeDeclaration: TypeDeclaration): Source =
internal fun TypeRenderer.jsInteropAnnotationsSource(typeDeclaration: TypeDeclaration): Source =
jsFunctionAnnotationSource(typeDeclaration)
.ifEmpty { jsTypeAnnotationSource(typeDeclaration) }
.ifEmpty { jsEnumAnnotationSource(typeDeclaration) }

internal fun Renderer.jsInteropAnnotationsSource(fieldDescriptor: FieldDescriptor): Source =
internal fun TypeRenderer.jsInteropAnnotationsSource(fieldDescriptor: FieldDescriptor): Source =
jsPropertyAnnotationSource(fieldDescriptor)
.ifEmpty { jsIgnoreAnnotationSource(fieldDescriptor) }
.ifEmpty { jsOverlayAnnotationSource(fieldDescriptor) }

internal fun Renderer.jsInteropAnnotationsSource(methodDescriptor: MethodDescriptor): Source =
internal fun TypeRenderer.jsInteropAnnotationsSource(methodDescriptor: MethodDescriptor): Source =
jsPropertyAnnotationSource(methodDescriptor)
.ifEmpty { jsMethodAnnotationSource(methodDescriptor) }
.ifEmpty { jsConstructorAnnotationSource(methodDescriptor) }
.ifEmpty { jsIgnoreAnnotationSource(methodDescriptor) }
.ifEmpty { jsOverlayAnnotationSource(methodDescriptor) }

internal fun Renderer.jsInteropAnnotationsSource(parameterDescriptor: ParameterDescriptor): Source =
internal fun TypeRenderer.jsInteropAnnotationsSource(
parameterDescriptor: ParameterDescriptor
): Source =
parameterDescriptor
.takeIf { it.isJsOptional }
?.let {
annotation(nameRenderer.topLevelQualifiedNameSource("jsinterop.annotations.JsOptional"))
}
.orEmpty()

private fun Renderer.jsPropertyAnnotationSource(memberDescriptor: MemberDescriptor): Source =
private fun TypeRenderer.jsPropertyAnnotationSource(memberDescriptor: MemberDescriptor): Source =
memberDescriptor
.takeIf { it.isJsProperty }
?.let { jsInteropAnnotationSource(memberDescriptor, "jsinterop.annotations.JsProperty") }
.orEmpty()

private fun Renderer.jsIgnoreAnnotationSource(memberDescriptor: MemberDescriptor): Source =
private fun TypeRenderer.jsIgnoreAnnotationSource(memberDescriptor: MemberDescriptor): Source =
memberDescriptor
.takeIf { it.hasJsIgnoreAnnotation }
?.let { annotation(nameRenderer.topLevelQualifiedNameSource("jsinterop.annotations.JsIgnore")) }
.orEmpty()

private fun Renderer.jsOverlayAnnotationSource(memberDescriptor: MemberDescriptor): Source =
private fun TypeRenderer.jsOverlayAnnotationSource(memberDescriptor: MemberDescriptor): Source =
memberDescriptor
.takeIf { it.isJsOverlay }
?.let {
annotation(nameRenderer.topLevelQualifiedNameSource("jsinterop.annotations.JsOverlay"))
}
.orEmpty()

private fun Renderer.jsConstructorAnnotationSource(methodDescriptor: MethodDescriptor): Source =
private fun TypeRenderer.jsConstructorAnnotationSource(methodDescriptor: MethodDescriptor): Source =
methodDescriptor
.takeIf { it.hasJsConstructorAnnotation }
?.let {
annotation(nameRenderer.topLevelQualifiedNameSource("jsinterop.annotations.JsConstructor"))
}
.orEmpty()

private fun Renderer.jsMethodAnnotationSource(methodDescriptor: MethodDescriptor): Source =
private fun TypeRenderer.jsMethodAnnotationSource(methodDescriptor: MethodDescriptor): Source =
methodDescriptor
.takeIf { it.isJsMethod }
?.let { jsInteropAnnotationSource(methodDescriptor, "jsinterop.annotations.JsMethod") }
Expand All @@ -94,7 +96,7 @@ private fun Renderer.jsMethodAnnotationSource(methodDescriptor: MethodDescriptor
* Render the `annotationQualifiedName` annotation if the member had an annotation in the source or
* if it requires one to restore its jsname.
*/
private fun Renderer.jsInteropAnnotationSource(
private fun TypeRenderer.jsInteropAnnotationSource(
memberDescriptor: MemberDescriptor,
annotationQualifiedName: String
): Source =
Expand All @@ -120,15 +122,15 @@ private fun Renderer.jsInteropAnnotationSource(
}
.orEmpty()

private fun Renderer.jsFunctionAnnotationSource(typeDeclaration: TypeDeclaration): Source =
private fun TypeRenderer.jsFunctionAnnotationSource(typeDeclaration: TypeDeclaration): Source =
typeDeclaration
.takeIf { it.isJsFunctionInterface }
?.let {
annotation(nameRenderer.topLevelQualifiedNameSource("jsinterop.annotations.JsFunction"))
}
.orEmpty()

private fun Renderer.jsEnumAnnotationSource(typeDeclaration: TypeDeclaration): Source =
private fun TypeRenderer.jsEnumAnnotationSource(typeDeclaration: TypeDeclaration): Source =
typeDeclaration
.takeIf { it.isJsEnum }
?.let {
Expand All @@ -146,7 +148,7 @@ private fun Renderer.jsEnumAnnotationSource(typeDeclaration: TypeDeclaration): S
}
.orEmpty()

private fun Renderer.jsTypeAnnotationSource(typeDeclaration: TypeDeclaration): Source =
private fun TypeRenderer.jsTypeAnnotationSource(typeDeclaration: TypeDeclaration): Source =
typeDeclaration
.takeIf { it.isJsType }
?.let {
Expand All @@ -168,23 +170,23 @@ private fun nameParameterSource(typeDeclaration: TypeDeclaration): Source =
private fun nameParameterSource(value: String?): Source =
value?.let { assignment(source("name"), literal(it)) }.orEmpty()

private fun Renderer.namespaceParameterSource(typeDeclaration: TypeDeclaration): Source =
private fun TypeRenderer.namespaceParameterSource(typeDeclaration: TypeDeclaration): Source =
typeDeclaration
.takeIf { it.hasCustomizedJsNamespace() }
?.let { namespaceParameterSource(it.jsNamespace) }
.orEmpty()

private fun Renderer.namespaceParameterSource(namespace: String?): Source =
private fun TypeRenderer.namespaceParameterSource(namespace: String?): Source =
namespace?.let { assignment(source("namespace"), namespaceSource(it)) }.orEmpty()

private fun Renderer.namespaceSource(namespace: String): Source =
private fun TypeRenderer.namespaceSource(namespace: String): Source =
if (JsUtils.isGlobal(namespace)) {
globalNamespaceSource()
} else {
literal(namespace)
}

private fun Renderer.globalNamespaceSource(): Source =
private fun TypeRenderer.globalNamespaceSource(): Source =
dotSeparated(
nameRenderer.topLevelQualifiedNameSource("jsinterop.annotations.JsPackage"),
identifierSource("GLOBAL")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.newLine
import com.google.j2cl.transpiler.backend.kotlin.source.Source.Companion.spaceSeparated
import com.google.j2cl.transpiler.backend.kotlin.source.orEmpty

internal fun Renderer.source(member: Member): Source =
internal fun TypeRenderer.source(member: Member): Source =
when (member) {
is Member.WithCompanionObject -> source(member.companionObject)
is Member.WithJavaMember -> memberSource(member.javaMember)
is Member.WithType -> typeSource(member.type)
}

private fun Renderer.source(companionObject: CompanionObject): Source =
private fun TypeRenderer.source(companionObject: CompanionObject): Source =
newLineSeparated(
nameRenderer.objCAnnotationSource(companionObject),
spaceSeparated(
Expand All @@ -86,15 +86,15 @@ private fun Renderer.source(companionObject: CompanionObject): Source =
)
)

private fun Renderer.memberSource(member: JavaMember): Source =
private fun TypeRenderer.memberSource(member: JavaMember): Source =
when (member) {
is Method -> methodSource(member)
is Field -> fieldSource(member)
is InitializerBlock -> initializerBlockSource(member)
else -> throw InternalCompilerError("Unhandled ${member::class}")
}

private fun Renderer.methodSource(method: Method): Source =
private fun TypeRenderer.methodSource(method: Method): Source =
method.renderedStatements.let { statements ->
// Don't render primary constructor if it's empty.
Source.emptyUnless(!isKtPrimaryConstructor(method) || !statements.isEmpty()) {
Expand Down Expand Up @@ -133,16 +133,16 @@ private val Method.renderedStatements: List<Statement>
)
}

private fun Renderer.isKtPrimaryConstructor(method: Method): Boolean =
method == currentType!!.ktPrimaryConstructor
private fun TypeRenderer.isKtPrimaryConstructor(method: Method): Boolean =
method == currentBodyType?.ktPrimaryConstructor

private fun Renderer.fieldSource(field: Field): Source {
private fun TypeRenderer.fieldSource(field: Field): Source {
val fieldDescriptor = field.descriptor
val isFinal = fieldDescriptor.isFinal
val typeDescriptor = fieldDescriptor.typeDescriptor
val isConst = field.isCompileTimeConstant && field.isStatic
val isJvmField =
!currentType!!.jvmFieldsAreIllegal &&
!jvmFieldsAreIllegal &&
!isConst &&
!field.isKtLateInit &&
fieldDescriptor.ktVisibility != KtVisibility.PRIVATE
Expand All @@ -159,7 +159,7 @@ private fun Renderer.fieldSource(field: Field): Source {
if (isFinal) VAL_KEYWORD else VAR_KEYWORD,
colonSeparated(
identifierSource(fieldDescriptor.ktMangledName),
typeDescriptorSource(typeDescriptor)
nameRenderer.typeDescriptorSource(typeDescriptor)
),
initializer(
if (initializer == null && field.isNative) {
Expand All @@ -172,40 +172,45 @@ private fun Renderer.fieldSource(field: Field): Source {
)
}

private fun Renderer.jvmFieldAnnotationSource(): Source =
private val TypeRenderer.jvmFieldsAreIllegal: Boolean
get() = currentBodyType?.jvmFieldsAreIllegal ?: false

private fun TypeRenderer.jvmFieldAnnotationSource(): Source =
annotation(nameRenderer.topLevelQualifiedNameSource("kotlin.jvm.JvmField"))

private fun Renderer.jvmStaticAnnotationSource(): Source =
private fun TypeRenderer.jvmStaticAnnotationSource(): Source =
annotation(nameRenderer.topLevelQualifiedNameSource("kotlin.jvm.JvmStatic"))

private fun Renderer.jvmThrowsAnnotationSource(methodDescriptor: MethodDescriptor): Source =
private fun TypeRenderer.jvmThrowsAnnotationSource(methodDescriptor: MethodDescriptor): Source =
methodDescriptor.exceptionTypeDescriptors
.takeIf { it.isNotEmpty() }
?.let { exceptionTypeDescriptors ->
annotation(
nameRenderer.topLevelQualifiedNameSource("kotlin.jvm.Throws"),
exceptionTypeDescriptors.map {
classLiteral(typeDescriptorSource(it.toRawTypeDescriptor().toNonNullable()))
classLiteral(nameRenderer.typeDescriptorSource(it.toRawTypeDescriptor().toNonNullable()))
}
)
}
.orEmpty()

private fun Renderer.nativeThrowsAnnotationSource(methodDescriptor: MethodDescriptor): Source =
private fun TypeRenderer.nativeThrowsAnnotationSource(methodDescriptor: MethodDescriptor): Source =
methodDescriptor.ktInfo
.takeIf { it.isThrows }
?.let {
annotation(
nameRenderer.topLevelQualifiedNameSource("javaemul.lang.NativeThrows"),
classLiteral(typeDescriptorSource(TypeDescriptors.get().javaLangThrowable.toNonNullable()))
classLiteral(
nameRenderer.typeDescriptorSource(TypeDescriptors.get().javaLangThrowable.toNonNullable())
)
)
}
.orEmpty()

private fun Renderer.initializerBlockSource(initializerBlock: InitializerBlock): Source =
private fun TypeRenderer.initializerBlockSource(initializerBlock: InitializerBlock): Source =
spaceSeparated(INIT_KEYWORD, statementSource(initializerBlock.block))

private fun Renderer.methodHeaderSource(method: Method): Source =
private fun TypeRenderer.methodHeaderSource(method: Method): Source =
if (isKtPrimaryConstructor(method)) {
INIT_KEYWORD
} else {
Expand Down Expand Up @@ -235,7 +240,7 @@ private fun Renderer.methodHeaderSource(method: Method): Source =
)
}

internal fun Renderer.methodHeaderSource(functionExpression: FunctionExpression): Source =
internal fun TypeRenderer.methodHeaderSource(functionExpression: FunctionExpression): Source =
functionExpression.descriptor.let { methodDescriptor ->
newLineSeparated(
spaceSeparated(
Expand All @@ -252,7 +257,7 @@ internal fun Renderer.methodHeaderSource(functionExpression: FunctionExpression)
)
}

private fun Renderer.methodKindAndNameSource(methodDescriptor: MethodDescriptor): Source =
private fun TypeRenderer.methodKindAndNameSource(methodDescriptor: MethodDescriptor): Source =
if (methodDescriptor.isConstructor) {
CONSTRUCTOR_KEYWORD
} else {
Expand Down Expand Up @@ -289,7 +294,7 @@ private val MethodDescriptor.inheritanceModifierSource
else -> Source.EMPTY
}

internal fun Renderer.methodParametersSource(
internal fun TypeRenderer.methodParametersSource(
method: MethodLike,
objCParameterNames: List<String>? = null
): Source {
Expand Down Expand Up @@ -322,7 +327,7 @@ internal fun Renderer.methodParametersSource(
}
}

private fun Renderer.parameterSource(
private fun TypeRenderer.parameterSource(
parameterDescriptor: ParameterDescriptor,
parameter: Variable,
objCParameterName: String? = null
Expand All @@ -338,17 +343,20 @@ private fun Renderer.parameterSource(
Source.emptyUnless(parameterDescriptor.isVarargs) { VARARG_KEYWORD },
objCParameterName?.let { nameRenderer.objCNameAnnotationSource(it) }.orEmpty(),
jsInteropAnnotationsSource(parameterDescriptor),
colonSeparated(nameRenderer.nameSource(parameter), typeDescriptorSource(renderedTypeDescriptor))
colonSeparated(
nameRenderer.nameSource(parameter),
nameRenderer.typeDescriptorSource(renderedTypeDescriptor)
)
)
}

internal fun Renderer.methodReturnTypeSource(methodDescriptor: MethodDescriptor): Source =
internal fun TypeRenderer.methodReturnTypeSource(methodDescriptor: MethodDescriptor): Source =
methodDescriptor.returnTypeDescriptor
.takeIf { it != PrimitiveTypes.VOID }
?.let { typeDescriptorSource(it) }
?.let { nameRenderer.typeDescriptorSource(it) }
.orEmpty()

private fun Renderer.constructorInvocationSource(method: Method): Source =
private fun TypeRenderer.constructorInvocationSource(method: Method): Source =
getConstructorInvocation(method)
?.let { constructorInvocation ->
join(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 Google Inc.
* Copyright 2021 Google 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
Expand All @@ -22,7 +22,7 @@ import com.google.j2cl.transpiler.backend.kotlin.common.orIfNull
import com.google.j2cl.transpiler.backend.kotlin.source.Source

/**
* Renderer of Kotlin names.
* Renderer of Kotlin names, with import resolution and alias generation.
*
* @property environment rendering environment
* @property localNames a set of local names which are potentially shadowing imports
Expand Down

This file was deleted.

Loading

0 comments on commit edbfe8a

Please sign in to comment.