Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Resolver.mapToJvmClassName() for KSClassDeclaration #1338

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions api/api.base
Expand Up @@ -168,6 +168,7 @@ package com.google.devtools.ksp.processing {
method @com.google.devtools.ksp.KspExperimental public boolean isJavaRawType(@NonNull com.google.devtools.ksp.symbol.KSType type);
method @Nullable @com.google.devtools.ksp.KspExperimental public com.google.devtools.ksp.symbol.KSName mapJavaNameToKotlin(@NonNull com.google.devtools.ksp.symbol.KSName javaName);
method @Nullable @com.google.devtools.ksp.KspExperimental public com.google.devtools.ksp.symbol.KSName mapKotlinNameToJava(@NonNull com.google.devtools.ksp.symbol.KSName kotlinName);
method @Nullable @com.google.devtools.ksp.KspExperimental public String mapToJvmClassName(@NonNull com.google.devtools.ksp.symbol.KSClassDeclaration declaration);
method @Nullable @com.google.devtools.ksp.KspExperimental public String mapToJvmSignature(@NonNull com.google.devtools.ksp.symbol.KSDeclaration declaration);
method public boolean overrides(@NonNull com.google.devtools.ksp.symbol.KSDeclaration overrider, @NonNull com.google.devtools.ksp.symbol.KSDeclaration overridee);
method public boolean overrides(@NonNull com.google.devtools.ksp.symbol.KSDeclaration overrider, @NonNull com.google.devtools.ksp.symbol.KSDeclaration overridee, @NonNull com.google.devtools.ksp.symbol.KSClassDeclaration containingClass);
Expand Down
Expand Up @@ -115,6 +115,13 @@ interface Resolver {
@KspExperimental
fun mapToJvmSignature(declaration: KSDeclaration): String?

/**
* Returns the [binary class name](https://asm.ow2.io/javadoc/org/objectweb/asm/Type.html#getClassName()) in JVM
* for the given [KSClassDeclaration].
*/
@KspExperimental
fun mapToJvmClassName(declaration: KSClassDeclaration): String?

/**
* @param overrider the candidate overriding declaration being checked.
* @param overridee the candidate overridden declaration being checked.
Expand Down
Expand Up @@ -367,6 +367,13 @@ class ResolverImpl(
else -> null
}

@KspExperimental
override fun mapToJvmClassName(declaration: KSClassDeclaration): String? {
val descriptor = resolveClassDeclaration(declaration) ?: return null

return typeMapper.mapType(descriptor).className
}

override fun overrides(overrider: KSDeclaration, overridee: KSDeclaration): Boolean {
fun resolveForOverride(declaration: KSDeclaration): DeclarationDescriptor? {
return when (declaration) {
Expand Down
Expand Up @@ -339,6 +339,12 @@ class KSPCompilerPluginTest : AbstractKSPCompilerPluginTest() {
runTest("../test-utils/testData/api/javaWildcards2.kt")
}

@TestMetadata("jvmClassNameMapper.kt")
@Test
fun testJvmClassNameMapper() {
runTest("../test-utils/testData/api/jvmClassNameMapper.kt")
}

@TestMetadata("lateinitProperties.kt")
@Test
fun testLateinitProperties() {
Expand Down
Expand Up @@ -259,6 +259,10 @@ class ResolverAAImpl(
TODO("Not yet implemented")
}

override fun mapToJvmClassName(declaration: KSClassDeclaration): String? {
TODO("Not yet implemented")
}

override fun overrides(overrider: KSDeclaration, overridee: KSDeclaration): Boolean {
TODO("Not yet implemented")
}
Expand Down
@@ -0,0 +1,54 @@
/*
* Copyright 2020 Google LLC
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
*
* 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.google.devtools.ksp.processor

import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

@KspExperimental
class MapJvmClassNameProcessor : AbstractTestProcessor() {
private val result = mutableListOf<String>()

override fun toResult(): List<String> {
return result
}

override fun process(resolver: Resolver): List<KSAnnotated> {
listOf(
"Cls1",
"Cls1.Cls2",
"Cls1.Cls3",
"Cls1.Cls4",
"JavaInterfaceWithVoid",
"JavaClass1",
"JavaClass1.JavaClass2",
"JavaClass1.JavaClass3",
"JavaClass1.JavaClass4",
"JavaClass5",
"JavaAnno",
)
.map { className ->
resolver.getClassDeclarationByName(className)!!
}.forEach { subject ->
result.add(resolver.mapToJvmClassName(subject)!!)
}
return emptyList()
}
}
55 changes: 55 additions & 0 deletions test-utils/testData/api/jvmClassNameMapper.kt
@@ -0,0 +1,55 @@
/*
* Copyright 2020 Google LLC
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
*
* 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.
*/

// TEST PROCESSOR: MapJvmClassNameProcessor
// EXPECTED:
// Cls1
// Cls1$Cls2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any more complicated class names? It looks to me that if only nested class matters, we can actually write this in a format of extension function by recursively checking the parent declaration and build a name?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used signatureMapper.kt (and MapSignatureProcessor) as a template, for the equivalent Resolver.mapToJvmSignature() functionality. Both tests are equally underpowered. However, I don't think can really do much right now to make my test a lot more expressive until #1335 is fixed, which crashes the new Resolver.mapToJvmClassName() in the same manner, so I expect that a fix for #1335 will similarly clear the landscape here.

Once the fix is in place, I'd think the following additional tests will be particularly useful:

  • Local class inside internal function (function name mangling)
  • Local class inside function annotated with @JvmName("xyz")
  • Local class inside overloaded function

Anything else of particular interest that you can think of?

Edit: also: local class inside top level function (public & internal) in file annotated with @file:JvmName("xyz"). Is that possible within the current test infrastructure?

Edit: inline classes & local class in function with inline class parameter (may have special mangling)

// Cls1$Cls3
// Cls1$Cls4
// JavaInterfaceWithVoid
// JavaClass1
// JavaClass1$JavaClass2
// JavaClass1$JavaClass3
// JavaClass1$JavaClass4
// JavaClass5
// JavaAnno
// END

// FILE: Cls1.kt
class Cls1 {
class Cls2

open class Cls3

inner class Cls4
}

// FILE: JavaInterfaceWithVoid.java
interface JavaInterfaceWithVoid {}

// FILE: JavaClass1.java
class JavaClass1 {
static final class JavaClass2 {}
static class JavaClass3 {}
class JavaClass4 {}
}

class JavaClass5 {}

// FILE: JavaAnno.java
@interface JavaAnno {}