Skip to content

Commit

Permalink
AA: implements Resolver.effectiveJavaModifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
neetopia committed Aug 2, 2023
1 parent eea926d commit 45382e2
Show file tree
Hide file tree
Showing 12 changed files with 568 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
* limitations under the License.
*/

package com.google.devtools.ksp.processing.impl
package com.google.devtools.ksp

internal val JVM_STATIC_ANNOTATION_FQN = "kotlin.jvm.JvmStatic"
internal val JVM_DEFAULT_ANNOTATION_FQN = "kotlin.jvm.JvmDefault"
internal val JVM_DEFAULT_WITHOUT_COMPATIBILITY_ANNOTATION_FQN = "kotlin.jvm.JvmDefaultWithoutCompatibility"
internal val JVM_STRICTFP_ANNOTATION_FQN = "kotlin.jvm.Strictfp"
internal val JVM_SYNCHRONIZED_ANNOTATION_FQN = "kotlin.jvm.Synchronized"
internal val JVM_TRANSIENT_ANNOTATION_FQN = "kotlin.jvm.Transient"
internal val JVM_VOLATILE_ANNOTATION_FQN = "kotlin.jvm.Volatile"
val JVM_STATIC_ANNOTATION_FQN = "kotlin.jvm.JvmStatic"
val JVM_DEFAULT_ANNOTATION_FQN = "kotlin.jvm.JvmDefault"
val JVM_DEFAULT_WITHOUT_COMPATIBILITY_ANNOTATION_FQN = "kotlin.jvm.JvmDefaultWithoutCompatibility"
val JVM_STRICTFP_ANNOTATION_FQN = "kotlin.jvm.Strictfp"
val JVM_SYNCHRONIZED_ANNOTATION_FQN = "kotlin.jvm.Synchronized"
val JVM_TRANSIENT_ANNOTATION_FQN = "kotlin.jvm.Transient"
val JVM_VOLATILE_ANNOTATION_FQN = "kotlin.jvm.Volatile"
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,19 @@

package com.google.devtools.ksp.impl

import com.google.devtools.ksp.BinaryClassInfoCache
import com.google.devtools.ksp.JVM_DEFAULT_ANNOTATION_FQN
import com.google.devtools.ksp.JVM_DEFAULT_WITHOUT_COMPATIBILITY_ANNOTATION_FQN
import com.google.devtools.ksp.JVM_STATIC_ANNOTATION_FQN
import com.google.devtools.ksp.JVM_STRICTFP_ANNOTATION_FQN
import com.google.devtools.ksp.JVM_SYNCHRONIZED_ANNOTATION_FQN
import com.google.devtools.ksp.JVM_TRANSIENT_ANNOTATION_FQN
import com.google.devtools.ksp.JVM_VOLATILE_ANNOTATION_FQN
import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.extractThrowsAnnotation
import com.google.devtools.ksp.extractThrowsFromClassFile
import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.hasAnnotation
import com.google.devtools.ksp.impl.symbol.kotlin.KSClassDeclarationEnumEntryImpl
import com.google.devtools.ksp.impl.symbol.kotlin.KSClassDeclarationImpl
import com.google.devtools.ksp.impl.symbol.kotlin.KSFileImpl
Expand All @@ -36,7 +45,13 @@ import com.google.devtools.ksp.impl.symbol.kotlin.KSTypeImpl
import com.google.devtools.ksp.impl.symbol.kotlin.analyze
import com.google.devtools.ksp.impl.symbol.kotlin.findParentOfType
import com.google.devtools.ksp.impl.symbol.kotlin.toKtClassSymbol
import com.google.devtools.ksp.isAbstract
import com.google.devtools.ksp.isConstructor
import com.google.devtools.ksp.isOpen
import com.google.devtools.ksp.isPrivate
import com.google.devtools.ksp.isProtected
import com.google.devtools.ksp.isPublic
import com.google.devtools.ksp.javaModifiers
import com.google.devtools.ksp.processing.KSBuiltIns
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.impl.KSNameImpl
Expand Down Expand Up @@ -71,6 +86,7 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.org.objectweb.asm.Opcodes
import java.io.File
import java.nio.file.Files

Expand Down Expand Up @@ -131,9 +147,123 @@ class ResolverAAImpl(
}

override fun effectiveJavaModifiers(declaration: KSDeclaration): Set<Modifier> {
TODO("Not yet implemented")
val modifiers = HashSet<Modifier>(declaration.modifiers.filter { it in javaModifiers })

// This is only needed by sources.
// PUBLIC, PRIVATE, PROTECTED are already handled in descriptor based impls.
fun addVisibilityModifiers() {
when {
declaration.isPublic() -> modifiers.add(Modifier.PUBLIC)
declaration.isPrivate() -> modifiers.add(Modifier.PRIVATE)
declaration.isProtected() -> modifiers.add(Modifier.PROTECTED)
}
}

when (declaration.origin) {
Origin.JAVA -> {
addVisibilityModifiers()
if (declaration is KSClassDeclaration && declaration.classKind == ClassKind.INTERFACE)
modifiers.add(Modifier.ABSTRACT)
}
Origin.KOTLIN -> {
addVisibilityModifiers()
if (!declaration.isOpen())
modifiers.add(Modifier.FINAL)
(declaration as? KSClassDeclarationImpl)?.let {
analyze {
if (
it.ktClassOrObjectSymbol.getStaticMemberScope()
.getAllSymbols().contains(declaration.ktDeclarationSymbol)
)
modifiers.add(Modifier.JAVA_STATIC)
}
}

if (declaration.hasAnnotation(JVM_DEFAULT_ANNOTATION_FQN))
modifiers.add(Modifier.JAVA_DEFAULT)
if (declaration.hasAnnotation(JVM_DEFAULT_WITHOUT_COMPATIBILITY_ANNOTATION_FQN))
modifiers.add(Modifier.JAVA_DEFAULT)
if (declaration.hasAnnotation(JVM_STRICTFP_ANNOTATION_FQN))
modifiers.add(Modifier.JAVA_STRICT)
if (declaration.hasAnnotation(JVM_SYNCHRONIZED_ANNOTATION_FQN))
modifiers.add(Modifier.JAVA_SYNCHRONIZED)
if (declaration.hasAnnotation(JVM_TRANSIENT_ANNOTATION_FQN))
modifiers.add(Modifier.JAVA_TRANSIENT)
if (declaration.hasAnnotation(JVM_VOLATILE_ANNOTATION_FQN))
modifiers.add(Modifier.JAVA_VOLATILE)
when (declaration) {
is KSClassDeclaration -> {
if (declaration.isCompanionObject)
modifiers.add(Modifier.JAVA_STATIC)
if (declaration.classKind == ClassKind.INTERFACE)
modifiers.add(Modifier.ABSTRACT)
}
is KSPropertyDeclaration -> {
if (declaration.isAbstract())
modifiers.add(Modifier.ABSTRACT)
}
is KSFunctionDeclaration -> {
if (declaration.isAbstract)
modifiers.add(Modifier.ABSTRACT)
}
}
}
Origin.KOTLIN_LIB, Origin.JAVA_LIB -> {
if (declaration.hasAnnotation(JVM_STATIC_ANNOTATION_FQN)) {
modifiers.add(Modifier.JAVA_STATIC)
}
addVisibilityModifiers()
when (declaration) {
is KSPropertyDeclaration -> {
if (declaration.jvmAccessFlag and Opcodes.ACC_TRANSIENT != 0)
modifiers.add(Modifier.JAVA_TRANSIENT)
if (declaration.jvmAccessFlag and Opcodes.ACC_VOLATILE != 0)
modifiers.add(Modifier.JAVA_VOLATILE)
}
is KSFunctionDeclaration -> {
if (declaration.jvmAccessFlag and Opcodes.ACC_STRICT != 0)
modifiers.add(Modifier.JAVA_STRICT)
if (declaration.jvmAccessFlag and Opcodes.ACC_SYNCHRONIZED != 0)
modifiers.add(Modifier.JAVA_SYNCHRONIZED)
}
}
}
else -> Unit
}
return modifiers
}

internal val KSPropertyDeclaration.jvmAccessFlag: Int
get() = when (origin) {
Origin.KOTLIN_LIB, Origin.JAVA_LIB -> {
val fileManager = instance.javaFileManager
val parentClass = this.findParentOfType<KSClassDeclaration>()
val classId = (parentClass as KSClassDeclarationImpl).ktClassOrObjectSymbol.classIdIfNonLocal!!
val virtualFileContent = analyze {
(fileManager.findClass(classId, analysisScope) as JavaClassImpl).virtualFile!!.contentsToByteArray()
}
BinaryClassInfoCache.getCached(classId, virtualFileContent)
.fieldAccFlags[this.simpleName.asString()] ?: 0
}
else -> throw IllegalStateException("this function expects only KOTLIN_LIB or JAVA_LIB")
}

internal val KSFunctionDeclaration.jvmAccessFlag: Int
get() = when (origin) {
Origin.KOTLIN_LIB, Origin.JAVA_LIB -> {
val jvmDesc = mapToJvmSignatureInternal(this)
val fileManager = instance.javaFileManager
val parentClass = this.findParentOfType<KSClassDeclaration>()
val classId = (parentClass as KSClassDeclarationImpl).ktClassOrObjectSymbol.classIdIfNonLocal!!
val virtualFileContent = analyze {
(fileManager.findClass(classId, analysisScope) as JavaClassImpl).virtualFile!!.contentsToByteArray()
}
BinaryClassInfoCache.getCached(classId, virtualFileContent)
.methodAccFlags[this.simpleName.asString() + jvmDesc] ?: 0
}
else -> throw IllegalStateException("this function expects only KOTLIN_LIB or JAVA_LIB")
}

override fun getAllFiles(): Sequence<KSFile> {
return ksFiles.asSequence()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@ import com.google.devtools.ksp.symbol.Location
import com.google.devtools.ksp.symbol.Modifier
import com.google.devtools.ksp.symbol.Origin
import com.google.devtools.ksp.toKSModifiers
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiJvmModifiersOwner
import com.intellij.psi.PsiModifierListOwner
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtDeclarationSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtFunctionLikeSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtPropertySymbol
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtNamedSymbol
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtModifierListOwner

Expand All @@ -56,16 +55,20 @@ abstract class AbstractKSDeclarationImpl(val ktDeclarationSymbol: KtDeclarationS
}

override val modifiers: Set<Modifier> by lazy {
when (val psi = ktDeclarationSymbol.psi) {
is KtModifierListOwner -> psi.toKSModifiers()
is PsiModifierListOwner -> psi.toKSModifiers()
null -> when (ktDeclarationSymbol) {
if (origin == Origin.JAVA_LIB || origin == Origin.KOTLIN_LIB) {
when (ktDeclarationSymbol) {
is KtPropertySymbol -> ktDeclarationSymbol.toModifiers()
is KtClassOrObjectSymbol -> ktDeclarationSymbol.toModifiers()
is KtFunctionLikeSymbol -> ktDeclarationSymbol.toModifiers()
is KtJavaFieldSymbol -> ktDeclarationSymbol.toModifiers()
else -> throw IllegalStateException("Unexpected symbol type ${ktDeclarationSymbol.javaClass}")
}
} else {
when (val psi = ktDeclarationSymbol.psi) {
is KtModifierListOwner -> psi.toKSModifiers()
is PsiModifierListOwner -> psi.toKSModifiers()
else -> throw IllegalStateException("Unexpected symbol type ${ktDeclarationSymbol.javaClass}")
}
else -> emptySet()
}
}

Expand All @@ -90,6 +93,8 @@ abstract class AbstractKSDeclarationImpl(val ktDeclarationSymbol: KtDeclarationS
analyze {
ktDeclarationSymbol.getContainingSymbol()?.let {
ktDeclarationSymbol.getContainingKSSymbol()
} ?: (ktDeclarationSymbol.psi?.parentOfType<PsiClass>())?.getNamedClassSymbol()?.let {
KSClassDeclarationImpl.getCached(it)
} ?: ktDeclarationSymbol.toContainingFile()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.google.devtools.ksp.symbol.*
import org.jetbrains.kotlin.analysis.api.KtStarTypeProjection
import org.jetbrains.kotlin.analysis.api.components.buildClassType
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
import org.jetbrains.kotlin.psi.KtObjectDeclaration

class KSClassDeclarationImpl private constructor(internal val ktClassOrObjectSymbol: KtClassOrObjectSymbol) :
Expand Down Expand Up @@ -161,7 +162,9 @@ internal fun KtClassOrObjectSymbol.toModifiers(): Set<Modifier> {
val result = mutableSetOf<Modifier>()
if (this is KtNamedClassOrObjectSymbol) {
result.add(modality.toModifier())
result.add(visibility.toModifier())
if (visibility != JavaVisibilities.PackageVisibility) {
result.add(visibility.toModifier())
}
if (isInline) {
result.add(Modifier.INLINE)
}
Expand All @@ -171,6 +174,9 @@ internal fun KtClassOrObjectSymbol.toModifiers(): Set<Modifier> {
if (isExternal) {
result.add(Modifier.EXTERNAL)
}
if (isInner) {
result.add(Modifier.INNER)
}
}
if (classKind == KtClassKind.ENUM_CLASS) {
result.add(Modifier.ENUM)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
package com.google.devtools.ksp.impl.symbol.kotlin

import com.google.devtools.ksp.KSObjectCache
import com.google.devtools.ksp.isConstructor
import com.google.devtools.ksp.isPublic
import com.google.devtools.ksp.processing.impl.KSNameImpl
import com.google.devtools.ksp.symbol.*
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.analysis.api.symbols.*
import org.jetbrains.kotlin.analysis.api.symbols.markers.KtSymbolKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFunction

Expand All @@ -51,6 +54,22 @@ class KSFunctionDeclarationImpl private constructor(internal val ktFunctionSymbo
(ktFunctionSymbol as? KtFunctionSymbol)?.modality == Modality.ABSTRACT
}

override val modifiers: Set<Modifier> by lazy {
if (isSyntheticConstructor()) {
val ksClassDeclaration = parentDeclaration as KSClassDeclaration
if (ksClassDeclaration.classKind == ClassKind.ENUM_CLASS) {
return@lazy setOf(Modifier.FINAL, Modifier.PRIVATE)
}
if (ksClassDeclaration.isPublic()) {
setOf(Modifier.FINAL, Modifier.PUBLIC)
} else {
setOf(Modifier.FINAL)
}
} else {
if (isConstructor()) super.modifiers + Modifier.FINAL else super.modifiers
}
}

override val extensionReceiver: KSTypeReference? by lazy {
analyze {
if (!ktFunctionSymbol.isExtension) {
Expand Down Expand Up @@ -150,30 +169,44 @@ class KSFunctionDeclarationImpl private constructor(internal val ktFunctionSymbo

internal fun KtFunctionLikeSymbol.toModifiers(): Set<Modifier> {
val result = mutableSetOf<Modifier>()
if (this is KtFunctionSymbol) {
result.add(visibility.toModifier())
result.add(modality.toModifier())
if (isExternal) {
result.add(Modifier.EXTERNAL)
}
if (isInfix) {
result.add(Modifier.INFIX)
}
if (isInline) {
result.add(Modifier.INLINE)
}
if (isStatic) {
result.add(Modifier.JAVA_STATIC)
}
if (isSuspend) {
result.add(Modifier.SUSPEND)
}
if (isOperator) {
result.add(Modifier.OPERATOR)
when (this) {
is KtConstructorSymbol -> {
if (visibility != JavaVisibilities.PackageVisibility) {
result.add(visibility.toModifier())
}
result.add(Modifier.FINAL)
}
if (isOperator) {
result.add(Modifier.OVERRIDE)
is KtFunctionSymbol -> {
if (visibility != JavaVisibilities.PackageVisibility) {
result.add(visibility.toModifier())
}
if (!isStatic || modality != Modality.OPEN) {
result.add(modality.toModifier())
}
if (isExternal) {
result.add(Modifier.EXTERNAL)
}
if (isInfix) {
result.add(Modifier.INFIX)
}
if (isInline) {
result.add(Modifier.INLINE)
}
if (isStatic) {
result.add(Modifier.JAVA_STATIC)
result.add(Modifier.FINAL)
}
if (isSuspend) {
result.add(Modifier.SUSPEND)
}
if (isOperator) {
result.add(Modifier.OPERATOR)
}
if (isOperator) {
result.add(Modifier.OVERRIDE)
}
}
else -> Unit
}
return result
}
Loading

0 comments on commit 45382e2

Please sign in to comment.