aboutsummaryrefslogtreecommitdiff
path: root/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl')
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt347
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassDeclarationDescriptorImpl.kt203
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassifierReferenceDescriptorImpl.kt86
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSDeclarationDescriptorImpl.kt84
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSExpectActualDescriptorImpl.kt50
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSFunctionDeclarationDescriptorImpl.kt114
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSNodeDescriptorImpl.kt9
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyAccessorDescriptorImpl.kt62
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyDeclarationDescriptorImpl.kt124
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyGetterDescriptorImpl.kt47
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertySetterDescriptorImpl.kt44
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeAliasDescriptorImpl.kt38
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeArgumentDescriptorImpl.kt65
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeParameterDescriptorImpl.kt74
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeReferenceDescriptorImpl.kt82
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSValueParameterDescriptorImpl.kt78
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSAnnotationJavaImpl.kt160
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaEnumEntryImpl.kt111
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaImpl.kt173
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassifierReferenceJavaImpl.kt66
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassifierReferenceLiteImplForJava.kt50
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSDeclarationJavaImpl.kt48
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSFileJavaImpl.kt62
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSFunctionDeclarationJavaImpl.kt125
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSNodeJavaImpl.kt12
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSPropertyDeclarationJavaImpl.kt101
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeArgumentJavaImpl.kt64
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeParameterJavaImpl.kt82
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceJavaImpl.kt148
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceLiteJavaImpl.kt90
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSValueArgumentJavaImpl.kt50
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSValueParameterJavaImpl.kt88
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSAnnotationImpl.kt120
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSCallableReferenceImpl.kt68
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassDeclarationImpl.kt138
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassifierReferenceImpl.kt62
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDeclarationImpl.kt96
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDefNonNullReferenceImpl.kt41
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDynamicReferenceImpl.kt43
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSErrorType.kt71
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSExpectActualImpl.kt64
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSExpectActualNoImpl.kt31
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFileImpl.kt68
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionDeclarationImpl.kt123
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionErrorImpl.kt60
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionImpl.kt76
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSNodeKtImpl.kt12
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyAccessorImpl.kt66
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt129
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationParameterImpl.kt107
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyGetterImpl.kt53
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertySetterImpl.kt50
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeAliasImpl.kt44
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeArgumentImpl.kt83
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeArgumentLiteImpl.kt56
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt154
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeParameterImpl.kt93
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceDeferredImpl.kt69
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceImpl.kt129
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueArgumentImpl.kt70
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueParameterImpl.kt131
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSConstructorSyntheticImpl.kt119
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSErrorTypeClassDeclaration.kt96
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertyAccessorSyntheticImpl.kt41
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertyGetterSyntheticImpl.kt59
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertySetterSyntheticImpl.kt57
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSTypeReferenceSyntheticImpl.kt43
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSValueParameterSyntheticImpl.kt76
-rw-r--r--compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt559
69 files changed, 6294 insertions, 0 deletions
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt
new file mode 100644
index 00000000..e52920c7
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSAnnotationDescriptorImpl.kt
@@ -0,0 +1,347 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.getClassDeclarationByName
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.findPsi
+import com.google.devtools.ksp.symbol.impl.java.KSAnnotationJavaImpl
+import com.google.devtools.ksp.symbol.impl.kotlin.KSErrorType
+import com.google.devtools.ksp.symbol.impl.kotlin.KSValueArgumentLiteImpl
+import com.google.devtools.ksp.symbol.impl.kotlin.getKSTypeCached
+import com.google.devtools.ksp.symbol.impl.synthetic.KSTypeReferenceSyntheticImpl
+import com.intellij.psi.JavaPsiFacade
+import com.intellij.psi.PsiAnnotation
+import com.intellij.psi.PsiAnnotationMethod
+import org.jetbrains.kotlin.builtins.StandardNames
+import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
+import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.NotFoundClasses
+import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
+import org.jetbrains.kotlin.load.java.components.JavaAnnotationDescriptor
+import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaAnnotationDescriptor
+import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
+import org.jetbrains.kotlin.load.java.structure.*
+import org.jetbrains.kotlin.load.java.structure.impl.VirtualFileBoundJavaClass
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryClassSignatureParser
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaAnnotationVisitor
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaMethod
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.ClassifierResolutionContext
+import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
+import org.jetbrains.kotlin.load.kotlin.getContainingKotlinJvmBinaryClass
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.name.FqName
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
+import org.jetbrains.kotlin.resolve.constants.*
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.TypeConstructor
+import org.jetbrains.kotlin.types.isError
+import org.jetbrains.kotlin.types.typeUtil.builtIns
+import org.jetbrains.org.objectweb.asm.AnnotationVisitor
+import org.jetbrains.org.objectweb.asm.ClassReader
+import org.jetbrains.org.objectweb.asm.ClassVisitor
+import org.jetbrains.org.objectweb.asm.MethodVisitor
+import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
+
+class KSAnnotationDescriptorImpl private constructor(
+ val descriptor: AnnotationDescriptor,
+ override val parent: KSNode?
+) : KSAnnotation {
+ companion object : KSObjectCache<Pair<AnnotationDescriptor, KSNode?>, KSAnnotationDescriptorImpl>() {
+ fun getCached(descriptor: AnnotationDescriptor, parent: KSNode?) = cache.getOrPut(Pair(descriptor, parent)) {
+ KSAnnotationDescriptorImpl(descriptor, parent)
+ }
+ }
+
+ override val origin =
+ when (descriptor) {
+ is JavaAnnotationDescriptor, is LazyJavaAnnotationDescriptor -> Origin.JAVA_LIB
+ else -> Origin.KOTLIN_LIB
+ }
+
+ override val location: Location = NonExistLocation
+
+ override val annotationType: KSTypeReference by lazy {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.type, origin, this)
+ }
+
+ override val arguments: List<KSValueArgument> by lazy {
+ descriptor.createKSValueArguments(this)
+ }
+
+ override val defaultArguments: List<KSValueArgument> by lazy {
+ descriptor.getDefaultArguments(this)
+ }
+
+ override val shortName: KSName by lazy {
+ KSNameImpl.getCached(descriptor.fqName!!.shortName().asString())
+ }
+
+ override val useSiteTarget: AnnotationUseSiteTarget? = null
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitAnnotation(this, data)
+ }
+
+ override fun toString(): String {
+ return "@${shortName.asString()}"
+ }
+}
+
+private fun ClassId.findKSClassDeclaration(): KSClassDeclaration? {
+ val ksName = KSNameImpl.getCached(this.asSingleFqName().asString().replace("$", "."))
+ return ResolverImpl.instance!!.getClassDeclarationByName(ksName)
+}
+
+private fun ClassId.findKSType(): KSType? = findKSClassDeclaration()?.asStarProjectedType()
+
+private fun <T> ConstantValue<T>.toValue(parent: KSNode): Any? = when (this) {
+ is AnnotationValue -> KSAnnotationDescriptorImpl.getCached(value, parent)
+ is ArrayValue -> value.map { it.toValue(parent) }
+ is EnumValue -> value.first.findKSClassDeclaration()?.declarations?.find {
+ it is KSClassDeclaration && it.classKind == ClassKind.ENUM_ENTRY &&
+ it.simpleName.asString() == value.second.asString()
+ }?.let { (it as KSClassDeclaration).asStarProjectedType() }
+ is KClassValue -> when (val classValue = value) {
+ is KClassValue.Value.NormalClass -> if (classValue.arrayDimensions > 0) {
+ classValue.value.classId.findKSType()?.let { componentType ->
+ var resultingType = componentType
+ for (i in 1..classValue.arrayDimensions) {
+ resultingType = ResolverImpl.instance!!.builtIns.arrayType.replace(
+ listOf(
+ ResolverImpl.instance!!.getTypeArgument(
+ KSTypeReferenceSyntheticImpl.getCached(resultingType, null), Variance.INVARIANT
+ )
+ )
+ )
+ }
+ resultingType
+ }
+ } else classValue.classId.findKSType()
+ is KClassValue.Value.LocalClass -> getKSTypeCached(classValue.type)
+ }
+ is ErrorValue, is NullValue -> null
+ else -> value
+}
+
+fun AnnotationDescriptor.createKSValueArguments(ownerAnnotation: KSAnnotation): List<KSValueArgument> {
+ val presentValueArguments = allValueArguments.map { (name, constantValue) ->
+ KSValueArgumentLiteImpl.getCached(
+ KSNameImpl.getCached(name.asString()),
+ constantValue.toValue(ownerAnnotation),
+ ownerAnnotation
+ )
+ }
+ val presentValueArgumentNames = presentValueArguments.map { it.name.asString() }
+ val argumentsFromDefault = this.type.getDefaultConstructorArguments(presentValueArgumentNames, ownerAnnotation)
+ return presentValueArguments.plus(argumentsFromDefault)
+}
+
+internal fun AnnotationDescriptor.getDefaultArguments(ownerAnnotation: KSAnnotation): List<KSValueArgument> {
+ return this.type.getDefaultConstructorArguments(emptyList(), ownerAnnotation)
+}
+
+internal fun TypeConstructor.toDeclarationDescriptor(): ClassDescriptor? {
+ if (this.declarationDescriptor !is NotFoundClasses.MockClassDescriptor) {
+ return this.declarationDescriptor as? ClassDescriptor
+ }
+ val fqName = (this.declarationDescriptor as? ClassDescriptor)?.fqNameSafe ?: return null
+ val shortNames = fqName.shortName().asString().split("$")
+ var parent = ResolverImpl.instance!!
+ .getClassDeclarationByName("${fqName.parent().asString()}.${shortNames.first()}")
+ for (i in 1 until shortNames.size) {
+ if (parent == null) {
+ return null
+ }
+ parent = parent.declarations
+ .filterIsInstance<KSClassDeclaration>()
+ .singleOrNull { it.simpleName.asString() == shortNames[i] }
+ }
+ return parent?.let { ResolverImpl.instance!!.resolveClassDeclaration(it) }
+}
+
+internal fun KotlinType.getDefaultConstructorArguments(
+ excludeNames: List<String>,
+ ownerAnnotation: KSAnnotation
+): List<KSValueArgument> {
+ return this.constructor.toDeclarationDescriptor()?.constructors?.single()
+ ?.getAbsentDefaultArguments(excludeNames, ownerAnnotation) ?: emptyList()
+}
+
+fun ClassConstructorDescriptor.getAbsentDefaultArguments(
+ excludeNames: List<String>,
+ ownerAnnotation: KSAnnotation
+): List<KSValueArgument> {
+ return this.valueParameters
+ .filterNot { param -> excludeNames.contains(param.name.asString()) || !param.hasDefaultValue() }
+ .map { param ->
+ KSValueArgumentLiteImpl.getCached(
+ KSNameImpl.getCached(param.name.asString()),
+ param.getDefaultValue(ownerAnnotation),
+ ownerAnnotation,
+ Origin.SYNTHETIC
+ )
+ }
+}
+
+fun ValueParameterDescriptor.getDefaultValue(ownerAnnotation: KSAnnotation): Any? {
+
+ // Copied from kotlin compiler
+ // TODO: expose in upstream
+ fun convertTypeToKClassValue(javaType: JavaType): KClassValue? {
+ var type = javaType
+ var arrayDimensions = 0
+ while (type is JavaArrayType) {
+ type = type.componentType
+ arrayDimensions++
+ }
+ return when (type) {
+ is JavaPrimitiveType -> {
+ val primitiveType = type.type
+ // void.class is not representable in Kotlin, we approximate it by Unit::class
+ ?: return KClassValue(ClassId.topLevel(StandardNames.FqNames.unit.toSafe()), 0)
+ if (arrayDimensions > 0) {
+ KClassValue(ClassId.topLevel(primitiveType.arrayTypeFqName), arrayDimensions - 1)
+ } else {
+ KClassValue(ClassId.topLevel(primitiveType.typeFqName), arrayDimensions)
+ }
+ }
+ is JavaClassifierType -> {
+ val fqName = FqName(type.classifierQualifiedName)
+ // TODO: support nested classes somehow
+ val classId = JavaToKotlinClassMap.mapJavaToKotlin(fqName) ?: ClassId.topLevel(fqName)
+ KClassValue(classId, arrayDimensions)
+ }
+ else -> null
+ }
+ }
+
+ // Copied from kotlin compiler
+ // TODO: expose in upstream
+ fun JavaAnnotationArgument.convert(expectedType: KotlinType): ConstantValue<*>? {
+ return when (this) {
+ is JavaLiteralAnnotationArgument -> value?.let {
+ when (value) {
+ // Note: `value` expression may be of class that does not match field type in some cases
+ // tested for Int, left other checks just in case
+ is Byte, is Short, is Int, is Long -> {
+ ConstantValueFactory.createIntegerConstantValue((value as Number).toLong(), expectedType, false)
+ }
+ else -> {
+ ConstantValueFactory.createConstantValue(value)
+ }
+ }
+ }
+ is JavaEnumValueAnnotationArgument -> {
+ enumClassId?.let { enumClassId ->
+ entryName?.let { entryName ->
+ EnumValue(enumClassId, entryName)
+ }
+ }
+ }
+ is JavaArrayAnnotationArgument -> {
+ val elementType = expectedType.builtIns.getArrayElementType(expectedType)
+ ConstantValueFactory.createArrayValue(
+ getElements().mapNotNull { it.convert(elementType) },
+ expectedType
+ )
+ }
+ is JavaAnnotationAsAnnotationArgument -> {
+ AnnotationValue(
+ LazyJavaAnnotationDescriptor(ResolverImpl.instance!!.lazyJavaResolverContext, this.getAnnotation())
+ )
+ }
+ is JavaClassObjectAnnotationArgument -> {
+ convertTypeToKClassValue(getReferencedType())
+ }
+ else -> null
+ }
+ }
+
+ val psi = this.findPsi()
+ return when (psi) {
+ null -> {
+ val file = if (this.source is JavaSourceElement) {
+ (
+ ((this.source as JavaSourceElement).javaElement as? BinaryJavaMethod)
+ ?.containingClass as? VirtualFileBoundJavaClass
+ )?.virtualFile?.contentsToByteArray()
+ } else {
+ (this.containingDeclaration.getContainingKotlinJvmBinaryClass() as? VirtualFileKotlinClass)
+ ?.file?.contentsToByteArray()
+ }
+ if (file == null) {
+ null
+ } else {
+ var defaultValue: JavaAnnotationArgument? = null
+ ClassReader(file).accept(
+ object : ClassVisitor(API_VERSION) {
+ override fun visitMethod(
+ access: Int,
+ name: String?,
+ desc: String?,
+ signature: String?,
+ exceptions: Array<out String>?
+ ): MethodVisitor {
+ return if (name == this@getDefaultValue.name.asString()) {
+ object : MethodVisitor(API_VERSION) {
+ override fun visitAnnotationDefault(): AnnotationVisitor =
+ BinaryJavaAnnotationVisitor(
+ ClassifierResolutionContext { null },
+ BinaryClassSignatureParser()
+ ) {
+ defaultValue = it
+ }
+ }
+ } else {
+ object : MethodVisitor(API_VERSION) {}
+ }
+ }
+ },
+ ClassReader.SKIP_CODE or ClassReader.SKIP_DEBUG or ClassReader.SKIP_FRAMES
+ )
+ if (!this.type.isError) {
+ defaultValue?.convert(this.type)?.toValue(ownerAnnotation)
+ } else {
+ KSErrorType
+ }
+ }
+ }
+ is KtParameter -> if (!this.type.isError) {
+ ResolverImpl.instance!!.evaluateConstant(psi.defaultValue, this.type)?.toValue(ownerAnnotation)
+ } else {
+ KSErrorType
+ }
+ is PsiAnnotationMethod -> {
+ when (psi.defaultValue) {
+ is PsiAnnotation -> KSAnnotationJavaImpl.getCached(psi.defaultValue as PsiAnnotation)
+ else -> JavaPsiFacade.getInstance(psi.project).constantEvaluationHelper
+ .computeConstantExpression((psi).defaultValue)
+ }
+ }
+ else -> throw IllegalStateException("Unexpected psi ${psi.javaClass}, $ExceptionMessage")
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassDeclarationDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassDeclarationDescriptorImpl.kt
new file mode 100644
index 00000000..94f788fb
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassDeclarationDescriptorImpl.kt
@@ -0,0 +1,203 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.*
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.symbol.impl.java.KSFunctionDeclarationJavaImpl
+import com.google.devtools.ksp.symbol.impl.java.KSPropertyDeclarationJavaImpl
+import com.google.devtools.ksp.symbol.impl.kotlin.*
+import com.google.devtools.ksp.symbol.impl.replaceTypeArguments
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiMethod
+import org.jetbrains.kotlin.builtins.StandardNames
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.psi.KtClassOrObject
+import org.jetbrains.kotlin.psi.KtFunction
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.resolve.calls.tower.isSynthesized
+import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
+import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
+import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
+import org.jetbrains.kotlin.descriptors.ClassKind as KtClassKind
+
+class KSClassDeclarationDescriptorImpl private constructor(val descriptor: ClassDescriptor) :
+ KSClassDeclaration,
+ KSDeclarationDescriptorImpl(descriptor),
+ KSExpectActual by KSExpectActualDescriptorImpl(descriptor) {
+ companion object : KSObjectCache<ClassDescriptor, KSClassDeclarationDescriptorImpl>() {
+ fun getCached(descriptor: ClassDescriptor) = cache.getOrPut(descriptor) {
+ KSClassDeclarationDescriptorImpl(descriptor)
+ }
+ }
+
+ override val classKind: ClassKind by lazy {
+ when (descriptor.kind) {
+ KtClassKind.INTERFACE -> ClassKind.INTERFACE
+ KtClassKind.CLASS -> ClassKind.CLASS
+ KtClassKind.OBJECT -> ClassKind.OBJECT
+ KtClassKind.ENUM_CLASS -> ClassKind.ENUM_CLASS
+ KtClassKind.ENUM_ENTRY -> ClassKind.ENUM_ENTRY
+ KtClassKind.ANNOTATION_CLASS -> ClassKind.ANNOTATION_CLASS
+ }
+ }
+
+ override val isCompanionObject by lazy {
+ descriptor.isCompanionObject
+ }
+
+ override fun getSealedSubclasses(): Sequence<KSClassDeclaration> {
+ return descriptor.sealedSubclassesSequence()
+ }
+
+ override fun getAllFunctions(): Sequence<KSFunctionDeclaration> = descriptor.getAllFunctions()
+
+ override fun getAllProperties(): Sequence<KSPropertyDeclaration> = descriptor.getAllProperties()
+
+ override val primaryConstructor: KSFunctionDeclaration? by lazy {
+ descriptor.unsubstitutedPrimaryConstructor?.let { KSFunctionDeclarationDescriptorImpl.getCached(it) }
+ }
+
+ // Workaround for https://github.com/google/ksp/issues/195
+ private val mockSerializableType = ResolverImpl.instance!!.mockSerializableType
+ private val javaSerializableType = ResolverImpl.instance!!.javaSerializableType
+
+ override val superTypes: Sequence<KSTypeReference> by lazy {
+
+ descriptor.defaultType.constructor.supertypes.asSequence().map { kotlinType ->
+ KSTypeReferenceDescriptorImpl.getCached(
+ javaSerializableType?.let { if (kotlinType === mockSerializableType) it else kotlinType }
+ ?: kotlinType,
+ origin,
+ this
+ )
+ }.memoized()
+ }
+
+ override val typeParameters: List<KSTypeParameter> by lazy {
+ descriptor.declaredTypeParameters.map { KSTypeParameterDescriptorImpl.getCached(it) }
+ }
+
+ override val declarations: Sequence<KSDeclaration> by lazy {
+ sequenceOf(
+ descriptor.unsubstitutedMemberScope.getDescriptorsFiltered(),
+ // FIXME: Support static, synthetic `entries` for enums when the language feature is enabled.
+ descriptor.staticScope.getDescriptorsFiltered().filterNot {
+ descriptor.kind == KtClassKind.ENUM_CLASS &&
+ it is CallableDescriptor &&
+ it.isSynthesized &&
+ it.name == StandardNames.ENUM_ENTRIES
+ },
+ descriptor.constructors
+ ).flatten()
+ .filter {
+ it is MemberDescriptor &&
+ it.visibility != DescriptorVisibilities.INHERITED &&
+ it.visibility != DescriptorVisibilities.INVISIBLE_FAKE &&
+ (it !is CallableMemberDescriptor || it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
+ }
+ .map {
+ when (it) {
+ is PropertyDescriptor -> KSPropertyDeclarationDescriptorImpl.getCached(it)
+ is FunctionDescriptor -> KSFunctionDeclarationDescriptorImpl.getCached(it)
+ is ClassDescriptor -> getCached(it)
+ else -> throw IllegalStateException("Unexpected descriptor type ${it.javaClass}, $ExceptionMessage")
+ }
+ }.memoized()
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ val modifiers = mutableSetOf<Modifier>()
+ modifiers.addAll(descriptor.toKSModifiers())
+ if (descriptor.isData) {
+ modifiers.add(Modifier.DATA)
+ }
+ if (descriptor.isInline) {
+ modifiers.add(Modifier.INLINE)
+ }
+ if (descriptor.kind == KtClassKind.ANNOTATION_CLASS) {
+ modifiers.add(Modifier.ANNOTATION)
+ }
+ if (descriptor.isInner) {
+ modifiers.add(Modifier.INNER)
+ }
+ if (descriptor.isFun) {
+ modifiers.add(Modifier.FUN)
+ }
+ if (descriptor.isValue) {
+ modifiers.add(Modifier.VALUE)
+ }
+ modifiers
+ }
+
+ override fun asType(typeArguments: List<KSTypeArgument>): KSType =
+ descriptor.defaultType.replaceTypeArguments(typeArguments)?.let {
+ getKSTypeCached(it, typeArguments)
+ } ?: KSErrorType
+
+ override fun asStarProjectedType(): KSType {
+ return getKSTypeCached(descriptor.defaultType.replaceArgumentsWithStarProjections())
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitClassDeclaration(this, data)
+ }
+}
+
+internal fun ClassDescriptor.getAllFunctions(): Sequence<KSFunctionDeclaration> {
+ ResolverImpl.instance!!.incrementalContext.recordLookupForGetAllFunctions(this)
+ val functionDescriptors = unsubstitutedMemberScope.getDescriptorsFiltered(DescriptorKindFilter.FUNCTIONS)
+ .asSequence()
+ .filter { (it as FunctionDescriptor).visibility != DescriptorVisibilities.INVISIBLE_FAKE }
+ return functionDescriptors.plus(constructors).map {
+ when (val psi = it.findPsi()) {
+ is KtFunction -> KSFunctionDeclarationImpl.getCached(psi)
+ is PsiMethod -> KSFunctionDeclarationJavaImpl.getCached(psi)
+ else -> KSFunctionDeclarationDescriptorImpl.getCached(it as FunctionDescriptor)
+ }
+ }
+}
+
+internal fun ClassDescriptor.getAllProperties(): Sequence<KSPropertyDeclaration> {
+ ResolverImpl.instance!!.incrementalContext.recordLookupForGetAllProperties(this)
+ return unsubstitutedMemberScope.getDescriptorsFiltered(DescriptorKindFilter.VARIABLES).asSequence()
+ .filter { (it as PropertyDescriptor).visibility != DescriptorVisibilities.INVISIBLE_FAKE }
+ .map {
+ when (val psi = it.findPsi()) {
+ is KtParameter -> KSPropertyDeclarationParameterImpl.getCached(psi)
+ is KtProperty -> KSPropertyDeclarationImpl.getCached(psi)
+ is PsiField -> KSPropertyDeclarationJavaImpl.getCached(psi)
+ else -> KSPropertyDeclarationDescriptorImpl.getCached(it as PropertyDescriptor)
+ }
+ }
+}
+
+internal fun ClassDescriptor.sealedSubclassesSequence(): Sequence<KSClassDeclaration> {
+ // TODO record incremental subclass lookups in Kotlin 1.5.x?
+ return sealedSubclasses
+ .asSequence()
+ .map { sealedSubClass ->
+ when (val psi = sealedSubClass.findPsi()) {
+ is KtClassOrObject -> KSClassDeclarationImpl.getCached(psi)
+ else -> KSClassDeclarationDescriptorImpl.getCached(sealedSubClass)
+ }
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassifierReferenceDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassifierReferenceDescriptorImpl.kt
new file mode 100644
index 00000000..96e086ee
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSClassifierReferenceDescriptorImpl.kt
@@ -0,0 +1,86 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.*
+import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
+import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.TypeProjection
+
+class KSClassifierReferenceDescriptorImpl private constructor(
+ val descriptor: ClassifierDescriptor,
+ val arguments: List<TypeProjection>,
+ override val origin: Origin,
+ override val parent: KSNode?
+) :
+ KSClassifierReference {
+ companion object : KSObjectCache<Triple<ClassifierDescriptor, List<TypeProjection>, Pair<KSNode?, Origin>>,
+ KSClassifierReferenceDescriptorImpl>() {
+ fun getCached(kotlinType: KotlinType, origin: Origin, parent: KSNode?) = cache.getOrPut(
+ Triple(
+ kotlinType.constructor.declarationDescriptor!!,
+ kotlinType.arguments,
+ Pair(parent, origin)
+ )
+ ) {
+ KSClassifierReferenceDescriptorImpl(
+ kotlinType.constructor.declarationDescriptor!!, kotlinType.arguments, origin, parent
+ )
+ }
+
+ fun getCached(
+ descriptor: ClassifierDescriptor,
+ arguments: List<TypeProjection>,
+ origin: Origin,
+ parent: KSNode?
+ ) = cache.getOrPut(
+ Triple(descriptor, arguments, Pair(parent, origin))
+ ) { KSClassifierReferenceDescriptorImpl(descriptor, arguments, origin, parent) }
+ }
+
+ private val nDeclaredArgs by lazy {
+ (descriptor as? ClassifierDescriptorWithTypeParameters)?.declaredTypeParameters?.size ?: 0
+ }
+
+ override val location: Location = NonExistLocation
+
+ override val qualifier: KSClassifierReference? by lazy {
+ val outerDescriptor = descriptor.containingDeclaration as? ClassifierDescriptor ?: return@lazy null
+ val outerArguments = arguments.drop(nDeclaredArgs)
+ getCached(outerDescriptor, outerArguments, origin, parent)
+ }
+
+ override val typeArguments: List<KSTypeArgument> by lazy {
+ arguments.map { KSTypeArgumentDescriptorImpl.getCached(it, origin, this.parent) }
+ }
+
+ override fun referencedName(): String {
+ val declaredArgs = if (arguments.isEmpty() || nDeclaredArgs == 0)
+ emptyList()
+ else
+ arguments.subList(0, nDeclaredArgs)
+ return descriptor.name.asString() + if (declaredArgs.isNotEmpty()) "<${
+ declaredArgs.map { it.toString() }
+ .joinToString(", ")
+ }>" else ""
+ }
+
+ override fun toString() = referencedName()
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSDeclarationDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSDeclarationDescriptorImpl.kt
new file mode 100644
index 00000000..db041b26
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSDeclarationDescriptorImpl.kt
@@ -0,0 +1,84 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import org.jetbrains.kotlin.backend.common.serialization.findPackage
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+import org.jetbrains.kotlin.resolve.descriptorUtil.parents
+import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
+import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
+
+abstract class KSDeclarationDescriptorImpl(private val descriptor: DeclarationDescriptor) : KSDeclaration {
+
+ override val origin by lazy {
+ descriptor.origin
+ }
+
+ override val containingFile: KSFile? = null
+
+ override val location: Location = NonExistLocation
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ descriptor.annotations.asSequence().map { KSAnnotationDescriptorImpl.getCached(it, this) }.memoized()
+ }
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ val containingDescriptor = descriptor.parents.first()
+ when (containingDescriptor) {
+ is ClassDescriptor -> KSClassDeclarationDescriptorImpl.getCached(containingDescriptor)
+ is FunctionDescriptor -> KSFunctionDeclarationDescriptorImpl.getCached(containingDescriptor)
+ else -> null
+ } as KSDeclaration?
+ }
+
+ override val parent: KSNode? by lazy {
+ parentDeclaration
+ }
+
+ override val packageName: KSName by lazy {
+ KSNameImpl.getCached(descriptor.findPackage().fqName.asString())
+ }
+
+ override val qualifiedName: KSName by lazy {
+ KSNameImpl.getCached(descriptor.fqNameSafe.asString())
+ }
+
+ override val simpleName: KSName by lazy {
+ KSNameImpl.getCached(descriptor.name.asString())
+ }
+
+ override fun toString(): String {
+ return this.simpleName.asString()
+ }
+
+ override val docString = null
+}
+
+val DeclarationDescriptor.origin: Origin
+ get() = if (parentsWithSelf.firstIsInstanceOrNull<JavaClassDescriptor>() != null) {
+ Origin.JAVA_LIB
+ } else {
+ Origin.KOTLIN_LIB
+ }
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSExpectActualDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSExpectActualDescriptorImpl.kt
new file mode 100644
index 00000000..7e527d77
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSExpectActualDescriptorImpl.kt
@@ -0,0 +1,50 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.processing.impl.findActualsInKSDeclaration
+import com.google.devtools.ksp.processing.impl.findExpectsInKSDeclaration
+import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSExpectActual
+import org.jetbrains.kotlin.descriptors.MemberDescriptor
+
+class KSExpectActualDescriptorImpl(val descriptor: MemberDescriptor) : KSExpectActual {
+ override val isExpect: Boolean = descriptor.isExpect
+
+ override val isActual: Boolean = descriptor.isActual
+
+ private val expects: Sequence<KSDeclaration> by lazy {
+ descriptor.findExpectsInKSDeclaration()
+ }
+
+ override fun findExpects(): Sequence<KSDeclaration> {
+ if (!isActual)
+ return emptySequence()
+ return expects
+ }
+
+ private val actuals: Sequence<KSDeclaration> by lazy {
+ descriptor.findActualsInKSDeclaration()
+ }
+
+ override fun findActuals(): Sequence<KSDeclaration> {
+ if (!isExpect)
+ return emptySequence()
+ return actuals
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSFunctionDeclarationDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSFunctionDeclarationDescriptorImpl.kt
new file mode 100644
index 00000000..0749a095
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSFunctionDeclarationDescriptorImpl.kt
@@ -0,0 +1,114 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.toFunctionKSModifiers
+import com.google.devtools.ksp.toKSModifiers
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
+import org.jetbrains.kotlin.load.java.isFromJava
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+import org.jetbrains.org.objectweb.asm.Opcodes
+
+class KSFunctionDeclarationDescriptorImpl private constructor(val descriptor: FunctionDescriptor) :
+ KSFunctionDeclaration,
+ KSDeclarationDescriptorImpl(descriptor),
+ KSExpectActual by KSExpectActualDescriptorImpl(descriptor) {
+ companion object : KSObjectCache<FunctionDescriptor, KSFunctionDeclarationDescriptorImpl>() {
+ fun getCached(descriptor: FunctionDescriptor) =
+ cache.getOrPut(descriptor) { KSFunctionDeclarationDescriptorImpl(descriptor) }
+ }
+
+ override fun findOverridee(): KSDeclaration? {
+ return descriptor?.findClosestOverridee()?.toKSDeclaration()
+ }
+
+ override val typeParameters: List<KSTypeParameter> by lazy {
+ descriptor.typeParameters.map { KSTypeParameterDescriptorImpl.getCached(it) }
+ }
+
+ override val declarations: Sequence<KSDeclaration> = emptySequence()
+
+ override val extensionReceiver: KSTypeReference? by lazy {
+ val extensionReceiver = descriptor.extensionReceiverParameter?.type
+ if (extensionReceiver != null) {
+ KSTypeReferenceDescriptorImpl.getCached(extensionReceiver, origin, this)
+ } else {
+ null
+ }
+ }
+
+ override val functionKind: FunctionKind by lazy {
+
+ when {
+ descriptor.dispatchReceiverParameter == null -> when {
+ descriptor.isFromJava -> FunctionKind.STATIC
+ else -> FunctionKind.TOP_LEVEL
+ }
+ !descriptor.name.isSpecial && !descriptor.name.asString().isEmpty() -> FunctionKind.MEMBER
+ descriptor is AnonymousFunctionDescriptor -> FunctionKind.ANONYMOUS
+ else -> throw IllegalStateException(
+ "Unable to resolve FunctionKind for ${descriptor.fqNameSafe}, $ExceptionMessage"
+ )
+ }
+ }
+
+ override val isAbstract: Boolean by lazy {
+ this.modifiers.contains(Modifier.ABSTRACT)
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ val modifiers = mutableSetOf<Modifier>()
+ modifiers.addAll(descriptor.toKSModifiers())
+ modifiers.addAll(descriptor.toFunctionKSModifiers())
+
+ if (this.origin == Origin.JAVA_LIB) {
+ if (this.jvmAccessFlag and Opcodes.ACC_STRICT != 0)
+ modifiers.add(Modifier.JAVA_STRICT)
+ if (this.jvmAccessFlag and Opcodes.ACC_SYNCHRONIZED != 0)
+ modifiers.add(Modifier.JAVA_SYNCHRONIZED)
+ }
+
+ modifiers
+ }
+
+ override val parameters: List<KSValueParameter> by lazy {
+ descriptor.valueParameters.map { KSValueParameterDescriptorImpl.getCached(it, this) }
+ }
+
+ override val returnType: KSTypeReference? by lazy {
+ val returnType = descriptor.returnType
+ if (returnType == null) {
+ null
+ } else {
+ KSTypeReferenceDescriptorImpl.getCached(returnType, origin, this)
+ }
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitFunctionDeclaration(this, data)
+ }
+
+ override fun asMemberOf(containing: KSType): KSFunction =
+ ResolverImpl.instance!!.asMemberOf(this, containing)
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSNodeDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSNodeDescriptorImpl.kt
new file mode 100644
index 00000000..0c82f750
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSNodeDescriptorImpl.kt
@@ -0,0 +1,9 @@
+package com.google.devtools.ksp.symbol.impl.binary
+
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.NonExistLocation
+
+abstract class KSNodeDescriptorImpl(override val parent: KSNode?) : KSNode {
+ override val location: Location = NonExistLocation
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyAccessorDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyAccessorDescriptorImpl.kt
new file mode 100644
index 00000000..505bb569
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyAccessorDescriptorImpl.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.toKSPropertyDeclaration
+import com.google.devtools.ksp.toFunctionKSModifiers
+import com.google.devtools.ksp.toKSModifiers
+import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
+
+abstract class KSPropertyAccessorDescriptorImpl(val descriptor: PropertyAccessorDescriptor) : KSPropertyAccessor {
+ override val origin: Origin by lazy {
+ when (receiver.origin) {
+ // if receiver is kotlin source, that means we are a synthetic where developer
+ // didn't declare an explicit accessor so we used the descriptor instead
+ Origin.KOTLIN -> Origin.SYNTHETIC
+ else -> descriptor.origin
+ }
+ }
+
+ override val receiver: KSPropertyDeclaration by lazy {
+ descriptor.correspondingProperty.toKSPropertyDeclaration()
+ }
+
+ override val parent: KSNode? by lazy {
+ receiver
+ }
+
+ override val location: Location
+ get() {
+ // if receiver is kotlin source, that means `this` is synthetic hence we want the property's location
+ // Otherwise, receiver is also from a .class file where the location will be NoLocation
+ return receiver.location
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ descriptor.annotations.asSequence().map { KSAnnotationDescriptorImpl.getCached(it, this) }.memoized()
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ val modifiers = mutableSetOf<Modifier>()
+ modifiers.addAll(descriptor.toKSModifiers())
+ modifiers.addAll(descriptor.toFunctionKSModifiers())
+ modifiers
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyDeclarationDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyDeclarationDescriptorImpl.kt
new file mode 100644
index 00000000..ad9e52f3
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyDeclarationDescriptorImpl.kt
@@ -0,0 +1,124 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.hasBackingFieldWithBinaryClassSupport
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.toKSModifiers
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.org.objectweb.asm.Opcodes
+
+class KSPropertyDeclarationDescriptorImpl private constructor(val descriptor: PropertyDescriptor) :
+ KSPropertyDeclaration,
+ KSDeclarationDescriptorImpl(descriptor),
+ KSExpectActual by KSExpectActualDescriptorImpl(descriptor) {
+ companion object : KSObjectCache<PropertyDescriptor, KSPropertyDeclarationDescriptorImpl>() {
+ fun getCached(descriptor: PropertyDescriptor) = cache.getOrPut(descriptor) {
+ KSPropertyDeclarationDescriptorImpl(descriptor)
+ }
+ }
+
+ override val extensionReceiver: KSTypeReference? by lazy {
+ if (descriptor.extensionReceiverParameter != null) {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.extensionReceiverParameter!!.type, origin, this)
+ } else {
+ null
+ }
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ // annotations on backing field will not visible in the property declaration so we query it directly to load
+ // its annotations as well.
+ val backingFieldAnnotations = descriptor.backingField?.annotations?.map {
+ KSAnnotationDescriptorImpl.getCached(it, this)
+ }.orEmpty()
+ (super.annotations + backingFieldAnnotations).memoized()
+ }
+
+ override val isMutable: Boolean by lazy {
+ descriptor.isVar
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ val modifiers = mutableSetOf<Modifier>()
+ modifiers.addAll(descriptor.toKSModifiers())
+ if (descriptor.isConst) {
+ modifiers.add(Modifier.CONST)
+ }
+ if (descriptor.isLateInit) {
+ modifiers.add(Modifier.LATEINIT)
+ }
+
+ if (this.origin == Origin.JAVA_LIB) {
+ if (this.jvmAccessFlag and Opcodes.ACC_TRANSIENT != 0)
+ modifiers.add(Modifier.JAVA_TRANSIENT)
+ if (this.jvmAccessFlag and Opcodes.ACC_VOLATILE != 0)
+ modifiers.add(Modifier.JAVA_VOLATILE)
+ }
+
+ modifiers
+ }
+
+ override val setter: KSPropertySetter? by lazy {
+ if (descriptor.setter != null) {
+ KSPropertySetterDescriptorImpl.getCached(descriptor.setter as PropertySetterDescriptor)
+ } else {
+ null
+ }
+ }
+
+ override val getter: KSPropertyGetter? by lazy {
+ if (descriptor.getter != null) {
+ KSPropertyGetterDescriptorImpl.getCached(descriptor.getter as PropertyGetterDescriptor)
+ } else {
+ null
+ }
+ }
+
+ override val typeParameters: List<KSTypeParameter> by lazy {
+ descriptor.typeParameters.map { KSTypeParameterDescriptorImpl.getCached(it) }
+ }
+
+ override val type: KSTypeReference by lazy {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.type, origin, this)
+ }
+
+ override val hasBackingField: Boolean by lazy {
+ descriptor.hasBackingFieldWithBinaryClassSupport()
+ }
+
+ override fun findOverridee(): KSPropertyDeclaration? {
+ val propertyDescriptor = ResolverImpl.instance!!.resolvePropertyDeclaration(this)
+ return propertyDescriptor?.findClosestOverridee()?.toKSPropertyDeclaration()
+ }
+
+ override fun isDelegated(): Boolean {
+ return (descriptor as? PropertyDescriptor)?.delegateField != null
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyDeclaration(this, data)
+ }
+
+ override fun asMemberOf(containing: KSType): KSType =
+ ResolverImpl.instance!!.asMemberOf(this, containing)
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyGetterDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyGetterDescriptorImpl.kt
new file mode 100644
index 00000000..a0951aad
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertyGetterDescriptorImpl.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.*
+import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
+
+class KSPropertyGetterDescriptorImpl private constructor(descriptor: PropertyGetterDescriptor) :
+ KSPropertyAccessorDescriptorImpl(descriptor), KSPropertyGetter {
+ companion object : KSObjectCache<PropertyGetterDescriptor, KSPropertyGetterDescriptorImpl>() {
+ fun getCached(descriptor: PropertyGetterDescriptor) = cache.getOrPut(descriptor) {
+ KSPropertyGetterDescriptorImpl(descriptor)
+ }
+ }
+
+ override val returnType: KSTypeReference? by lazy {
+ if (descriptor.returnType != null) {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.returnType!!, origin, this)
+ } else {
+ null
+ }
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyGetter(this, data)
+ }
+
+ override fun toString(): String {
+ return "$receiver.getter()"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertySetterDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertySetterDescriptorImpl.kt
new file mode 100644
index 00000000..834089b0
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSPropertySetterDescriptorImpl.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.*
+import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
+
+class KSPropertySetterDescriptorImpl private constructor(descriptor: PropertySetterDescriptor) :
+ KSPropertyAccessorDescriptorImpl(descriptor), KSPropertySetter {
+ companion object : KSObjectCache<PropertySetterDescriptor, KSPropertySetterDescriptorImpl>() {
+ fun getCached(descriptor: PropertySetterDescriptor) = cache.getOrPut(descriptor) {
+ KSPropertySetterDescriptorImpl(descriptor)
+ }
+ }
+
+ override val parameter: KSValueParameter by lazy {
+ descriptor.valueParameters.singleOrNull()?.let { KSValueParameterDescriptorImpl.getCached(it, this) }
+ ?: throw IllegalStateException("Failed to resolve property type")
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertySetter(this, data)
+ }
+
+ override fun toString(): String {
+ return "$receiver.setter()"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeAliasDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeAliasDescriptorImpl.kt
new file mode 100644
index 00000000..29dc0613
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeAliasDescriptorImpl.kt
@@ -0,0 +1,38 @@
+package com.google.devtools.ksp.symbol.impl.binary
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.toKSModifiers
+import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
+
+class KSTypeAliasDescriptorImpl(descriptor: TypeAliasDescriptor) :
+ KSTypeAlias,
+ KSDeclarationDescriptorImpl(descriptor),
+ KSExpectActual by KSExpectActualDescriptorImpl(descriptor) {
+ companion object : KSObjectCache<TypeAliasDescriptor, KSTypeAliasDescriptorImpl>() {
+ fun getCached(descriptor: TypeAliasDescriptor) = KSTypeAliasDescriptorImpl.cache.getOrPut(descriptor) {
+ KSTypeAliasDescriptorImpl(descriptor)
+ }
+ }
+
+ override val name: KSName by lazy {
+ KSNameImpl.getCached(descriptor.name.asString())
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ descriptor.toKSModifiers()
+ }
+
+ override val typeParameters: List<KSTypeParameter> by lazy {
+ descriptor.declaredTypeParameters.map { KSTypeParameterDescriptorImpl.getCached(it) }
+ }
+
+ override val type: KSTypeReference by lazy {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.underlyingType, origin, this)
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeAlias(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeArgumentDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeArgumentDescriptorImpl.kt
new file mode 100644
index 00000000..5b76e27a
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeArgumentDescriptorImpl.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.IdKeyTriple
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.Variance
+import com.google.devtools.ksp.symbol.impl.kotlin.KSTypeArgumentImpl
+import org.jetbrains.kotlin.types.TypeProjection
+
+class KSTypeArgumentDescriptorImpl private constructor(
+ val descriptor: TypeProjection,
+ override val origin: Origin,
+ override val parent: KSNode?
+) : KSTypeArgumentImpl() {
+ companion object : KSObjectCache<IdKeyTriple<TypeProjection, Origin, KSNode?>, KSTypeArgumentDescriptorImpl>() {
+ fun getCached(descriptor: TypeProjection, origin: Origin, parent: KSNode?) = cache
+ .getOrPut(IdKeyTriple(descriptor, origin, parent)) {
+ KSTypeArgumentDescriptorImpl(descriptor, origin, parent)
+ }
+ }
+
+ override val location: Location = NonExistLocation
+
+ override val type: KSTypeReference by lazy {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.type, origin, if (parent != null) this else null)
+ }
+
+ override val variance: Variance by lazy {
+ if (descriptor.isStarProjection)
+ Variance.STAR
+ else {
+ when (descriptor.projectionKind) {
+ org.jetbrains.kotlin.types.Variance.IN_VARIANCE -> Variance.CONTRAVARIANT
+ org.jetbrains.kotlin.types.Variance.OUT_VARIANCE -> Variance.COVARIANT
+ else -> Variance.INVARIANT
+ }
+ }
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ descriptor.type.annotations.asSequence().map { KSAnnotationDescriptorImpl.getCached(it, this) }
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeParameterDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeParameterDescriptorImpl.kt
new file mode 100644
index 00000000..98de3b98
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeParameterDescriptorImpl.kt
@@ -0,0 +1,74 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.kotlin.KSExpectActualNoImpl
+import com.google.devtools.ksp.toKSVariance
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+
+class KSTypeParameterDescriptorImpl private constructor(val descriptor: TypeParameterDescriptor) :
+ KSTypeParameter,
+ KSDeclarationDescriptorImpl(descriptor),
+ KSExpectActual by KSExpectActualNoImpl() {
+ companion object : KSObjectCache<TypeParameterDescriptor, KSTypeParameterDescriptorImpl>() {
+ fun getCached(descriptor: TypeParameterDescriptor) = cache.getOrPut(descriptor) {
+ KSTypeParameterDescriptorImpl(descriptor)
+ }
+ }
+
+ override val bounds: Sequence<KSTypeReference> by lazy {
+ descriptor.upperBounds.asSequence().map { KSTypeReferenceDescriptorImpl.getCached(it, origin, this) }
+ }
+
+ override val typeParameters: List<KSTypeParameter> = emptyList()
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ when (val parent = descriptor.containingDeclaration) {
+ is ClassDescriptor -> KSClassDeclarationDescriptorImpl.getCached(parent)
+ is FunctionDescriptor -> KSFunctionDeclarationDescriptorImpl.getCached(parent)
+ is PropertyDescriptor -> KSPropertyDeclarationDescriptorImpl.getCached(parent)
+ else -> throw IllegalStateException(
+ "Unexpected containing declaration for ${descriptor.fqNameSafe}, $ExceptionMessage"
+ )
+ }
+ }
+
+ override val modifiers: Set<Modifier> = emptySet()
+
+ override val isReified: Boolean by lazy {
+ descriptor.isReified
+ }
+
+ override val name: KSName by lazy {
+ KSNameImpl.getCached(descriptor.name.asString())
+ }
+
+ override val variance: Variance = descriptor.variance.toKSVariance()
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeParameter(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeReferenceDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeReferenceDescriptorImpl.kt
new file mode 100644
index 00000000..91f68fa4
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSTypeReferenceDescriptorImpl.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.IdKeyTriple
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSReferenceElement
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.Modifier
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.kotlin.getKSTypeCached
+import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
+import org.jetbrains.kotlin.types.AbbreviatedType
+import org.jetbrains.kotlin.types.KotlinType
+
+class KSTypeReferenceDescriptorImpl private constructor(
+ val kotlinType: KotlinType,
+ override val origin: Origin,
+ override val parent: KSNode?
+) : KSTypeReference {
+ companion object : KSObjectCache<IdKeyTriple<KotlinType, Origin, KSNode?>, KSTypeReferenceDescriptorImpl>() {
+ fun getCached(kotlinType: KotlinType, origin: Origin, parent: KSNode?) = cache
+ .getOrPut(IdKeyTriple(kotlinType, origin, parent)) {
+ KSTypeReferenceDescriptorImpl(kotlinType, origin, parent)
+ }
+ }
+
+ private fun KotlinType.findAlias(): KotlinType =
+ (kotlinType as? AbbreviatedType)?.abbreviation ?: this
+
+ override val location: Location = NonExistLocation
+
+ override val element: KSReferenceElement by lazy {
+ KSClassifierReferenceDescriptorImpl.getCached(kotlinType.findAlias(), origin, this)
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ kotlinType.annotations.asSequence().map { KSAnnotationDescriptorImpl.getCached(it, this) }.memoized()
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ if (kotlinType.isSuspendFunctionTypeOrSubtype) {
+ setOf(Modifier.SUSPEND)
+ } else {
+ emptySet<Modifier>()
+ }
+ }
+
+ override fun resolve(): KSType {
+ return getKSTypeCached(kotlinType)
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeReference(this, data)
+ }
+
+ override fun toString(): String {
+ return element.toString()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSValueParameterDescriptorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSValueParameterDescriptorImpl.kt
new file mode 100644
index 00000000..29f53a45
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/binary/KSValueParameterDescriptorImpl.kt
@@ -0,0 +1,78 @@
+/*
+ * 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.symbol.impl.binary
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
+import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
+import org.jetbrains.kotlin.resolve.calls.components.isVararg
+
+class KSValueParameterDescriptorImpl private constructor(
+ val descriptor: ValueParameterDescriptor,
+ override val parent: KSNode?
+) : KSValueParameter {
+ companion object : KSObjectCache<Pair<ValueParameterDescriptor, KSNode?>, KSValueParameterDescriptorImpl>() {
+ fun getCached(descriptor: ValueParameterDescriptor, parent: KSNode?) = cache
+ .getOrPut(Pair(descriptor, parent)) { KSValueParameterDescriptorImpl(descriptor, parent) }
+ }
+
+ override val origin by lazy {
+ descriptor.origin
+ }
+
+ override val location: Location = NonExistLocation
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ descriptor.annotations.asSequence().map { KSAnnotationDescriptorImpl.getCached(it, this) }
+ }
+
+ override val isCrossInline: Boolean = descriptor.isCrossinline
+
+ override val isNoInline: Boolean = descriptor.isNoinline
+
+ override val isVararg: Boolean = descriptor.isVararg
+
+ override val isVal: Boolean = !descriptor.isVar
+
+ override val isVar: Boolean = descriptor.isVar
+
+ override val name: KSName? by lazy {
+ KSNameImpl.getCached(descriptor.name.asString())
+ }
+
+ override val type: KSTypeReference by lazy {
+ // Descriptor wraps vararg with Array<>, to align with the actual behavior in source.
+ if (isVararg) {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.varargElementType!!, origin, this)
+ } else {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.type, origin, this)
+ }
+ }
+
+ override val hasDefault: Boolean = descriptor.hasDefaultValue()
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitValueParameter(this, data)
+ }
+
+ override fun toString(): String {
+ return name?.asString() ?: "_"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSAnnotationJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSAnnotationJavaImpl.kt
new file mode 100644
index 00000000..f6ae397b
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSAnnotationJavaImpl.kt
@@ -0,0 +1,160 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.getClassDeclarationByName
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.binary.getAbsentDefaultArguments
+import com.google.devtools.ksp.symbol.impl.binary.getDefaultConstructorArguments
+import com.google.devtools.ksp.symbol.impl.kotlin.KSTypeImpl
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.intellij.lang.jvm.JvmClassKind
+import com.intellij.psi.*
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+
+class KSAnnotationJavaImpl private constructor(val psi: PsiAnnotation) : KSAnnotation {
+ companion object : KSObjectCache<PsiAnnotation, KSAnnotationJavaImpl>() {
+ fun getCached(psi: PsiAnnotation) = cache.getOrPut(psi) { KSAnnotationJavaImpl(psi) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+
+ override val parent: KSNode? by lazy {
+ var parentPsi = psi.parent
+ while (true) {
+ when (parentPsi) {
+ null, is PsiJavaFile, is PsiClass, is PsiMethod, is PsiParameter, is PsiTypeParameter, is PsiType ->
+ break
+ else -> parentPsi = parentPsi.parent
+ }
+ }
+ when (parentPsi) {
+ is PsiJavaFile -> KSFileJavaImpl.getCached(parentPsi)
+ is PsiClass -> KSClassDeclarationJavaImpl.getCached(parentPsi)
+ is PsiMethod -> KSFunctionDeclarationJavaImpl.getCached(parentPsi)
+ is PsiParameter -> KSValueParameterJavaImpl.getCached(parentPsi)
+ is PsiTypeParameter -> KSTypeParameterJavaImpl.getCached(parentPsi)
+ is PsiType ->
+ if (parentPsi.parent is PsiClassType) KSTypeArgumentJavaImpl.getCached(parentPsi, this)
+ else KSTypeReferenceJavaImpl.getCached(parentPsi, this)
+ else -> null
+ }
+ }
+
+ override val annotationType: KSTypeReference by lazy {
+ KSTypeReferenceLiteJavaImpl.getCached(psi, this)
+ }
+
+ override val arguments: List<KSValueArgument> by lazy {
+ val annotationConstructor = (
+ (annotationType.resolve() as? KSTypeImpl)?.kotlinType?.constructor
+ ?.declarationDescriptor as? ClassDescriptor
+ )?.constructors?.single()
+ val presentValueArguments = psi.parameterList.attributes
+ .mapIndexed { index, it ->
+ // use the name in the attribute if it is explicitly specified, otherwise, fall back to index.
+ val name = it.name ?: annotationConstructor?.valueParameters?.getOrNull(index)?.name?.asString()
+ val value = it.value
+ val calculatedValue: Any? = if (value is PsiArrayInitializerMemberValue) {
+ value.initializers.map {
+ calcValue(it)
+ }
+ } else {
+ calcValue(it.value)
+ }
+ KSValueArgumentJavaImpl.getCached(
+ name = name?.let(KSNameImpl::getCached),
+ value = calculatedValue,
+ this
+ )
+ }
+ val presentValueArgumentNames = presentValueArguments.map { it.name?.asString() ?: "" }
+ val argumentsFromDefault = annotationConstructor?.let {
+ it.getAbsentDefaultArguments(presentValueArgumentNames, this)
+ } ?: emptyList()
+ presentValueArguments.plus(argumentsFromDefault)
+ }
+
+ override val defaultArguments: List<KSValueArgument> by lazy {
+ val kotlinType = (annotationType.resolve() as? KSTypeImpl)?.kotlinType
+ kotlinType?.getDefaultConstructorArguments(emptyList(), this) ?: emptyList()
+ }
+
+ private fun calcValue(value: PsiAnnotationMemberValue?): Any? {
+ if (value is PsiAnnotation) {
+ return getCached(value)
+ }
+ val result = when (value) {
+ is PsiReference -> value.resolve()?.let { resolved ->
+ JavaPsiFacade.getInstance(value.project).constantEvaluationHelper.computeConstantExpression(value)
+ ?: resolved
+ }
+ else -> value?.let {
+ JavaPsiFacade.getInstance(value.project).constantEvaluationHelper.computeConstantExpression(value)
+ }
+ }
+ return when (result) {
+ is PsiType -> {
+ ResolverImpl.instance!!.resolveJavaTypeInAnnotations(result)
+ }
+ is PsiLiteralValue -> {
+ result.value
+ }
+ is PsiField -> {
+ // manually handle enums as constant expression evaluator does not seem to be resolving them.
+ val containingClass = result.containingClass
+ if (containingClass?.classKind == JvmClassKind.ENUM) {
+ // this is an enum entry
+ containingClass.qualifiedName?.let {
+ ResolverImpl.instance!!.getClassDeclarationByName(it)
+ }?.declarations?.find {
+ it is KSClassDeclaration && it.classKind == ClassKind.ENUM_ENTRY &&
+ it.simpleName.asString() == result.name
+ }?.let { (it as KSClassDeclaration).asStarProjectedType() }
+ ?.let {
+ return it
+ }
+ } else {
+ null
+ }
+ }
+ else -> result
+ }
+ }
+
+ override val shortName: KSName by lazy {
+ KSNameImpl.getCached(psi.qualifiedName!!.split(".").last())
+ }
+
+ override val useSiteTarget: AnnotationUseSiteTarget? = null
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitAnnotation(this, data)
+ }
+
+ override fun toString(): String {
+ return "@${shortName.asString()}"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaEnumEntryImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaEnumEntryImpl.kt
new file mode 100644
index 00000000..05f017be
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaEnumEntryImpl.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.symbol.impl.binary.getAllFunctions
+import com.google.devtools.ksp.symbol.impl.binary.getAllProperties
+import com.google.devtools.ksp.symbol.impl.kotlin.KSErrorType
+import com.google.devtools.ksp.symbol.impl.kotlin.KSExpectActualNoImpl
+import com.google.devtools.ksp.symbol.impl.kotlin.getKSTypeCached
+import com.google.devtools.ksp.toKSModifiers
+import com.intellij.psi.PsiEnumConstant
+import com.intellij.psi.PsiJavaFile
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+
+class KSClassDeclarationJavaEnumEntryImpl private constructor(val psi: PsiEnumConstant) :
+ KSClassDeclaration,
+ KSDeclarationJavaImpl(psi),
+ KSExpectActual by KSExpectActualNoImpl() {
+ companion object : KSObjectCache<PsiEnumConstant, KSClassDeclarationJavaEnumEntryImpl>() {
+ fun getCached(psi: PsiEnumConstant) = cache.getOrPut(psi) { KSClassDeclarationJavaEnumEntryImpl(psi) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }
+ }
+
+ override val classKind: ClassKind = ClassKind.ENUM_ENTRY
+
+ override val containingFile: KSFile? by lazy {
+ KSFileJavaImpl.getCached(psi.containingFile as PsiJavaFile)
+ }
+
+ override val isCompanionObject = false
+
+ override fun getSealedSubclasses(): Sequence<KSClassDeclaration> = emptySequence()
+
+ private val descriptor: ClassDescriptor? by lazy {
+ ResolverImpl.instance!!.resolveJavaDeclaration(psi) as ClassDescriptor
+ }
+
+ override fun getAllFunctions(): Sequence<KSFunctionDeclaration> =
+ descriptor?.getAllFunctions() ?: emptySequence()
+
+ override fun getAllProperties(): Sequence<KSPropertyDeclaration> =
+ descriptor?.getAllProperties() ?: emptySequence()
+
+ override val declarations: Sequence<KSDeclaration> = emptySequence()
+
+ override val modifiers: Set<Modifier> by lazy {
+ psi.toKSModifiers()
+ }
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ psi.findParentDeclaration()
+ }
+
+ override val primaryConstructor: KSFunctionDeclaration? = null
+
+ override val qualifiedName: KSName by lazy {
+ KSNameImpl.getCached("${parentDeclaration!!.qualifiedName!!.asString()}.${psi.name}")
+ }
+
+ override val simpleName: KSName by lazy {
+ KSNameImpl.getCached(psi.name)
+ }
+
+ override val superTypes: Sequence<KSTypeReference> = emptySequence()
+
+ override val typeParameters: List<KSTypeParameter> = emptyList()
+
+ // Enum can't have type parameters.
+ override fun asType(typeArguments: List<KSTypeArgument>): KSType {
+ if (typeArguments.isNotEmpty())
+ return KSErrorType
+ return asStarProjectedType()
+ }
+
+ override fun asStarProjectedType(): KSType {
+ return getKSTypeCached(descriptor!!.defaultType)
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitClassDeclaration(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaImpl.kt
new file mode 100644
index 00000000..f12933f8
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassDeclarationJavaImpl.kt
@@ -0,0 +1,173 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.isConstructor
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.processing.impl.workaroundForNested
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.symbol.impl.binary.getAllFunctions
+import com.google.devtools.ksp.symbol.impl.binary.getAllProperties
+import com.google.devtools.ksp.symbol.impl.kotlin.KSErrorType
+import com.google.devtools.ksp.symbol.impl.kotlin.KSExpectActualNoImpl
+import com.google.devtools.ksp.symbol.impl.kotlin.getKSTypeCached
+import com.google.devtools.ksp.symbol.impl.replaceTypeArguments
+import com.google.devtools.ksp.symbol.impl.synthetic.KSConstructorSyntheticImpl
+import com.google.devtools.ksp.toKSModifiers
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiEnumConstant
+import com.intellij.psi.PsiJavaFile
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
+import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
+
+class KSClassDeclarationJavaImpl private constructor(val psi: PsiClass) :
+ KSClassDeclaration,
+ KSDeclarationJavaImpl(psi),
+ KSExpectActual by KSExpectActualNoImpl() {
+ companion object : KSObjectCache<PsiClass, KSClassDeclarationJavaImpl>() {
+ fun getCached(psi: PsiClass) = cache.getOrPut(psi) { KSClassDeclarationJavaImpl(psi) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }.memoized()
+ }
+
+ override val classKind: ClassKind by lazy {
+ when {
+ psi.isAnnotationType -> ClassKind.ANNOTATION_CLASS
+ psi.isInterface -> ClassKind.INTERFACE
+ psi.isEnum -> ClassKind.ENUM_CLASS
+ else -> ClassKind.CLASS
+ }
+ }
+
+ override val containingFile: KSFile? by lazy {
+ KSFileJavaImpl.getCached(psi.containingFile as PsiJavaFile)
+ }
+
+ override val isCompanionObject = false
+
+ // Could the resolution ever fail?
+ private val descriptor: ClassDescriptor? by lazy {
+ ResolverImpl.instance!!.moduleClassResolver.resolveClass(JavaClassImpl(psi).apply { workaroundForNested() })
+ }
+
+ // TODO in 1.5 + jvmTarget 15, will we return Java permitted types?
+ override fun getSealedSubclasses(): Sequence<KSClassDeclaration> = emptySequence()
+
+ override fun getAllFunctions(): Sequence<KSFunctionDeclaration> =
+ descriptor?.getAllFunctions() ?: emptySequence()
+
+ override fun getAllProperties(): Sequence<KSPropertyDeclaration> =
+ descriptor?.getAllProperties() ?: emptySequence()
+
+ override val declarations: Sequence<KSDeclaration> by lazy {
+ val allDeclarations = (
+ psi.fields.asSequence().map {
+ when (it) {
+ is PsiEnumConstant -> KSClassDeclarationJavaEnumEntryImpl.getCached(it)
+ else -> KSPropertyDeclarationJavaImpl.getCached(it)
+ }
+ } +
+ psi.innerClasses.map { KSClassDeclarationJavaImpl.getCached(it) } +
+ psi.constructors.map { KSFunctionDeclarationJavaImpl.getCached(it) } +
+ psi.methods.map { KSFunctionDeclarationJavaImpl.getCached(it) }
+ )
+ .distinct()
+ // java annotation classes are interface. they get a constructor in .class
+ // hence they should get one here.
+ if (classKind == ClassKind.ANNOTATION_CLASS || !psi.isInterface) {
+ val hasConstructor = allDeclarations.any {
+ it is KSFunctionDeclaration && it.isConstructor()
+ }
+ if (hasConstructor) {
+ allDeclarations.memoized()
+ } else {
+ (allDeclarations + KSConstructorSyntheticImpl.getCached(this)).memoized()
+ }
+ } else {
+ allDeclarations.memoized()
+ }
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ val modifiers = mutableSetOf<Modifier>()
+ modifiers.addAll(psi.toKSModifiers())
+ if (psi.isAnnotationType) {
+ modifiers.add(Modifier.ANNOTATION)
+ }
+ if (psi.isEnum) {
+ modifiers.add(Modifier.ENUM)
+ }
+ modifiers
+ }
+
+ override val primaryConstructor: KSFunctionDeclaration? = null
+
+ override val qualifiedName: KSName by lazy {
+ KSNameImpl.getCached(psi.qualifiedName!!)
+ }
+
+ override val simpleName: KSName by lazy {
+ KSNameImpl.getCached(psi.name!!)
+ }
+
+ override val superTypes: Sequence<KSTypeReference> by lazy {
+ val adjusted = if (!psi.isInterface && psi.superTypes.size > 1) {
+ psi.superTypes.filterNot {
+ it.className == "Object" && it.canonicalText == "java.lang.Object"
+ }
+ } else {
+ psi.superTypes.toList()
+ }
+ adjusted.asSequence().map { KSTypeReferenceJavaImpl.getCached(it, this) }.memoized()
+ }
+
+ override val typeParameters: List<KSTypeParameter> by lazy {
+ psi.typeParameters.map { KSTypeParameterJavaImpl.getCached(it) }
+ }
+
+ override fun asType(typeArguments: List<KSTypeArgument>): KSType {
+ return descriptor?.let {
+ it.defaultType.replaceTypeArguments(typeArguments)?.let {
+ getKSTypeCached(it, typeArguments)
+ }
+ } ?: KSErrorType
+ }
+
+ override fun asStarProjectedType(): KSType {
+ return descriptor?.let {
+ getKSTypeCached(it.defaultType.replaceArgumentsWithStarProjections())
+ } ?: KSErrorType
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitClassDeclaration(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassifierReferenceJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassifierReferenceJavaImpl.kt
new file mode 100644
index 00000000..748a0b93
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassifierReferenceJavaImpl.kt
@@ -0,0 +1,66 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.getInstanceForCurrentRound
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.intellij.psi.PsiClassType
+import com.intellij.psi.PsiJavaCodeReferenceElement
+import com.intellij.psi.impl.source.PsiClassReferenceType
+
+class KSClassifierReferenceJavaImpl private constructor(
+ val psi: PsiClassType,
+ override val parent: KSNode
+) : KSClassifierReference {
+ companion object : KSObjectCache<Pair<PsiClassType, KSNode>, KSClassifierReferenceJavaImpl>() {
+ fun getCached(psi: PsiClassType, parent: KSNode): KSClassifierReferenceJavaImpl {
+ val curParent = getInstanceForCurrentRound(parent) as KSTypeReference
+ return cache.getOrPut(Pair(psi, curParent)) { KSClassifierReferenceJavaImpl(psi, curParent) }
+ }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ (psi as? PsiJavaCodeReferenceElement)?.toLocation() ?: NonExistLocation
+ }
+
+ override val qualifier: KSClassifierReference? by lazy {
+ val qualifierReference = (psi as? PsiClassReferenceType)?.reference?.qualifier as? PsiJavaCodeReferenceElement
+ ?: return@lazy null
+ val qualifierType = PsiClassReferenceType(qualifierReference, psi.languageLevel)
+ getCached(qualifierType, parent)
+ }
+
+ // PsiClassType.parameters is semantically argument
+ override val typeArguments: List<KSTypeArgument> by lazy {
+ psi.parameters.map { KSTypeArgumentJavaImpl.getCached(it, this) }
+ }
+
+ override fun referencedName(): String {
+ return psi.className + if (psi.parameterCount > 0) "<${
+ psi.parameters.joinToString(", ") {
+ it.presentableText
+ }
+ }>" else ""
+ }
+
+ override fun toString() = referencedName()
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassifierReferenceLiteImplForJava.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassifierReferenceLiteImplForJava.kt
new file mode 100644
index 00000000..3d2a0624
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSClassifierReferenceLiteImplForJava.kt
@@ -0,0 +1,50 @@
+package com.google.devtools.ksp.symbol.impl.java
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.KSClassifierReference
+import com.google.devtools.ksp.symbol.KSTypeArgument
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.intellij.psi.PsiAnnotation
+import com.intellij.psi.PsiMethod
+
+class KSClassifierReferenceLiteImplForJava(
+ override val parent: KSTypeReferenceLiteJavaImpl,
+ private val name: String?
+) : KSClassifierReference {
+ companion object : KSObjectCache<Pair<KSTypeReferenceLiteJavaImpl, String?>, KSClassifierReference>() {
+ fun getCached(parent: KSTypeReferenceLiteJavaImpl, name: String? = null) =
+ KSClassifierReferenceLiteImplForJava.cache
+ .getOrPut(Pair(parent, name)) { KSClassifierReferenceLiteImplForJava(parent, name) }
+ }
+ override val qualifier: KSClassifierReference? by lazy {
+ val referencedName = referencedName()
+ if (referencedName.lastIndexOf('.') == -1) {
+ null
+ } else {
+ getCached(parent, referencedName.substringBeforeLast('.'))
+ }
+ }
+
+ override fun referencedName(): String {
+ return name ?: when (parent.psiElement) {
+ is PsiAnnotation -> parent.psiElement.nameReferenceElement?.text ?: "<ERROR>"
+ is PsiMethod -> parent.psiElement.name
+ else -> throw IllegalStateException(
+ "Unexpected psi type in KSTypeReferenceLiteJavaImpl: ${parent.psiElement.javaClass}, $ExceptionMessage"
+ )
+ }
+ }
+
+ override val typeArguments: List<KSTypeArgument> = emptyList()
+
+ override val origin: Origin = Origin.JAVA
+
+ override val location: Location = NonExistLocation
+
+ override fun toString(): String {
+ return referencedName()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSDeclarationJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSDeclarationJavaImpl.kt
new file mode 100644
index 00000000..3609a5a3
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSDeclarationJavaImpl.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.getDocString
+import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSName
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.impl.findParentAnnotated
+import com.google.devtools.ksp.symbol.impl.findParentDeclaration
+import com.intellij.psi.PsiElement
+
+abstract class KSDeclarationJavaImpl(private val psi: PsiElement) : KSDeclaration {
+ override val packageName: KSName by lazy {
+ this.containingFile!!.packageName
+ }
+
+ override fun toString(): String {
+ return this.simpleName.asString()
+ }
+
+ override val docString by lazy {
+ psi.getDocString()
+ }
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ psi.findParentDeclaration()
+ }
+
+ override val parent: KSNode? by lazy {
+ psi.findParentAnnotated()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSFileJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSFileJavaImpl.kt
new file mode 100644
index 00000000..e49eea06
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSFileJavaImpl.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.intellij.psi.PsiJavaFile
+
+class KSFileJavaImpl private constructor(val psi: PsiJavaFile) : KSFile {
+ companion object : KSObjectCache<PsiJavaFile, KSFileJavaImpl>() {
+ fun getCached(psi: PsiJavaFile) = cache.getOrPut(psi) { KSFileJavaImpl(psi) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+ override val parent: KSNode? = null
+
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override val declarations: Sequence<KSDeclaration> by lazy {
+ psi.classes.asSequence().map { KSClassDeclarationJavaImpl.getCached(it) }.memoized()
+ }
+
+ override val fileName: String by lazy {
+ psi.name
+ }
+
+ override val filePath: String by lazy {
+ psi.virtualFile.path
+ }
+
+ override val packageName: KSName = KSNameImpl.getCached(psi.packageName)
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitFile(this, data)
+ }
+
+ override fun toString(): String {
+ return "File: ${this.fileName}"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSFunctionDeclarationJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSFunctionDeclarationJavaImpl.kt
new file mode 100644
index 00000000..1513fffc
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSFunctionDeclarationJavaImpl.kt
@@ -0,0 +1,125 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.symbol.impl.kotlin.KSExpectActualNoImpl
+import com.google.devtools.ksp.toKSModifiers
+import com.intellij.lang.jvm.JvmModifier
+import com.intellij.psi.PsiJavaFile
+import com.intellij.psi.PsiMethod
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+
+class KSFunctionDeclarationJavaImpl private constructor(val psi: PsiMethod) :
+ KSFunctionDeclaration,
+ KSDeclarationJavaImpl(psi),
+ KSExpectActual by KSExpectActualNoImpl() {
+ companion object : KSObjectCache<PsiMethod, KSFunctionDeclarationJavaImpl>() {
+ fun getCached(psi: PsiMethod) = cache.getOrPut(psi) { KSFunctionDeclarationJavaImpl(psi) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }.memoized()
+ }
+
+ override val containingFile: KSFile? by lazy {
+ KSFileJavaImpl.getCached(psi.containingFile as PsiJavaFile)
+ }
+
+ override fun findOverridee(): KSDeclaration? {
+ val descriptor = ResolverImpl.instance!!.resolveFunctionDeclaration(this)
+ return (descriptor as? FunctionDescriptor)?.findClosestOverridee()?.toKSDeclaration()
+ }
+
+ override val declarations: Sequence<KSDeclaration> = emptySequence()
+
+ override val extensionReceiver: KSTypeReference? = null
+
+ override val functionKind: FunctionKind = when {
+ psi.hasModifier(JvmModifier.STATIC) -> FunctionKind.STATIC
+ else -> FunctionKind.MEMBER
+ }
+
+ override val isAbstract: Boolean by lazy {
+ this.modifiers.contains(Modifier.ABSTRACT) ||
+ (
+ (this.parentDeclaration as? KSClassDeclaration)?.classKind == ClassKind.INTERFACE &&
+ !this.modifiers.contains(Modifier.JAVA_DEFAULT) && functionKind != FunctionKind.STATIC
+ )
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ psi.toKSModifiers()
+ }
+
+ override val parameters: List<KSValueParameter> by lazy {
+ psi.parameterList.parameters.map { KSValueParameterJavaImpl.getCached(it) }
+ }
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ psi.findParentDeclaration()
+ }
+
+ override val qualifiedName: KSName by lazy {
+ KSNameImpl.getCached("${parentDeclaration?.qualifiedName?.asString()}.${this.simpleName.asString()}")
+ }
+
+ override val returnType: KSTypeReference? by lazy {
+ when {
+ psi.returnType != null -> {
+ KSTypeReferenceJavaImpl.getCached(psi.returnType!!, this)
+ }
+ psi.isConstructor -> {
+ KSTypeReferenceLiteJavaImpl.getCached(psi, this)
+ }
+ else -> {
+ null
+ }
+ }
+ }
+
+ override val simpleName: KSName by lazy {
+ if (psi.isConstructor) {
+ KSNameImpl.getCached("<init>")
+ } else {
+ KSNameImpl.getCached(psi.name)
+ }
+ }
+
+ override val typeParameters: List<KSTypeParameter> by lazy {
+ psi.typeParameters.map { KSTypeParameterJavaImpl.getCached(it) }
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitFunctionDeclaration(this, data)
+ }
+
+ override fun asMemberOf(containing: KSType): KSFunction =
+ ResolverImpl.instance!!.asMemberOf(this, containing)
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSNodeJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSNodeJavaImpl.kt
new file mode 100644
index 00000000..860fb5fa
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSNodeJavaImpl.kt
@@ -0,0 +1,12 @@
+package com.google.devtools.ksp.symbol.impl.java
+
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.intellij.psi.PsiElement
+
+abstract class KSNodeJavaImpl(private val psi: PsiElement, override val parent: KSNode?) : KSNode {
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSPropertyDeclarationJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSPropertyDeclarationJavaImpl.kt
new file mode 100644
index 00000000..57ff5941
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSPropertyDeclarationJavaImpl.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.symbol.impl.kotlin.KSExpectActualNoImpl
+import com.google.devtools.ksp.toKSModifiers
+import com.intellij.psi.PsiField
+import com.intellij.psi.PsiJavaFile
+
+class KSPropertyDeclarationJavaImpl private constructor(val psi: PsiField) :
+ KSPropertyDeclaration,
+ KSDeclarationJavaImpl(psi),
+ KSExpectActual by KSExpectActualNoImpl() {
+ companion object : KSObjectCache<PsiField, KSPropertyDeclarationJavaImpl>() {
+ fun getCached(psi: PsiField) = cache.getOrPut(psi) { KSPropertyDeclarationJavaImpl(psi) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+
+ override val isMutable: Boolean
+ get() = !modifiers.contains(Modifier.FINAL)
+
+ override val hasBackingField: Boolean
+ get() = true
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }.memoized()
+ }
+
+ override val containingFile: KSFile? by lazy {
+ KSFileJavaImpl.getCached(psi.containingFile as PsiJavaFile)
+ }
+
+ override val extensionReceiver: KSTypeReference? = null
+
+ override val getter: KSPropertyGetter? = null
+
+ override val setter: KSPropertySetter? = null
+
+ override val modifiers: Set<Modifier> by lazy {
+ psi.toKSModifiers()
+ }
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ psi.findParentDeclaration()
+ }
+
+ override val qualifiedName: KSName by lazy {
+ KSNameImpl.getCached("${parentDeclaration?.qualifiedName?.asString()}.${this.simpleName.asString()}")
+ }
+
+ override val simpleName: KSName by lazy {
+ KSNameImpl.getCached(psi.name)
+ }
+
+ override val typeParameters: List<KSTypeParameter> = emptyList()
+
+ override val type: KSTypeReference by lazy {
+ KSTypeReferenceJavaImpl.getCached(psi.type, this)
+ }
+
+ override fun findOverridee(): KSPropertyDeclaration? {
+ return null
+ }
+
+ override fun isDelegated(): Boolean {
+ return false
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyDeclaration(this, data)
+ }
+
+ override fun asMemberOf(containing: KSType): KSType =
+ ResolverImpl.instance!!.asMemberOf(this, containing)
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeArgumentJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeArgumentJavaImpl.kt
new file mode 100644
index 00000000..211cf4c8
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeArgumentJavaImpl.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.kotlin.KSTypeArgumentImpl
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.intellij.psi.PsiType
+import com.intellij.psi.PsiWildcardType
+import com.intellij.psi.impl.source.PsiClassReferenceType
+
+class KSTypeArgumentJavaImpl private constructor(
+ val psi: PsiType,
+ override val parent: KSNode?
+) : KSTypeArgumentImpl() {
+ companion object : KSObjectCache<PsiType, KSTypeArgumentJavaImpl>() {
+ fun getCached(psi: PsiType, parent: KSNode?) = cache.getOrPut(psi) { KSTypeArgumentJavaImpl(psi, parent) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ (psi as? PsiClassReferenceType)?.reference?.toLocation() ?: NonExistLocation
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }.memoized()
+ }
+
+ // Could be unbounded, need to model unbdouned type argument.
+ override val type: KSTypeReference? by lazy {
+ KSTypeReferenceJavaImpl.getCached(psi, this)
+ }
+
+ override val variance: Variance by lazy {
+ if (psi is PsiWildcardType) {
+ when {
+ psi.isExtends -> Variance.COVARIANT
+ psi.isSuper -> Variance.CONTRAVARIANT
+ psi.bound == null -> Variance.STAR
+ else -> Variance.INVARIANT
+ }
+ } else {
+ Variance.INVARIANT
+ }
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeParameterJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeParameterJavaImpl.kt
new file mode 100644
index 00000000..e3c41286
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeParameterJavaImpl.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.findParentDeclaration
+import com.google.devtools.ksp.symbol.impl.kotlin.KSExpectActualNoImpl
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.intellij.psi.PsiJavaFile
+import com.intellij.psi.PsiTypeParameter
+
+class KSTypeParameterJavaImpl private constructor(val psi: PsiTypeParameter) :
+ KSTypeParameter,
+ KSDeclarationJavaImpl(psi),
+ KSExpectActual by KSExpectActualNoImpl() {
+ companion object : KSObjectCache<PsiTypeParameter, KSTypeParameterJavaImpl>() {
+ fun getCached(psi: PsiTypeParameter) = cache.getOrPut(psi) { KSTypeParameterJavaImpl(psi) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }.memoized()
+ }
+
+ override val bounds: Sequence<KSTypeReference> by lazy {
+ psi.extendsListTypes.asSequence().map { KSTypeReferenceJavaImpl.getCached(it, this) }.memoized()
+ }
+ override val simpleName: KSName by lazy {
+ KSNameImpl.getCached(psi.name ?: "_")
+ }
+
+ override val qualifiedName: KSName? by lazy {
+ KSNameImpl.getCached(parentDeclaration?.qualifiedName?.asString() ?: "" + "." + simpleName.asString())
+ }
+
+ override val typeParameters: List<KSTypeParameter> = emptyList()
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ psi.findParentDeclaration()
+ }
+
+ override val containingFile: KSFile? by lazy {
+ KSFileJavaImpl.getCached(psi.containingFile as PsiJavaFile)
+ }
+
+ override val modifiers: Set<Modifier> = emptySet()
+
+ override val isReified: Boolean = false
+
+ override val name: KSName by lazy {
+ KSNameImpl.getCached(psi.name!!)
+ }
+
+ override val variance: Variance = Variance.INVARIANT
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeParameter(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceJavaImpl.kt
new file mode 100644
index 00000000..6b035244
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceJavaImpl.kt
@@ -0,0 +1,148 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.KSAnnotated
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSReferenceElement
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.Modifier
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.binary.KSClassDeclarationDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.binary.KSClassifierReferenceDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.kotlin.KSErrorType
+import com.google.devtools.ksp.symbol.impl.kotlin.KSTypeImpl
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.intellij.psi.PsiArrayType
+import com.intellij.psi.PsiClassType
+import com.intellij.psi.PsiPrimitiveType
+import com.intellij.psi.PsiType
+import com.intellij.psi.PsiWildcardType
+import com.intellij.psi.impl.source.PsiClassReferenceType
+import org.jetbrains.kotlin.descriptors.NotFoundClasses
+import org.jetbrains.kotlin.load.java.NOT_NULL_ANNOTATIONS
+import org.jetbrains.kotlin.load.java.NULLABLE_ANNOTATIONS
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.Variance
+import org.jetbrains.kotlin.types.typeUtil.makeNullable
+
+class KSTypeReferenceJavaImpl private constructor(val psi: PsiType, override val parent: KSNode?) : KSTypeReference {
+ companion object : KSObjectCache<Pair<PsiType, KSNode?>, KSTypeReferenceJavaImpl>() {
+ fun getCached(psi: PsiType, parent: KSNode?) = cache
+ .getOrPut(Pair(psi, parent)) { KSTypeReferenceJavaImpl(psi, parent) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ (psi as? PsiClassReferenceType)?.reference?.toLocation() ?: NonExistLocation
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }.memoized()
+ }
+
+ override val modifiers: Set<Modifier> = emptySet()
+
+ override val element: KSReferenceElement by lazy {
+ fun PsiPrimitiveType.toKotlinType(): KotlinType {
+ return when (this.name) {
+ "int" -> ResolverImpl.instance!!.module.builtIns.intType
+ "short" -> ResolverImpl.instance!!.module.builtIns.shortType
+ "byte" -> ResolverImpl.instance!!.module.builtIns.byteType
+ "long" -> ResolverImpl.instance!!.module.builtIns.longType
+ "float" -> ResolverImpl.instance!!.module.builtIns.floatType
+ "double" -> ResolverImpl.instance!!.module.builtIns.doubleType
+ "char" -> ResolverImpl.instance!!.module.builtIns.charType
+ "boolean" -> ResolverImpl.instance!!.module.builtIns.booleanType
+ "void" -> ResolverImpl.instance!!.module.builtIns.unitType
+ else -> throw IllegalStateException("Unexpected primitive type ${this.name}, $ExceptionMessage")
+ }
+ }
+
+ val type = if (psi is PsiWildcardType) {
+ psi.bound
+ } else {
+ psi
+ }
+ when (type) {
+ is PsiClassType -> KSClassifierReferenceJavaImpl.getCached(type, this)
+ is PsiWildcardType -> KSClassifierReferenceJavaImpl.getCached(type.extendsBound as PsiClassType, this)
+ is PsiPrimitiveType -> KSClassifierReferenceDescriptorImpl.getCached(type.toKotlinType(), origin, this)
+ is PsiArrayType -> {
+ val componentType = ResolverImpl.instance!!.resolveJavaType(type.componentType, this)
+ if (type.componentType !is PsiPrimitiveType) {
+ KSClassifierReferenceDescriptorImpl.getCached(
+ ResolverImpl.instance!!.module.builtIns.getArrayType(Variance.INVARIANT, componentType),
+ origin,
+ this
+ )
+ } else {
+ KSClassifierReferenceDescriptorImpl.getCached(
+ ResolverImpl.instance!!.module.builtIns
+ .getPrimitiveArrayKotlinTypeByPrimitiveKotlinType(componentType)!!,
+ origin, this
+ )
+ }
+ }
+ null ->
+ KSClassifierReferenceDescriptorImpl.getCached(
+ (ResolverImpl.instance!!.builtIns.anyType as KSTypeImpl).kotlinType.makeNullable(), origin, this
+ )
+ else -> throw IllegalStateException("Unexpected psi type for ${type.javaClass}, $ExceptionMessage")
+ }
+ }
+
+ override fun resolve(): KSType {
+ val resolvedType = ResolverImpl.instance!!.resolveUserType(this)
+ val relatedAnnotations = (annotations + ((parent as? KSAnnotated)?.annotations ?: emptySequence()))
+ .mapNotNull {
+ (it.annotationType.resolve() as? KSTypeImpl)?.kotlinType?.constructor?.declarationDescriptor?.fqNameSafe
+ }
+ val resolved = if ((resolvedType.declaration as? KSClassDeclarationDescriptorImpl)
+ ?.descriptor is NotFoundClasses.MockClassDescriptor
+ ) {
+ KSErrorType
+ } else resolvedType
+ val hasNotNull = relatedAnnotations.any { it in NOT_NULL_ANNOTATIONS }
+ val hasNullable = relatedAnnotations.any { it in NULLABLE_ANNOTATIONS }
+ return if (hasNullable && !hasNotNull) {
+ resolved.makeNullable()
+ } else if (!hasNullable && hasNotNull) {
+ resolved.makeNotNullable()
+ } else resolved
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeReference(this, data)
+ }
+
+ override fun toString(): String {
+ return element.toString()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceLiteJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceLiteJavaImpl.kt
new file mode 100644
index 00000000..601c8bee
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSTypeReferenceLiteJavaImpl.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSReferenceElement
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.Modifier
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.kotlin.KSErrorType
+import com.intellij.psi.PsiAnnotation
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiJavaFile
+import com.intellij.psi.PsiMethod
+
+class KSTypeReferenceLiteJavaImpl private constructor(val psiElement: PsiElement, override val parent: KSNode) :
+ KSTypeReference {
+ companion object : KSObjectCache<KSNode, KSTypeReferenceLiteJavaImpl>() {
+ fun getCached(psiElement: PsiElement, parent: KSNode) = cache
+ .getOrPut(parent) { KSTypeReferenceLiteJavaImpl(psiElement, parent) }
+ }
+
+ val type: KSType by lazy {
+ when (psiElement) {
+ is PsiAnnotation -> {
+ val psiClass = psiElement.nameReferenceElement!!.resolve() as? PsiClass
+ psiClass?.let {
+ (psiElement.containingFile as? PsiJavaFile)?.let {
+ ResolverImpl.instance!!.incrementalContext.recordLookup(it, psiClass.qualifiedName!!)
+ }
+ KSClassDeclarationJavaImpl.getCached(psiClass).asStarProjectedType()
+ } ?: KSErrorType
+ }
+ is PsiMethod -> {
+ KSClassDeclarationJavaImpl.getCached(psiElement.containingClass!!).asStarProjectedType()
+ }
+ else -> throw IllegalStateException(
+ "Unexpected psi type in KSTypeReferenceLiteJavaImpl: ${psiElement.javaClass}, $ExceptionMessage"
+ )
+ }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location = NonExistLocation
+
+ override val element: KSReferenceElement by lazy {
+ KSClassifierReferenceLiteImplForJava.getCached(this)
+ }
+
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override val modifiers: Set<Modifier> = emptySet()
+
+ override fun resolve(): KSType {
+ return type
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeReference(this, data)
+ }
+
+ override fun toString(): String {
+ return type.toString()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSValueArgumentJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSValueArgumentJavaImpl.kt
new file mode 100644
index 00000000..1424b9e4
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSValueArgumentJavaImpl.kt
@@ -0,0 +1,50 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSName
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.kotlin.KSValueArgumentImpl
+
+class KSValueArgumentJavaImpl private constructor(
+ override val name: KSName?,
+ override val value: Any?,
+ override val parent: KSNode?
+) : KSValueArgumentImpl() {
+ companion object : KSObjectCache<Triple<KSName?, Any?, KSNode?>, KSValueArgumentJavaImpl>() {
+ fun getCached(name: KSName?, value: Any?, parent: KSNode?) =
+ cache.getOrPut(Triple(name, value, parent)) { KSValueArgumentJavaImpl(name, value, parent) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location = NonExistLocation
+
+ override val isSpread: Boolean = false
+
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override fun toString(): String {
+ return "${name?.asString() ?: ""}:$value"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSValueParameterJavaImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSValueParameterJavaImpl.kt
new file mode 100644
index 00000000..086b670a
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/java/KSValueParameterJavaImpl.kt
@@ -0,0 +1,88 @@
+/*
+ * 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.symbol.impl.java
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.intellij.psi.PsiAnnotation
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.PsiParameter
+
+class KSValueParameterJavaImpl private constructor(val psi: PsiParameter) : KSValueParameter {
+ companion object : KSObjectCache<PsiParameter, KSValueParameterJavaImpl>() {
+ fun getCached(psi: PsiParameter) = cache.getOrPut(psi) { KSValueParameterJavaImpl(psi) }
+ }
+
+ override val origin = Origin.JAVA
+
+ override val location: Location by lazy {
+ psi.toLocation()
+ }
+ override val parent: KSNode? by lazy {
+ var parentPsi = psi.parent
+ while (true) {
+ when (parentPsi) {
+ null, is PsiMethod, is PsiAnnotation -> break
+ else -> parentPsi = parentPsi.parent
+ }
+ }
+ when (parentPsi) {
+ is PsiMethod -> KSFunctionDeclarationJavaImpl.getCached(parentPsi)
+ is PsiAnnotation -> KSAnnotationJavaImpl.getCached(parentPsi)
+ else -> null
+ }
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ psi.annotations.asSequence().map { KSAnnotationJavaImpl.getCached(it) }
+ }
+
+ override val isCrossInline: Boolean = false
+
+ override val isNoInline: Boolean = false
+
+ override val isVararg: Boolean = psi.isVarArgs
+
+ override val isVal: Boolean = false
+
+ override val isVar: Boolean = false
+
+ override val name: KSName? by lazy {
+ if (psi.name != null) {
+ KSNameImpl.getCached(psi.name!!)
+ } else {
+ null
+ }
+ }
+
+ override val type: KSTypeReference by lazy {
+ KSTypeReferenceJavaImpl.getCached(psi.type, this)
+ }
+
+ override val hasDefault: Boolean = false
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitValueParameter(this, data)
+ }
+
+ override fun toString(): String {
+ return name?.asString() ?: "_"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSAnnotationImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSAnnotationImpl.kt
new file mode 100644
index 00000000..19bde157
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSAnnotationImpl.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.binary.createKSValueArguments
+import com.google.devtools.ksp.symbol.impl.binary.getDefaultArguments
+import com.google.devtools.ksp.symbol.impl.toLocation
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget.*
+import org.jetbrains.kotlin.psi.KtAnnotationEntry
+import org.jetbrains.kotlin.psi.KtClassOrObject
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.KtFunction
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.psi.KtPropertyAccessor
+import org.jetbrains.kotlin.psi.KtTypeAlias
+import org.jetbrains.kotlin.psi.KtTypeParameter
+import org.jetbrains.kotlin.psi.KtTypeProjection
+import org.jetbrains.kotlin.psi.KtTypeReference
+
+class KSAnnotationImpl private constructor(val ktAnnotationEntry: KtAnnotationEntry) : KSAnnotation {
+ companion object : KSObjectCache<KtAnnotationEntry, KSAnnotationImpl>() {
+ fun getCached(ktAnnotationEntry: KtAnnotationEntry) = cache.getOrPut(ktAnnotationEntry) {
+ KSAnnotationImpl(ktAnnotationEntry)
+ }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val parent: KSNode? by lazy {
+ var parentPsi = ktAnnotationEntry.parent
+ while (true) {
+ when (parentPsi) {
+ null, is KtFile, is KtClassOrObject, is KtFunction, is KtParameter, is KtTypeParameter,
+ is KtTypeAlias, is KtProperty, is KtPropertyAccessor, is KtTypeProjection, is KtTypeReference -> break
+ else -> parentPsi = parentPsi.parent
+ }
+ }
+ when (parentPsi) {
+ is KtFile -> KSFileImpl.getCached(parentPsi)
+ is KtClassOrObject -> KSClassDeclarationImpl.getCached(parentPsi)
+ is KtFunction -> KSFunctionDeclarationImpl.getCached(parentPsi)
+ is KtParameter -> KSValueParameterImpl.getCached(parentPsi)
+ is KtTypeParameter -> KSTypeParameterImpl.getCached(parentPsi)
+ is KtTypeAlias -> KSTypeAliasImpl.getCached(parentPsi)
+ is KtProperty -> KSPropertyDeclarationImpl.getCached(parentPsi)
+ is KtPropertyAccessor -> KSPropertyAccessorImpl.getCached(parentPsi)
+ is KtTypeProjection -> KSTypeArgumentKtImpl.getCached(parentPsi)
+ is KtTypeReference -> KSTypeReferenceImpl.getCached(parentPsi)
+ else -> null
+ }
+ }
+
+ override val location: Location by lazy {
+ ktAnnotationEntry.toLocation()
+ }
+
+ override val annotationType: KSTypeReference by lazy {
+ KSTypeReferenceImpl.getCached(ktAnnotationEntry.typeReference!!)
+ }
+
+ override val arguments: List<KSValueArgument> by lazy {
+ resolved?.createKSValueArguments(this) ?: emptyList()
+ }
+
+ override val defaultArguments: List<KSValueArgument> by lazy {
+ resolved?.getDefaultArguments(this) ?: emptyList()
+ }
+
+ override val shortName: KSName by lazy {
+ KSNameImpl.getCached(ktAnnotationEntry.shortName!!.asString())
+ }
+
+ override val useSiteTarget: AnnotationUseSiteTarget? by lazy {
+ when (ktAnnotationEntry.useSiteTarget?.getAnnotationUseSiteTarget()) {
+ null -> null
+ FILE -> AnnotationUseSiteTarget.FILE
+ PROPERTY -> AnnotationUseSiteTarget.PROPERTY
+ FIELD -> AnnotationUseSiteTarget.FIELD
+ PROPERTY_GETTER -> AnnotationUseSiteTarget.GET
+ PROPERTY_SETTER -> AnnotationUseSiteTarget.SET
+ RECEIVER -> AnnotationUseSiteTarget.RECEIVER
+ CONSTRUCTOR_PARAMETER -> AnnotationUseSiteTarget.PARAM
+ SETTER_PARAMETER -> AnnotationUseSiteTarget.SETPARAM
+ PROPERTY_DELEGATE_FIELD -> AnnotationUseSiteTarget.DELEGATE
+ }
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitAnnotation(this, data)
+ }
+
+ private val resolved: AnnotationDescriptor? by lazy {
+ ResolverImpl.instance!!.resolveAnnotationEntry(ktAnnotationEntry)
+ }
+
+ override fun toString(): String {
+ return "@${shortName.asString()}"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSCallableReferenceImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSCallableReferenceImpl.kt
new file mode 100644
index 00000000..c71f37d4
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSCallableReferenceImpl.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.findParentOfType
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.toLocation
+import org.jetbrains.kotlin.psi.KtFunctionType
+import org.jetbrains.kotlin.psi.KtTypeReference
+
+class KSCallableReferenceImpl private constructor(val ktFunctionType: KtFunctionType) : KSCallableReference {
+ companion object : KSObjectCache<KtFunctionType, KSCallableReferenceImpl>() {
+ fun getCached(ktFunctionType: KtFunctionType) = cache.getOrPut(ktFunctionType) {
+ KSCallableReferenceImpl(ktFunctionType)
+ }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location by lazy {
+ ktFunctionType.toLocation()
+ }
+
+ override val parent: KSNode? by lazy {
+ ktFunctionType.findParentOfType<KtTypeReference>()?.let { KSTypeReferenceImpl.getCached(it) }
+ }
+
+ override val typeArguments: List<KSTypeArgument> by lazy {
+ ktFunctionType.typeArgumentsAsTypes.map { KSTypeArgumentLiteImpl.getCached(it) }
+ }
+
+ override val functionParameters: List<KSValueParameter> by lazy {
+ ktFunctionType.parameters.map { KSValueParameterImpl.getCached(it) }
+ }
+
+ override val receiverType: KSTypeReference? by lazy {
+ if (ktFunctionType.receiver != null) {
+ KSTypeReferenceImpl.getCached(ktFunctionType.receiverTypeReference!!)
+ } else {
+ null
+ }
+ }
+
+ override val returnType: KSTypeReference by lazy {
+ KSTypeReferenceImpl.getCached(ktFunctionType.returnTypeReference!!)
+ }
+
+ override fun toString(): String {
+ return "${receiverType?.let { "$it." } ?: ""}(${functionParameters
+ .joinToString(", ") { it.type.toString() }}) -> $returnType"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassDeclarationImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassDeclarationImpl.kt
new file mode 100644
index 00000000..89bb2b4f
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassDeclarationImpl.kt
@@ -0,0 +1,138 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.getClassType
+import com.google.devtools.ksp.isConstructor
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.symbol.impl.binary.getAllFunctions
+import com.google.devtools.ksp.symbol.impl.binary.getAllProperties
+import com.google.devtools.ksp.symbol.impl.binary.sealedSubclassesSequence
+import com.google.devtools.ksp.symbol.impl.synthetic.KSConstructorSyntheticImpl
+import com.google.devtools.ksp.symbol.impl.synthetic.KSTypeReferenceSyntheticImpl
+import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.psi.KtClassOrObject
+import org.jetbrains.kotlin.psi.KtObjectDeclaration
+import org.jetbrains.kotlin.psi.KtSecondaryConstructor
+import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
+
+class KSClassDeclarationImpl private constructor(val ktClassOrObject: KtClassOrObject) :
+ KSClassDeclaration,
+ KSDeclarationImpl(ktClassOrObject),
+ KSExpectActual by KSExpectActualImpl(ktClassOrObject) {
+ companion object : KSObjectCache<KtClassOrObject, KSClassDeclarationImpl>() {
+ fun getCached(ktClassOrObject: KtClassOrObject) =
+ cache.getOrPut(ktClassOrObject) { KSClassDeclarationImpl(ktClassOrObject) }
+ }
+
+ override val classKind: ClassKind by lazy {
+ ktClassOrObject.getClassType()
+ }
+
+ override val isCompanionObject by lazy {
+ (ktClassOrObject is KtObjectDeclaration) && (ktClassOrObject.isCompanion())
+ }
+
+ override fun getSealedSubclasses(): Sequence<KSClassDeclaration> {
+ return if (Modifier.SEALED in modifiers) {
+ ResolverImpl.instance!!.incrementalContext.recordGetSealedSubclasses(this)
+ descriptor.sealedSubclassesSequence()
+ } else {
+ emptySequence()
+ }
+ }
+
+ override fun getAllFunctions(): Sequence<KSFunctionDeclaration> = descriptor.getAllFunctions()
+
+ override fun getAllProperties(): Sequence<KSPropertyDeclaration> = descriptor.getAllProperties()
+
+ override val declarations: Sequence<KSDeclaration> by lazy {
+ val propertiesFromConstructor = primaryConstructor?.parameters
+ ?.asSequence()
+ ?.filter { it.isVar || it.isVal }
+ ?.map { KSPropertyDeclarationParameterImpl.getCached((it as KSValueParameterImpl).ktParameter) }
+ ?: emptySequence()
+ var result = propertiesFromConstructor.plus(ktClassOrObject.declarations.asSequence().getKSDeclarations())
+ primaryConstructor?.let { primaryConstructor: KSFunctionDeclaration ->
+ // if primary constructor is from source, it won't show up in declarations
+ // hence add it as well.
+ if (primaryConstructor.origin == Origin.KOTLIN) {
+ result = sequenceOf(primaryConstructor).plus(result)
+ }
+ }
+ if (classKind != ClassKind.INTERFACE) {
+ // check if we need to add a synthetic constructor
+ val hasConstructor = result.any {
+ it is KSFunctionDeclaration && it.isConstructor()
+ }
+ if (hasConstructor) {
+ result.memoized()
+ } else {
+ (result + KSConstructorSyntheticImpl.getCached(this)).memoized()
+ }
+ } else {
+ result.memoized()
+ }
+ }
+
+ override val primaryConstructor: KSFunctionDeclaration? by lazy {
+ ktClassOrObject.primaryConstructor?.let { KSFunctionDeclarationImpl.getCached(it) }
+ ?: if ((classKind == ClassKind.CLASS || classKind == ClassKind.ENUM_CLASS) &&
+ ktClassOrObject.declarations.none { it is KtSecondaryConstructor }
+ )
+ KSConstructorSyntheticImpl.getCached(this) else null
+ }
+
+ override val superTypes: Sequence<KSTypeReference> by lazy {
+ val resolver = ResolverImpl.instance!!
+ ktClassOrObject.superTypeListEntries
+ .asSequence()
+ .map { KSTypeReferenceImpl.getCached(it.typeReference!!) }
+ .ifEmpty {
+ sequenceOf(
+ KSTypeReferenceSyntheticImpl.getCached(
+ resolver.builtIns.anyType,
+ this
+ )
+ )
+ }
+ .memoized()
+ }
+
+ private val descriptor: ClassDescriptor by lazy {
+ (ResolverImpl.instance!!.resolveDeclaration(ktClassOrObject) as ClassDescriptor)
+ }
+
+ override fun asType(typeArguments: List<KSTypeArgument>): KSType {
+ return descriptor.defaultType.replaceTypeArguments(typeArguments)?.let {
+ getKSTypeCached(it, typeArguments)
+ } ?: KSErrorType
+ }
+
+ override fun asStarProjectedType(): KSType {
+ return getKSTypeCached(descriptor.defaultType.replaceArgumentsWithStarProjections())
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitClassDeclaration(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassifierReferenceImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassifierReferenceImpl.kt
new file mode 100644
index 00000000..575c15d5
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSClassifierReferenceImpl.kt
@@ -0,0 +1,62 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.findParentOfType
+import com.google.devtools.ksp.symbol.KSClassifierReference
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSTypeArgument
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.toLocation
+import org.jetbrains.kotlin.psi.*
+
+class KSClassifierReferenceImpl private constructor(val ktUserType: KtUserType) : KSClassifierReference {
+ companion object : KSObjectCache<KtUserType, KSClassifierReferenceImpl>() {
+ fun getCached(ktUserType: KtUserType) = cache.getOrPut(ktUserType) { KSClassifierReferenceImpl(ktUserType) }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location by lazy {
+ ktUserType.toLocation()
+ }
+
+ override val parent: KSNode? by lazy {
+ ktUserType.findParentOfType<KtTypeReference>()?.let { KSTypeReferenceImpl.getCached(it) }
+ }
+
+ override val typeArguments: List<KSTypeArgument> by lazy {
+ ktUserType.typeArguments.map { KSTypeArgumentKtImpl.getCached(it) }
+ }
+
+ override fun referencedName(): String {
+ return ktUserType.referencedName ?: ""
+ }
+
+ override val qualifier: KSClassifierReference? by lazy {
+ if (ktUserType.qualifier == null) {
+ null
+ } else {
+ KSClassifierReferenceImpl.getCached(ktUserType.qualifier!!)
+ }
+ }
+
+ override fun toString() = referencedName()
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDeclarationImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDeclarationImpl.kt
new file mode 100644
index 00000000..3e596664
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDeclarationImpl.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.getDocString
+import com.google.devtools.ksp.isConstructor
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.findParentAnnotated
+import com.google.devtools.ksp.symbol.impl.findParentDeclaration
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.google.devtools.ksp.toKSModifiers
+import org.jetbrains.kotlin.psi.*
+
+abstract class KSDeclarationImpl(val ktDeclaration: KtDeclaration) : KSDeclaration {
+ override val origin: Origin = Origin.KOTLIN
+
+ override val location: Location by lazy {
+ ktDeclaration.toLocation()
+ }
+
+ override val simpleName: KSName by lazy {
+ KSNameImpl.getCached(ktDeclaration.name!!)
+ }
+
+ override val qualifiedName: KSName? by lazy {
+ (ktDeclaration as? KtNamedDeclaration)?.fqName?.let { KSNameImpl.getCached(it.asString()) }
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ ktDeclaration.annotationEntries.asSequence().map { KSAnnotationImpl.getCached(it) }.memoized()
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ // we do not check for JVM_STATIC here intentionally as it actually means static in parent class,
+ // not in this class.
+ // see: https://github.com/google/ksp/issues/378
+ if (this is KSFunctionDeclaration && this.isConstructor() &&
+ (this.parentDeclaration as? KSClassDeclaration)?.classKind == ClassKind.ENUM_CLASS
+ ) {
+ setOf(Modifier.FINAL, Modifier.PRIVATE)
+ } else {
+ ktDeclaration.toKSModifiers()
+ }
+ }
+
+ override val containingFile: KSFile? by lazy {
+ KSFileImpl.getCached(ktDeclaration.containingKtFile)
+ }
+
+ override val packageName: KSName by lazy {
+ this.containingFile!!.packageName
+ }
+
+ override val typeParameters: List<KSTypeParameter> by lazy {
+ (ktDeclaration as? KtTypeParameterListOwner)?.let {
+ it.typeParameters.map { KSTypeParameterImpl.getCached(it) }
+ } ?: emptyList()
+ }
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ ktDeclaration.findParentDeclaration()
+ }
+
+ override val parent: KSNode? by lazy {
+ ktDeclaration.findParentAnnotated()
+ }
+
+ override fun toString(): String {
+ return this.simpleName.asString()
+ }
+
+ internal val originalAnnotations: List<KSAnnotation> by lazy {
+ ktDeclaration.annotationEntries.map { KSAnnotationImpl.getCached(it) }
+ }
+
+ override val docString by lazy {
+ ktDeclaration.getDocString()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDefNonNullReferenceImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDefNonNullReferenceImpl.kt
new file mode 100644
index 00000000..37d07c92
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDefNonNullReferenceImpl.kt
@@ -0,0 +1,41 @@
+package com.google.devtools.ksp.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.findParentOfType
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.toLocation
+import org.jetbrains.kotlin.psi.KtIntersectionType
+import org.jetbrains.kotlin.psi.KtTypeReference
+import org.jetbrains.kotlin.psi.KtUserType
+
+class KSDefNonNullReferenceImpl private constructor(val ktIntersectionType: KtIntersectionType) :
+ KSDefNonNullReference {
+ companion object : KSObjectCache<KtIntersectionType, KSDefNonNullReferenceImpl>() {
+ fun getCached(ktIntersectionType: KtIntersectionType) = KSDefNonNullReferenceImpl
+ .cache.getOrPut(ktIntersectionType) { KSDefNonNullReferenceImpl(ktIntersectionType) }
+ }
+
+ override val enclosedType: KSClassifierReference by lazy {
+ val lhs = ktIntersectionType.getLeftTypeRef()?.typeElement
+ if (lhs is KtUserType) {
+ KSClassifierReferenceImpl.getCached(lhs)
+ } else {
+ throw IllegalStateException("LHS operand of definitely non null type should be a user type")
+ }
+ }
+
+ override val typeArguments: List<KSTypeArgument>
+ get() = emptyList()
+
+ override val origin: Origin
+ get() = Origin.KOTLIN
+
+ override val location: Location
+ get() = ktIntersectionType.toLocation()
+
+ override val parent: KSNode? by lazy {
+ ktIntersectionType.findParentOfType<KtTypeReference>()?.let { KSTypeReferenceImpl.getCached(it) }
+ }
+
+ override fun toString() = "${enclosedType.referencedName()} & Any"
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDynamicReferenceImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDynamicReferenceImpl.kt
new file mode 100644
index 00000000..27579fce
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSDynamicReferenceImpl.kt
@@ -0,0 +1,43 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.*
+
+class KSDynamicReferenceImpl private constructor(override val parent: KSNode?) : KSDynamicReference {
+ companion object : KSObjectCache<KSTypeReference, KSDynamicReferenceImpl>() {
+ fun getCached(parent: KSTypeReference) = cache.getOrPut(parent) { KSDynamicReferenceImpl(parent) }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location by lazy {
+ NonExistLocation
+ }
+
+ override val typeArguments: List<KSTypeArgument> = emptyList()
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitDynamicReference(this, data)
+ }
+
+ override fun toString(): String {
+ return "<dynamic type>"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSErrorType.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSErrorType.kt
new file mode 100644
index 00000000..8cf66385
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSErrorType.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.synthetic.KSErrorTypeClassDeclaration
+
+object KSErrorType : KSType {
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override val arguments: List<KSTypeArgument> = emptyList()
+
+ override val declaration: KSDeclaration = KSErrorTypeClassDeclaration
+
+ override val isError: Boolean = true
+
+ override val nullability: Nullability = Nullability.NULLABLE
+
+ override fun isAssignableFrom(that: KSType): Boolean {
+ return false
+ }
+
+ override fun isCovarianceFlexible(): Boolean {
+ return false
+ }
+
+ override fun isMutabilityFlexible(): Boolean {
+ return false
+ }
+
+ override fun makeNotNullable(): KSType {
+ return this
+ }
+
+ override fun makeNullable(): KSType {
+ return this
+ }
+
+ override val isMarkedNullable: Boolean = false
+
+ override fun replace(arguments: List<KSTypeArgument>): KSType {
+ return this
+ }
+
+ override fun starProjection(): KSType {
+ return this
+ }
+
+ override fun toString(): String {
+ return "<ERROR TYPE>"
+ }
+
+ override val isFunctionType: Boolean = false
+
+ override val isSuspendFunctionType: Boolean = false
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSExpectActualImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSExpectActualImpl.kt
new file mode 100644
index 00000000..18c3f9c5
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSExpectActualImpl.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.processing.impl.findActualsInKSDeclaration
+import com.google.devtools.ksp.processing.impl.findExpectsInKSDeclaration
+import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSExpectActual
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
+import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
+import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
+
+class KSExpectActualImpl(val declaration: KtDeclaration) : KSExpectActual {
+ /**
+ * "All actual declarations that match any part of an expected declaration need to be marked as actual."
+ */
+ override val isActual: Boolean = declaration.hasActualModifier()
+
+ private fun KtDeclaration.isExpect(): Boolean = hasExpectModifier() || containingClassOrObject?.isExpect() == true
+
+ override val isExpect: Boolean = declaration.isExpect()
+
+ private val expects: Sequence<KSDeclaration> by lazy {
+ descriptor?.findExpectsInKSDeclaration() ?: emptySequence()
+ }
+
+ override fun findExpects(): Sequence<KSDeclaration> {
+ if (!isActual)
+ return emptySequence()
+ return expects
+ }
+
+ private val actuals: Sequence<KSDeclaration> by lazy {
+ descriptor?.findActualsInKSDeclaration() ?: emptySequence()
+ }
+
+ override fun findActuals(): Sequence<KSDeclaration> {
+ if (!isExpect)
+ return emptySequence()
+ return actuals
+ }
+
+ private val descriptor: DeclarationDescriptor? by lazy {
+ ResolverImpl.instance!!.resolveDeclaration(declaration)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSExpectActualNoImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSExpectActualNoImpl.kt
new file mode 100644
index 00000000..c06cd2ca
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSExpectActualNoImpl.kt
@@ -0,0 +1,31 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSExpectActual
+
+class KSExpectActualNoImpl : KSExpectActual {
+ override val isActual: Boolean = false
+
+ override val isExpect: Boolean = false
+
+ override fun findActuals(): Sequence<KSDeclaration> = emptySequence()
+
+ override fun findExpects(): Sequence<KSDeclaration> = emptySequence()
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFileImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFileImpl.kt
new file mode 100644
index 00000000..3e333a2e
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFileImpl.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.getKSDeclarations
+import com.google.devtools.ksp.symbol.impl.toLocation
+import org.jetbrains.kotlin.psi.KtFile
+
+class KSFileImpl private constructor(val file: KtFile) : KSFile {
+ companion object : KSObjectCache<KtFile, KSFileImpl>() {
+ fun getCached(file: KtFile) = cache.getOrPut(file) { KSFileImpl(file) }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location by lazy {
+ file.toLocation()
+ }
+
+ override val parent: KSNode? = null
+
+ override val packageName: KSName by lazy {
+ KSNameImpl.getCached(file.packageFqName.asString())
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ file.annotationEntries.asSequence().map { KSAnnotationImpl.getCached(it) }.memoized()
+ }
+
+ override val declarations: Sequence<KSDeclaration> by lazy {
+ file.declarations.asSequence().getKSDeclarations().memoized()
+ }
+
+ override val fileName: String by lazy {
+ file.name
+ }
+
+ override val filePath: String by lazy {
+ file.virtualFilePath
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitFile(this, data)
+ }
+
+ override fun toString(): String {
+ return "File: ${this.fileName}"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionDeclarationImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionDeclarationImpl.kt
new file mode 100644
index 00000000..75017fbb
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionDeclarationImpl.kt
@@ -0,0 +1,123 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.KSPCompilationError
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.KtConstructor
+import org.jetbrains.kotlin.psi.KtFunction
+import org.jetbrains.kotlin.psi.KtFunctionLiteral
+import org.jetbrains.kotlin.psi.KtNamedFunction
+import org.jetbrains.kotlin.psi.psiUtil.startOffset
+import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
+
+class KSFunctionDeclarationImpl private constructor(val ktFunction: KtFunction) :
+ KSFunctionDeclaration,
+ KSDeclarationImpl(ktFunction),
+ KSExpectActual by KSExpectActualImpl(ktFunction) {
+ companion object : KSObjectCache<KtFunction, KSFunctionDeclarationImpl>() {
+ fun getCached(ktFunction: KtFunction) = cache.getOrPut(ktFunction) { KSFunctionDeclarationImpl(ktFunction) }
+ }
+
+ override fun findOverridee(): KSDeclaration? {
+ val descriptor = ResolverImpl.instance!!.resolveFunctionDeclaration(this)
+ return (descriptor as? FunctionDescriptor)?.findClosestOverridee()?.toKSDeclaration()
+ }
+
+ override val simpleName: KSName by lazy {
+ if (ktFunction is KtConstructor<*>) {
+ KSNameImpl.getCached("<init>")
+ } else {
+ if (ktFunction.name == null) {
+ throw KSPCompilationError(
+ ktFunction.containingFile,
+ ktFunction.startOffset,
+ "Function declaration must have a name"
+ )
+ }
+ KSNameImpl.getCached(ktFunction.name!!)
+ }
+ }
+
+ override val declarations: Sequence<KSDeclaration> by lazy {
+ if (!ktFunction.hasBlockBody()) {
+ emptySequence()
+ } else {
+ ktFunction.bodyBlockExpression?.statements?.asSequence()?.getKSDeclarations()?.memoized() ?: emptySequence()
+ }
+ }
+
+ override val extensionReceiver: KSTypeReference? by lazy {
+ if (ktFunction.receiverTypeReference != null) {
+ KSTypeReferenceImpl.getCached(ktFunction.receiverTypeReference!!)
+ } else {
+ null
+ }
+ }
+
+ override val functionKind: FunctionKind by lazy {
+ if (parentDeclaration == null) {
+ FunctionKind.TOP_LEVEL
+ } else {
+ when (ktFunction) {
+ is KtNamedFunction, is KtConstructor<*> -> FunctionKind.MEMBER
+ is KtFunctionLiteral -> if (ktFunction.node.findChildByType(KtTokens.FUN_KEYWORD) != null)
+ FunctionKind.ANONYMOUS else FunctionKind.LAMBDA
+ else -> throw IllegalStateException("Unexpected psi type ${ktFunction.javaClass}, $ExceptionMessage")
+ }
+ }
+ }
+
+ override val isAbstract: Boolean by lazy {
+ this.modifiers.contains(Modifier.ABSTRACT) ||
+ (
+ (this.parentDeclaration as? KSClassDeclaration)?.classKind == ClassKind.INTERFACE &&
+ !this.ktFunction.hasBody()
+ )
+ }
+
+ override val parameters: List<KSValueParameter> by lazy {
+ ktFunction.valueParameters.map { KSValueParameterImpl.getCached(it) }
+ }
+
+ override val returnType: KSTypeReference by lazy {
+ if (ktFunction.typeReference != null) {
+ KSTypeReferenceImpl.getCached(ktFunction.typeReference!!)
+ } else {
+ KSTypeReferenceDeferredImpl.getCached(this) {
+ val desc = ResolverImpl.instance!!.resolveDeclaration(ktFunction) as FunctionDescriptor
+ getKSTypeCached(desc.returnTypeOrNothing)
+ }
+ }
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitFunctionDeclaration(this, data)
+ }
+
+ override fun asMemberOf(containing: KSType): KSFunction =
+ ResolverImpl.instance!!.asMemberOf(this, containing)
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionErrorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionErrorImpl.kt
new file mode 100644
index 00000000..5100e367
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionErrorImpl.kt
@@ -0,0 +1,60 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.symbol.KSFunction
+import com.google.devtools.ksp.symbol.KSFunctionDeclaration
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeParameter
+
+/**
+ * Used when `ResolverImpl.asMemberOf` is called with an error type or function declaration cannot be found.
+ */
+class KSFunctionErrorImpl(
+ private val declaration: KSFunctionDeclaration
+) : KSFunction {
+ override val isError: Boolean = true
+
+ override val returnType: KSType = KSErrorType
+
+ override val parameterTypes: List<KSType?>
+ get() = declaration.parameters.map {
+ KSErrorType
+ }
+ override val typeParameters: List<KSTypeParameter>
+ get() = emptyList()
+
+ override val extensionReceiverType: KSType?
+ get() = declaration.extensionReceiver?.let {
+ KSErrorType
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as KSFunctionErrorImpl
+
+ if (declaration != other.declaration) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ return declaration.hashCode()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionImpl.kt
new file mode 100644
index 00000000..55eebfbf
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSFunctionImpl.kt
@@ -0,0 +1,76 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.symbol.KSFunction
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeParameter
+import com.google.devtools.ksp.symbol.impl.binary.KSTypeParameterDescriptorImpl
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import java.util.Objects
+
+class KSFunctionImpl(val descriptor: CallableDescriptor) : KSFunction {
+
+ override val isError: Boolean = false
+
+ private val cachedHashCode by lazy(LazyThreadSafetyMode.PUBLICATION) {
+ Objects.hash(
+ returnType ?: 0,
+ parameterTypes,
+ typeParameters,
+ extensionReceiverType ?: 0
+ )
+ }
+
+ override val returnType by lazy(LazyThreadSafetyMode.PUBLICATION) {
+ descriptor.returnType?.let(::getKSTypeCached)
+ }
+ override val parameterTypes: List<KSType> by lazy(LazyThreadSafetyMode.PUBLICATION) {
+ descriptor.valueParameters.map {
+ getKSTypeCached(it.type)
+ }
+ }
+ override val typeParameters: List<KSTypeParameter> by lazy(LazyThreadSafetyMode.PUBLICATION) {
+ descriptor.typeParameters.map {
+ KSTypeParameterDescriptorImpl.getCached(it)
+ }
+ }
+
+ override val extensionReceiverType: KSType? by lazy(LazyThreadSafetyMode.PUBLICATION) {
+ descriptor.extensionReceiverParameter?.type?.let(::getKSTypeCached)
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as KSFunctionImpl
+
+ if (returnType != other.returnType) return false
+ if (parameterTypes != other.parameterTypes) return false
+ if (typeParameters != other.typeParameters) return false
+ if (extensionReceiverType != other.extensionReceiverType) return false
+
+ return true
+ }
+
+ override fun hashCode() = cachedHashCode
+
+ override fun toString(): String {
+ return "KSFunctionImpl(descriptor=$descriptor)"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSNodeKtImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSNodeKtImpl.kt
new file mode 100644
index 00000000..8c44b145
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSNodeKtImpl.kt
@@ -0,0 +1,12 @@
+package com.google.devtools.ksp.symbol.impl.kotlin
+
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.impl.toLocation
+import org.jetbrains.kotlin.psi.KtElement
+
+abstract class KSNodeKtImpl(private val element: KtElement) : KSNode {
+ override val location: Location by lazy {
+ element.toLocation()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyAccessorImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyAccessorImpl.kt
new file mode 100644
index 00000000..d7559bf7
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyAccessorImpl.kt
@@ -0,0 +1,66 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.processing.impl.findAnnotationFromUseSiteTarget
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.toLocation
+import com.google.devtools.ksp.toKSModifiers
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.psi.KtPropertyAccessor
+
+abstract class KSPropertyAccessorImpl(val ktPropertyAccessor: KtPropertyAccessor) : KSPropertyAccessor {
+ companion object {
+ fun getCached(ktPropertyAccessor: KtPropertyAccessor): KSPropertyAccessor {
+ return if (ktPropertyAccessor.isGetter) {
+ KSPropertyGetterImpl.getCached(ktPropertyAccessor)
+ } else {
+ KSPropertySetterImpl.getCached(ktPropertyAccessor)
+ }
+ }
+ }
+ override val receiver: KSPropertyDeclaration by lazy {
+ KSPropertyDeclarationImpl.getCached(ktPropertyAccessor.property as KtProperty)
+ }
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ ktPropertyAccessor.filterUseSiteTargetAnnotations().map { KSAnnotationImpl.getCached(it) }
+ .plus(this.findAnnotationFromUseSiteTarget())
+ }
+
+ override val parent: KSNode? by lazy {
+ receiver
+ }
+
+ override val location: Location by lazy {
+ ktPropertyAccessor.toLocation()
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ ktPropertyAccessor.toKSModifiers()
+ }
+
+ override val origin: Origin = Origin.KOTLIN
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyAccessor(this, data)
+ }
+
+ internal val originalAnnotations: List<KSAnnotation> by lazy {
+ ktPropertyAccessor.annotationEntries.map { KSAnnotationImpl.getCached(it) }
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt
new file mode 100644
index 00000000..312b73d1
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationImpl.kt
@@ -0,0 +1,129 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.symbol.impl.binary.KSPropertyGetterDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.binary.KSPropertySetterDescriptorImpl
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.KtAnnotated
+import org.jetbrains.kotlin.psi.KtAnnotationEntry
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
+import org.jetbrains.kotlin.resolve.BindingContext
+
+class KSPropertyDeclarationImpl private constructor(val ktProperty: KtProperty) :
+ KSPropertyDeclaration,
+ KSDeclarationImpl(ktProperty),
+ KSExpectActual by KSExpectActualImpl(ktProperty) {
+ companion object : KSObjectCache<KtProperty, KSPropertyDeclarationImpl>() {
+ fun getCached(ktProperty: KtProperty) = cache.getOrPut(ktProperty) { KSPropertyDeclarationImpl(ktProperty) }
+ }
+
+ private val propertyDescriptor by lazy {
+ ResolverImpl.instance!!.resolveDeclaration(ktProperty) as? PropertyDescriptor
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ ktProperty.filterUseSiteTargetAnnotations().map { KSAnnotationImpl.getCached(it) }
+ }
+
+ override val extensionReceiver: KSTypeReference? by lazy {
+ if (ktProperty.isExtensionDeclaration()) {
+ KSTypeReferenceImpl.getCached(ktProperty.receiverTypeReference!!)
+ } else {
+ null
+ }
+ }
+
+ override val isMutable: Boolean by lazy {
+ ktProperty.isVar
+ }
+
+ override val hasBackingField: Boolean by lazy {
+ // taken from: https://github.com/JetBrains/kotlin/blob/master/compiler/light-classes/src/org/jetbrains/kotlin/asJava/classes/ultraLightMembersCreator.kt#L104
+ when {
+ ktProperty.initializer != null -> true
+ ktProperty.hasModifier(KtTokens.LATEINIT_KEYWORD) -> true
+ else -> {
+ val context = ResolverImpl.instance!!.bindingTrace.bindingContext
+ val descriptor = ResolverImpl.instance!!.resolveDeclaration(ktProperty)
+ descriptor is PropertyDescriptor && context[BindingContext.BACKING_FIELD_REQUIRED, descriptor] == true
+ }
+ }
+ }
+
+ override val getter: KSPropertyGetter? by lazy {
+ ktProperty.getter?.let {
+ KSPropertyGetterImpl.getCached(it)
+ } ?: propertyDescriptor?.getter?.let {
+ KSPropertyGetterDescriptorImpl.getCached(it)
+ }
+ }
+
+ override val setter: KSPropertySetter? by lazy {
+ ktProperty.setter?.let {
+ KSPropertySetterImpl.getCached(it)
+ } ?: propertyDescriptor?.setter?.let {
+ KSPropertySetterDescriptorImpl.getCached(it)
+ }
+ }
+
+ override val type: KSTypeReference by lazy {
+ if (ktProperty.typeReference != null) {
+ KSTypeReferenceImpl.getCached(ktProperty.typeReference!!)
+ } else {
+ KSTypeReferenceDeferredImpl.getCached(this) {
+ val desc = propertyDescriptor as? VariableDescriptorWithAccessors
+ if (desc == null) {
+ KSErrorType
+ } else {
+ getKSTypeCached(desc.type)
+ }
+ }
+ }
+ }
+
+ override fun isDelegated(): Boolean = ktProperty.hasDelegate()
+
+ override fun findOverridee(): KSPropertyDeclaration? {
+ return propertyDescriptor?.findClosestOverridee()?.toKSPropertyDeclaration()
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyDeclaration(this, data)
+ }
+
+ override fun asMemberOf(containing: KSType): KSType =
+ ResolverImpl.instance!!.asMemberOf(this, containing)
+}
+
+internal fun KtAnnotated.filterUseSiteTargetAnnotations(): Sequence<KtAnnotationEntry> {
+ return this.annotationEntries.asSequence().filter { property ->
+ property.useSiteTarget?.getAnnotationUseSiteTarget()?.let {
+ it != AnnotationUseSiteTarget.PROPERTY_GETTER && it != AnnotationUseSiteTarget.PROPERTY_SETTER &&
+ it != AnnotationUseSiteTarget.SETTER_PARAMETER && it != AnnotationUseSiteTarget.CONSTRUCTOR_PARAMETER
+ } ?: true
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationParameterImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationParameterImpl.kt
new file mode 100644
index 00000000..1e69d243
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyDeclarationParameterImpl.kt
@@ -0,0 +1,107 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.isPrivate
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.*
+import com.google.devtools.ksp.symbol.impl.synthetic.KSPropertyGetterSyntheticImpl
+import com.google.devtools.ksp.symbol.impl.synthetic.KSPropertySetterSyntheticImpl
+import org.jetbrains.kotlin.psi.KtParameter
+
+class KSPropertyDeclarationParameterImpl private constructor(val ktParameter: KtParameter) :
+ KSPropertyDeclaration,
+ KSDeclarationImpl(ktParameter),
+ KSExpectActual by KSExpectActualImpl(ktParameter) {
+ companion object : KSObjectCache<KtParameter, KSPropertyDeclarationParameterImpl>() {
+ fun getCached(ktParameter: KtParameter) = cache.getOrPut(ktParameter) {
+ KSPropertyDeclarationParameterImpl(ktParameter)
+ }
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ ktParameter.filterUseSiteTargetAnnotations().map { KSAnnotationImpl.getCached(it) }
+ .filterNot { valueParameterAnnotation ->
+ valueParameterAnnotation.useSiteTarget == AnnotationUseSiteTarget.PARAM ||
+ (
+ valueParameterAnnotation.annotationType.resolve()
+ .declaration.annotations.any { metaAnnotation ->
+ metaAnnotation.annotationType.resolve().declaration.qualifiedName
+ ?.asString() == "kotlin.annotation.Target" &&
+ (metaAnnotation.arguments.singleOrNull()?.value as? ArrayList<*>)?.any {
+ (it as? KSType)?.declaration?.qualifiedName
+ ?.asString() == "kotlin.annotation.AnnotationTarget.VALUE_PARAMETER"
+ } ?: false
+ } && valueParameterAnnotation.useSiteTarget == null
+ )
+ }
+ }
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ ktParameter.findParentDeclaration()!!.parentDeclaration
+ }
+
+ override val hasBackingField: Boolean
+ get() = true
+
+ override val extensionReceiver: KSTypeReference? = null
+
+ override val isMutable: Boolean by lazy {
+ ktParameter.isMutable
+ }
+
+ override val getter: KSPropertyGetter? by lazy {
+ if (this.isPrivate()) {
+ null
+ } else {
+ KSPropertyGetterSyntheticImpl.getCached(this)
+ }
+ }
+
+ override val setter: KSPropertySetter? by lazy {
+ if (ktParameter.isMutable && !this.isPrivate()) {
+ KSPropertySetterSyntheticImpl.getCached(this)
+ } else {
+ null
+ }
+ }
+
+ override val type: KSTypeReference by lazy {
+ if (ktParameter.typeReference != null) {
+ KSTypeReferenceImpl.getCached(ktParameter.typeReference!!)
+ } else {
+ throw IllegalStateException("properties in parameter must have explicit type")
+ }
+ }
+
+ override fun isDelegated(): Boolean = false
+
+ override fun findOverridee(): KSPropertyDeclaration? {
+ return ResolverImpl.instance!!.resolvePropertyDeclaration(this)?.original
+ ?.findClosestOverridee()?.toKSPropertyDeclaration()
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyDeclaration(this, data)
+ }
+
+ override fun asMemberOf(containing: KSType): KSType =
+ ResolverImpl.instance!!.asMemberOf(this, containing)
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyGetterImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyGetterImpl.kt
new file mode 100644
index 00000000..bf328c29
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertyGetterImpl.kt
@@ -0,0 +1,53 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.binary.KSTypeReferenceDescriptorImpl
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.psi.KtPropertyAccessor
+
+class KSPropertyGetterImpl private constructor(ktPropertyGetter: KtPropertyAccessor) :
+ KSPropertyAccessorImpl(ktPropertyGetter),
+ KSPropertyGetter {
+ companion object : KSObjectCache<KtPropertyAccessor, KSPropertyGetterImpl>() {
+ fun getCached(ktPropertyGetter: KtPropertyAccessor) = cache.getOrPut(ktPropertyGetter) {
+ KSPropertyGetterImpl(ktPropertyGetter)
+ }
+ }
+
+ override val returnType: KSTypeReference? by lazy {
+ val property = ktPropertyGetter.property
+ if (property.typeReference != null) {
+ KSTypeReferenceImpl.getCached(property.typeReference!!)
+ } else {
+ val desc = ResolverImpl.instance!!.resolveDeclaration(property) as PropertyDescriptor
+ KSTypeReferenceDescriptorImpl.getCached(desc.returnType!!, origin, this)
+ }
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyGetter(this, data)
+ }
+
+ override fun toString(): String {
+ return "$receiver.getter()"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertySetterImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertySetterImpl.kt
new file mode 100644
index 00000000..177567b0
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSPropertySetterImpl.kt
@@ -0,0 +1,50 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.impl.synthetic.KSValueParameterSyntheticImpl
+import org.jetbrains.kotlin.psi.KtPropertyAccessor
+
+class KSPropertySetterImpl private constructor(ktPropertySetter: KtPropertyAccessor) :
+ KSPropertyAccessorImpl(ktPropertySetter),
+ KSPropertySetter {
+ companion object : KSObjectCache<KtPropertyAccessor, KSPropertySetterImpl>() {
+ fun getCached(ktPropertySetter: KtPropertyAccessor) = cache.getOrPut(ktPropertySetter) {
+ KSPropertySetterImpl(ktPropertySetter)
+ }
+ }
+
+ override val parameter: KSValueParameter by lazy {
+ ktPropertySetter.parameterList?.parameters?.singleOrNull()?.let { KSValueParameterImpl.getCached(it) }
+ ?: KSValueParameterSyntheticImpl.getCached(this) {
+ ResolverImpl.instance!!.resolvePropertyAccessorDeclaration(this)
+ ?.valueParameters?.singleOrNull()
+ }
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertySetter(this, data)
+ }
+
+ override fun toString(): String {
+ return "$receiver.setter()"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeAliasImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeAliasImpl.kt
new file mode 100644
index 00000000..7ccbcec6
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeAliasImpl.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.symbol.*
+import org.jetbrains.kotlin.psi.*
+
+class KSTypeAliasImpl private constructor(val ktTypeAlias: KtTypeAlias) :
+ KSTypeAlias,
+ KSDeclarationImpl(ktTypeAlias),
+ KSExpectActual by KSExpectActualImpl(ktTypeAlias) {
+ companion object : KSObjectCache<KtTypeAlias, KSTypeAliasImpl>() {
+ fun getCached(ktTypeAlias: KtTypeAlias) = cache.getOrPut(ktTypeAlias) { KSTypeAliasImpl(ktTypeAlias) }
+ }
+
+ override val name: KSName by lazy {
+ KSNameImpl.getCached(ktTypeAlias.name!!)
+ }
+
+ override val type: KSTypeReference by lazy {
+ KSTypeReferenceImpl.getCached(ktTypeAlias.getTypeReference()!!)
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeAlias(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeArgumentImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeArgumentImpl.kt
new file mode 100644
index 00000000..d3cb3975
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeArgumentImpl.kt
@@ -0,0 +1,83 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.findParentOfType
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSTypeArgument
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.Variance
+import com.google.devtools.ksp.symbol.impl.toLocation
+import org.jetbrains.kotlin.psi.KtProjectionKind
+import org.jetbrains.kotlin.psi.KtTypeProjection
+import org.jetbrains.kotlin.psi.KtUserType
+
+abstract class KSTypeArgumentImpl : KSTypeArgument {
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeArgument(this, data)
+ }
+
+ override fun toString(): String {
+ return "$variance $type"
+ }
+}
+
+class KSTypeArgumentKtImpl private constructor(val ktTypeArgument: KtTypeProjection) : KSTypeArgumentImpl() {
+ companion object : KSObjectCache<KtTypeProjection, KSTypeArgumentKtImpl>() {
+ fun getCached(ktTypeArgument: KtTypeProjection) = cache.getOrPut(ktTypeArgument) {
+ KSTypeArgumentKtImpl(ktTypeArgument)
+ }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location by lazy {
+ ktTypeArgument.toLocation()
+ }
+
+ override val parent: KSNode? by lazy {
+ ktTypeArgument.findParentOfType<KtUserType>()?.let { KSClassifierReferenceImpl.getCached(it) }
+ }
+
+ override val variance: Variance by lazy {
+ when (ktTypeArgument.projectionKind) {
+ KtProjectionKind.STAR -> Variance.STAR
+ KtProjectionKind.IN -> Variance.CONTRAVARIANT
+ KtProjectionKind.NONE -> Variance.INVARIANT
+ KtProjectionKind.OUT -> Variance.COVARIANT
+ }
+ }
+
+ override val type: KSTypeReference? by lazy {
+ if (ktTypeArgument.typeReference != null) {
+ KSTypeReferenceImpl.getCached(ktTypeArgument.typeReference!!)
+ } else {
+ null
+ }
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ ktTypeArgument.annotationEntries.asSequence().map { KSAnnotationImpl.getCached(it) }.memoized()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeArgumentLiteImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeArgumentLiteImpl.kt
new file mode 100644
index 00000000..d080fd87
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeArgumentLiteImpl.kt
@@ -0,0 +1,56 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.findParentOfType
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.Variance
+import org.jetbrains.kotlin.psi.KtFunctionType
+import org.jetbrains.kotlin.psi.KtTypeReference
+
+class KSTypeArgumentLiteImpl private constructor(override val type: KSTypeReference, override val variance: Variance) :
+ KSTypeArgumentImpl() {
+ companion object : KSObjectCache<Pair<KSTypeReference, Variance>, KSTypeArgumentLiteImpl>() {
+ fun getCached(type: KSTypeReference, variance: Variance) = cache.getOrPut(Pair(type, variance)) {
+ KSTypeArgumentLiteImpl(type, variance)
+ }
+
+ fun getCached(type: KtTypeReference) = cache.getOrPut(
+ Pair(KSTypeReferenceImpl.getCached(type), Variance.INVARIANT)
+ ) {
+ KSTypeArgumentLiteImpl(KSTypeReferenceImpl.getCached(type), Variance.INVARIANT)
+ }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location = NonExistLocation
+
+ override val parent: KSNode? by lazy {
+ (type as? KSTypeReferenceImpl)?.ktTypeReference
+ ?.findParentOfType<KtFunctionType>()?.let { KSCallableReferenceImpl.getCached(it) }
+ }
+
+ override val annotations: Sequence<KSAnnotation> = type.annotations
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt
new file mode 100644
index 00000000..9e8929a8
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeImpl.kt
@@ -0,0 +1,154 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.IdKey
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeArgument
+import com.google.devtools.ksp.symbol.Nullability
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.binary.KSAnnotationDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.binary.KSTypeArgumentDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.convertKotlinType
+import com.google.devtools.ksp.symbol.impl.replaceTypeArguments
+import org.jetbrains.kotlin.builtins.isFunctionType
+import org.jetbrains.kotlin.builtins.isKFunctionType
+import org.jetbrains.kotlin.builtins.isKSuspendFunctionType
+import org.jetbrains.kotlin.builtins.isSuspendFunctionType
+import org.jetbrains.kotlin.descriptors.NotFoundClasses
+import org.jetbrains.kotlin.descriptors.SourceElement
+import org.jetbrains.kotlin.types.*
+import org.jetbrains.kotlin.types.typeUtil.TypeNullability
+import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
+import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
+import org.jetbrains.kotlin.types.typeUtil.makeNullable
+import org.jetbrains.kotlin.types.typeUtil.nullability
+import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithStarProjections
+
+class KSTypeImpl private constructor(
+ val kotlinType: KotlinType,
+ private val ksTypeArguments: List<KSTypeArgument>? = null,
+ override val annotations: Sequence<KSAnnotation> = sequenceOf()
+) : KSType {
+ companion object : KSObjectCache<IdKey<KotlinType>, KSTypeImpl>() {
+ fun getCached(
+ kotlinType: KotlinType,
+ ksTypeArguments: List<KSTypeArgument>? = null,
+ annotations: Sequence<KSAnnotation> = sequenceOf()
+ ): KSTypeImpl {
+ return cache.getOrPut(IdKey(kotlinType)) { KSTypeImpl(kotlinType, ksTypeArguments, annotations) }
+ }
+ }
+
+ override val declaration: KSDeclaration by lazy {
+ ResolverImpl.instance!!.findDeclaration(kotlinType.getAbbreviation() ?: kotlinType)
+ }
+
+ override val nullability: Nullability by lazy {
+ when (kotlinType.nullability()) {
+ TypeNullability.NULLABLE -> Nullability.NULLABLE
+ TypeNullability.NOT_NULL -> Nullability.NOT_NULL
+ TypeNullability.FLEXIBLE -> Nullability.PLATFORM
+ }
+ }
+
+ // TODO: fix calls to getKSTypeCached and use ksTypeArguments when available.
+ override val arguments: List<KSTypeArgument> by lazy {
+ (kotlinType.getAbbreviation() ?: kotlinType).arguments.map {
+ KSTypeArgumentDescriptorImpl.getCached(it, Origin.SYNTHETIC, null)
+ }
+ }
+
+ override fun isAssignableFrom(that: KSType): Boolean {
+ val subType = (that as? KSTypeImpl)?.kotlinType?.convertKotlinType() ?: return false
+ ResolverImpl.instance!!.incrementalContext.recordLookupWithSupertypes(subType)
+ val thisType = (this as? KSTypeImpl)?.kotlinType?.convertKotlinType() ?: return false
+ return subType.isSubtypeOf(thisType)
+ }
+
+ // TODO: find a better way to reuse the logic in [DescriptorRendererImpl.renderFlexibleType].
+ override fun isMutabilityFlexible(): Boolean {
+ return kotlinType.toString().startsWith("(Mutable)")
+ }
+
+ // TODO: find a better way to reuse the logic in [DescriptorRendererImpl.renderFlexibleType].
+ override fun isCovarianceFlexible(): Boolean {
+ return kotlinType.toString().startsWith("Array<(out) ")
+ }
+
+ override fun replace(arguments: List<KSTypeArgument>): KSType {
+ return kotlinType.replaceTypeArguments(arguments)?.let {
+ getKSTypeCached(it, arguments)
+ } ?: KSErrorType
+ }
+
+ override fun starProjection(): KSType {
+ return getKSTypeCached(kotlinType.replaceArgumentsWithStarProjections())
+ }
+
+ private val meNullable: KSType by lazy { getKSTypeCached(kotlinType.makeNullable()) }
+ override fun makeNullable(): KSType = meNullable
+
+ private val meNotNullable: KSType by lazy { getKSTypeCached(kotlinType.makeNotNullable()) }
+ override fun makeNotNullable(): KSType = meNotNullable
+
+ override val isMarkedNullable: Boolean = kotlinType.isMarkedNullable
+
+ override val isError: Boolean = false
+
+ override fun equals(other: Any?): Boolean {
+ if (other !is KSTypeImpl)
+ return false
+ return kotlinType.equals(other.kotlinType)
+ }
+
+ override fun hashCode(): Int = kotlinType.hashCode()
+
+ override fun toString(): String = (kotlinType.getAbbreviation() ?: kotlinType).toString()
+
+ override val isFunctionType: Boolean
+ get() = kotlinType.isFunctionType || kotlinType.isKFunctionType
+
+ override val isSuspendFunctionType: Boolean
+ get() = kotlinType.isSuspendFunctionType || kotlinType.isKSuspendFunctionType
+}
+
+fun getKSTypeCached(
+ kotlinType: KotlinType,
+ ksTypeArguments: List<KSTypeArgument>? = null,
+ annotations: Sequence<KSAnnotation> = sequenceOf()
+): KSType {
+ return if (kotlinType.isError ||
+ kotlinType.constructor.declarationDescriptor is NotFoundClasses.MockClassDescriptor
+ ) {
+ KSErrorType
+ } else {
+ KSTypeImpl.getCached(
+ kotlinType,
+ ksTypeArguments,
+ annotations + kotlinType.annotations
+ .filter { it.source == SourceElement.NO_SOURCE }
+ .map { KSAnnotationDescriptorImpl.getCached(it, null) }
+ .asSequence()
+ )
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeParameterImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeParameterImpl.kt
new file mode 100644
index 00000000..340833a4
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeParameterImpl.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.KSExpectActual
+import com.google.devtools.ksp.symbol.KSName
+import com.google.devtools.ksp.symbol.KSTypeParameter
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Variance
+import com.google.devtools.ksp.symbol.impl.synthetic.KSTypeReferenceSyntheticImpl
+import org.jetbrains.kotlin.lexer.KtTokens
+import org.jetbrains.kotlin.psi.KtTypeParameter
+import org.jetbrains.kotlin.psi.KtTypeParameterListOwner
+
+class KSTypeParameterImpl private constructor(val ktTypeParameter: KtTypeParameter) :
+ KSTypeParameter,
+ KSDeclarationImpl(ktTypeParameter),
+ KSExpectActual by KSExpectActualNoImpl() {
+ companion object : KSObjectCache<KtTypeParameter, KSTypeParameterImpl>() {
+ fun getCached(ktTypeParameter: KtTypeParameter) =
+ cache.getOrPut(ktTypeParameter) { KSTypeParameterImpl(ktTypeParameter) }
+ }
+
+ override val name: KSName by lazy {
+ KSNameImpl.getCached(ktTypeParameter.name!!)
+ }
+
+ override val isReified: Boolean by lazy {
+ ktTypeParameter.modifierList?.hasModifier(KtTokens.REIFIED_KEYWORD) ?: false
+ }
+
+ override val variance: Variance by lazy {
+ when {
+ ktTypeParameter.modifierList == null -> Variance.INVARIANT
+ ktTypeParameter.modifierList!!.hasModifier(KtTokens.OUT_KEYWORD) -> Variance.COVARIANT
+ ktTypeParameter.modifierList!!.hasModifier(KtTokens.IN_KEYWORD) -> Variance.CONTRAVARIANT
+ else -> Variance.INVARIANT
+ }
+ }
+
+ private val owner: KtTypeParameterListOwner by lazy {
+ (parentDeclaration as KSDeclarationImpl).ktDeclaration as KtTypeParameterListOwner
+ }
+
+ override val bounds: Sequence<KSTypeReference> by lazy {
+ val list = sequenceOf(ktTypeParameter.extendsBound)
+ list.plus(
+ owner.typeConstraints
+ .filter {
+ it.subjectTypeParameterName!!.getReferencedName() == ktTypeParameter.nameAsSafeName.asString()
+ }
+ .map { it.boundTypeReference }
+ ).filterNotNull().map { KSTypeReferenceImpl.getCached(it) }.ifEmpty {
+ sequenceOf(
+ KSTypeReferenceSyntheticImpl.getCached(ResolverImpl.instance!!.builtIns.anyType.makeNullable(), this)
+ )
+ }.memoized()
+ }
+
+ override val qualifiedName: KSName? by lazy {
+ KSNameImpl.getCached("${this.parentDeclaration!!.qualifiedName!!.asString()}.${simpleName.asString()}")
+ }
+
+ override val simpleName: KSName by lazy {
+ KSNameImpl.getCached(ktTypeParameter.name ?: "_")
+ }
+
+ override val typeParameters: List<KSTypeParameter> = emptyList()
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeParameter(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceDeferredImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceDeferredImpl.kt
new file mode 100644
index 00000000..16a74374
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceDeferredImpl.kt
@@ -0,0 +1,69 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSDeclaration
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSReferenceElement
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.Modifier
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.getInstanceForCurrentRound
+
+class KSTypeReferenceDeferredImpl private constructor(
+ private val resolver: () -> KSType,
+ override val parent: KSNode?
+) : KSTypeReference {
+ companion object : KSObjectCache<KSDeclaration, KSTypeReferenceDeferredImpl>() {
+ fun getCached(parent: KSDeclaration, resolver: () -> KSType): KSTypeReferenceDeferredImpl {
+ val currentParent = parent.getInstanceForCurrentRound() as KSDeclaration
+ return cache
+ .getOrPut(currentParent) { KSTypeReferenceDeferredImpl(resolver, currentParent) }
+ }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location = NonExistLocation
+
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override val element: KSReferenceElement? = null
+
+ override val modifiers: Set<Modifier> = emptySet()
+
+ private val resolved: KSType by lazy {
+ resolver()
+ }
+
+ override fun resolve(): KSType = resolved
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeReference(this, data)
+ }
+
+ override fun toString(): String {
+ return resolved.toString()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceImpl.kt
new file mode 100644
index 00000000..9f751700
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceImpl.kt
@@ -0,0 +1,129 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSReferenceElement
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+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.symbol.impl.toLocation
+import com.google.devtools.ksp.toKSModifiers
+import org.jetbrains.kotlin.psi.*
+
+class KSTypeReferenceImpl private constructor(val ktTypeReference: KtTypeReference) : KSTypeReference {
+ companion object : KSObjectCache<KtTypeReference, KSTypeReferenceImpl>() {
+ fun getCached(ktTypeReference: KtTypeReference) = cache.getOrPut(ktTypeReference) {
+ KSTypeReferenceImpl(ktTypeReference)
+ }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location by lazy {
+ ktTypeReference.toLocation()
+ }
+ override val parent: KSNode? by lazy {
+ var parentPsi = ktTypeReference.parent
+ while (
+ parentPsi != null && parentPsi !is KtAnnotationEntry && parentPsi !is KtFunctionType &&
+ parentPsi !is KtClassOrObject && parentPsi !is KtFunction && parentPsi !is KtUserType &&
+ parentPsi !is KtProperty && parentPsi !is KtTypeAlias && parentPsi !is KtTypeProjection &&
+ parentPsi !is KtTypeParameter && parentPsi !is KtParameter
+ ) {
+ parentPsi = parentPsi.parent
+ }
+ when (parentPsi) {
+ is KtAnnotationEntry -> KSAnnotationImpl.getCached(parentPsi)
+ is KtFunctionType -> KSCallableReferenceImpl.getCached(parentPsi)
+ is KtClassOrObject -> KSClassDeclarationImpl.getCached(parentPsi)
+ is KtFunction -> KSFunctionDeclarationImpl.getCached(parentPsi)
+ is KtUserType -> KSClassifierReferenceImpl.getCached(parentPsi)
+ is KtProperty -> KSPropertyDeclarationImpl.getCached(parentPsi)
+ is KtTypeAlias -> KSTypeAliasImpl.getCached(parentPsi)
+ is KtTypeProjection -> KSTypeArgumentKtImpl.getCached(parentPsi)
+ is KtTypeParameter -> KSTypeParameterImpl.getCached(parentPsi)
+ is KtParameter -> KSValueParameterImpl.getCached(parentPsi)
+ else -> null
+ }
+ }
+
+ // Parenthesized type in grammar seems to be implemented as KtNullableType.
+ private fun visitNullableType(visit: (KtNullableType) -> Unit) {
+ var typeElement = ktTypeReference.typeElement
+ while (typeElement is KtNullableType) {
+ visit(typeElement)
+ typeElement = typeElement.innerType
+ }
+ }
+
+ // Annotations and modifiers are only allowed in one of the parenthesized type.
+ // https://github.com/JetBrains/kotlin/blob/50e12239ef8141a45c4dca2bf0544be6191ecfb6/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java#L608
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ fun List<KtAnnotationEntry>.toKSAnnotations(): Sequence<KSAnnotation> =
+ asSequence().map {
+ KSAnnotationImpl.getCached(it)
+ }
+
+ val innerAnnotations = mutableListOf<Sequence<KSAnnotation>>()
+ visitNullableType {
+ innerAnnotations.add(it.annotationEntries.toKSAnnotations())
+ }
+
+ (ktTypeReference.annotationEntries.toKSAnnotations() + innerAnnotations.asSequence().flatten()).memoized()
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ val innerModifiers = mutableSetOf<Modifier>()
+ visitNullableType {
+ innerModifiers.addAll(it.modifierList.toKSModifiers())
+ }
+ ktTypeReference.toKSModifiers() + innerModifiers
+ }
+
+ override val element: KSReferenceElement by lazy {
+ var typeElement = ktTypeReference.typeElement
+ while (typeElement is KtNullableType)
+ typeElement = typeElement.innerType
+ when (typeElement) {
+ is KtFunctionType -> KSCallableReferenceImpl.getCached(typeElement)
+ is KtUserType -> KSClassifierReferenceImpl.getCached(typeElement)
+ is KtDynamicType -> KSDynamicReferenceImpl.getCached(this)
+ is KtIntersectionType -> KSDefNonNullReferenceImpl.getCached(typeElement)
+ else -> throw IllegalStateException("Unexpected type element ${typeElement?.javaClass}, $ExceptionMessage")
+ }
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeReference(this, data)
+ }
+
+ override fun resolve(): KSType = ResolverImpl.instance!!.resolveUserType(this)
+
+ override fun toString(): String {
+ return element.toString()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueArgumentImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueArgumentImpl.kt
new file mode 100644
index 00000000..aac1f416
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueArgumentImpl.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSName
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSValueArgument
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+
+class KSValueArgumentLiteImpl private constructor(
+ override val name: KSName,
+ override val value: Any?,
+ override val parent: KSNode?,
+ override val origin: Origin
+) : KSValueArgumentImpl() {
+ companion object : KSObjectCache<Triple<KSName, Any?, KSNode>, KSValueArgumentLiteImpl>() {
+
+ fun getCached(name: KSName, value: Any?, parent: KSNode, origin: Origin = Origin.KOTLIN) = cache
+ .getOrPut(Triple(name, value, parent)) {
+ KSValueArgumentLiteImpl(name, value, parent, origin)
+ }
+ }
+
+ override val location: Location = NonExistLocation
+
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override val isSpread: Boolean = false
+}
+
+abstract class KSValueArgumentImpl : KSValueArgument {
+ override fun hashCode(): Int {
+ return name.hashCode() * 31 + value.hashCode()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (other !is KSValueArgument)
+ return false
+
+ return other.name == this.name && other.value == this.value
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitValueArgument(this, data)
+ }
+
+ override fun toString(): String {
+ return "${name?.asString() ?: ""}:$value"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueParameterImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueParameterImpl.kt
new file mode 100644
index 00000000..162d77fa
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSValueParameterImpl.kt
@@ -0,0 +1,131 @@
+/*
+ * 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.symbol.impl.kotlin
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.memoized
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.findAnnotationFromUseSiteTarget
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSName
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSPropertyDeclaration
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSValueParameter
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.synthetic.KSTypeReferenceSyntheticImpl
+import com.google.devtools.ksp.symbol.impl.toLocation
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
+import org.jetbrains.kotlin.lexer.KtTokens.CROSSINLINE_KEYWORD
+import org.jetbrains.kotlin.lexer.KtTokens.NOINLINE_KEYWORD
+import org.jetbrains.kotlin.psi.KtAnnotationEntry
+import org.jetbrains.kotlin.psi.KtFunction
+import org.jetbrains.kotlin.psi.KtFunctionType
+import org.jetbrains.kotlin.psi.KtParameter
+import org.jetbrains.kotlin.psi.KtProperty
+import org.jetbrains.kotlin.psi.KtPropertyAccessor
+
+class KSValueParameterImpl private constructor(val ktParameter: KtParameter) : KSValueParameter {
+ companion object : KSObjectCache<KtParameter, KSValueParameterImpl>() {
+ fun getCached(ktParameter: KtParameter) = cache.getOrPut(ktParameter) { KSValueParameterImpl(ktParameter) }
+ }
+
+ override val origin = Origin.KOTLIN
+
+ override val location: Location by lazy {
+ ktParameter.toLocation()
+ }
+
+ override val parent: KSNode? by lazy {
+ var parentPsi = ktParameter.parent
+ while (
+ parentPsi != null && parentPsi !is KtAnnotationEntry && parentPsi !is KtFunctionType &&
+ parentPsi !is KtFunction && parentPsi !is KtPropertyAccessor
+ ) {
+ parentPsi = parentPsi.parent
+ }
+ when (parentPsi) {
+ is KtAnnotationEntry -> KSAnnotationImpl.getCached(parentPsi)
+ is KtFunctionType -> KSCallableReferenceImpl.getCached(parentPsi)
+ is KtFunction -> KSFunctionDeclarationImpl.getCached(parentPsi)
+ is KtPropertyAccessor -> if (parentPsi.isSetter) KSPropertySetterImpl.getCached(parentPsi) else null
+ else -> null
+ }
+ }
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ ktParameter.annotationEntries.asSequence().filter { annotation ->
+ annotation.useSiteTarget?.getAnnotationUseSiteTarget()?.let {
+ it != AnnotationUseSiteTarget.PROPERTY_GETTER &&
+ it != AnnotationUseSiteTarget.PROPERTY_SETTER &&
+ it != AnnotationUseSiteTarget.SETTER_PARAMETER &&
+ it != AnnotationUseSiteTarget.FIELD
+ } ?: true
+ }.map { KSAnnotationImpl.getCached(it) }.filterNot { valueParameterAnnotation ->
+ valueParameterAnnotation.annotationType.resolve().declaration.annotations.any { metaAnnotation ->
+ metaAnnotation.annotationType.resolve().declaration.qualifiedName
+ ?.asString() == "kotlin.annotation.Target" &&
+ (metaAnnotation.arguments.singleOrNull()?.value as? ArrayList<*>)?.none {
+ (it as? KSType)?.declaration?.qualifiedName
+ ?.asString() == "kotlin.annotation.AnnotationTarget.VALUE_PARAMETER"
+ } ?: false
+ }
+ }
+ .plus(this.findAnnotationFromUseSiteTarget()).memoized()
+ }
+
+ override val isCrossInline: Boolean = ktParameter.hasModifier(CROSSINLINE_KEYWORD)
+
+ override val isNoInline: Boolean = ktParameter.hasModifier(NOINLINE_KEYWORD)
+
+ override val isVararg: Boolean = ktParameter.isVarArg
+
+ override val isVal = ktParameter.hasValOrVar() && !ktParameter.isMutable
+
+ override val isVar = ktParameter.hasValOrVar() && ktParameter.isMutable
+
+ override val name: KSName? by lazy {
+ if (ktParameter.name == null) {
+ null
+ } else {
+ KSNameImpl.getCached(ktParameter.name!!)
+ }
+ }
+
+ override val type: KSTypeReference by lazy {
+ ktParameter.typeReference?.let { KSTypeReferenceImpl.getCached(it) }
+ ?: findPropertyForAccessor()?.type ?: KSTypeReferenceSyntheticImpl.getCached(KSErrorType, this)
+ }
+
+ override val hasDefault: Boolean = ktParameter.hasDefaultValue()
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitValueParameter(this, data)
+ }
+
+ override fun toString(): String {
+ return name?.asString() ?: "_"
+ }
+
+ private fun findPropertyForAccessor(): KSPropertyDeclaration? {
+ return (ktParameter.parent?.parent?.parent as? KtProperty)?.let { KSPropertyDeclarationImpl.getCached(it) }
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSConstructorSyntheticImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSConstructorSyntheticImpl.kt
new file mode 100644
index 00000000..19108d99
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSConstructorSyntheticImpl.kt
@@ -0,0 +1,119 @@
+/*
+ * 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.symbol.impl.synthetic
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.isPublic
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+
+class KSConstructorSyntheticImpl private constructor(val ksClassDeclaration: KSClassDeclaration) :
+ KSFunctionDeclaration,
+ KSDeclaration
+ by ksClassDeclaration {
+ companion object : KSObjectCache<KSClassDeclaration, KSConstructorSyntheticImpl>() {
+ fun getCached(ksClassDeclaration: KSClassDeclaration) =
+ KSConstructorSyntheticImpl.cache.getOrPut(ksClassDeclaration) {
+ KSConstructorSyntheticImpl(ksClassDeclaration)
+ }
+ }
+
+ override val isAbstract: Boolean = false
+
+ override val extensionReceiver: KSTypeReference? = null
+
+ override val parameters: List<KSValueParameter> = emptyList()
+
+ override val functionKind: FunctionKind = FunctionKind.MEMBER
+
+ override val qualifiedName: KSName? by lazy {
+ KSNameImpl.getCached(ksClassDeclaration.qualifiedName?.asString()?.plus(".<init>") ?: "")
+ }
+
+ override val simpleName: KSName by lazy {
+ KSNameImpl.getCached("<init>")
+ }
+
+ override val typeParameters: List<KSTypeParameter> = emptyList()
+
+ override val containingFile: KSFile? by lazy {
+ ksClassDeclaration.containingFile
+ }
+
+ override val parentDeclaration: KSDeclaration? by lazy {
+ ksClassDeclaration
+ }
+
+ override val parent: KSNode? by lazy {
+ parentDeclaration
+ }
+
+ override val returnType: KSTypeReference by lazy {
+ KSTypeReferenceSyntheticImpl(
+ ksClassDeclaration.asStarProjectedType(), this
+ )
+ }
+
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override val isActual: Boolean = false
+
+ override val isExpect: Boolean = false
+
+ override val declarations: Sequence<KSDeclaration> = emptySequence()
+
+ override val location: Location by lazy {
+ ksClassDeclaration.location
+ }
+
+ override val modifiers: Set<Modifier> by lazy {
+ if (ksClassDeclaration.classKind == ClassKind.ENUM_CLASS) {
+ return@lazy setOf(Modifier.FINAL, Modifier.PRIVATE)
+ }
+ // add public if parent class is public
+ if (ksClassDeclaration.isPublic()) {
+ setOf(Modifier.FINAL, Modifier.PUBLIC)
+ } else {
+ setOf(Modifier.FINAL)
+ }
+ }
+
+ override val origin: Origin = Origin.SYNTHETIC
+
+ override fun findOverridee(): KSFunctionDeclaration? = null
+
+ override fun findActuals(): Sequence<KSDeclaration> {
+ return emptySequence()
+ }
+
+ override fun findExpects(): Sequence<KSDeclaration> {
+ return emptySequence()
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitFunctionDeclaration(this, data)
+ }
+
+ override fun toString(): String {
+ return "synthetic constructor for ${this.parentDeclaration}"
+ }
+
+ override fun asMemberOf(containing: KSType): KSFunction =
+ ResolverImpl.instance!!.asMemberOf(this, containing)
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSErrorTypeClassDeclaration.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSErrorTypeClassDeclaration.kt
new file mode 100644
index 00000000..2a71233b
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSErrorTypeClassDeclaration.kt
@@ -0,0 +1,96 @@
+/*
+ * 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.symbol.impl.synthetic
+
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.*
+
+object KSErrorTypeClassDeclaration : KSClassDeclaration {
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override val classKind: ClassKind = ClassKind.CLASS
+
+ override val containingFile: KSFile? = null
+
+ override val declarations: Sequence<KSDeclaration> = emptySequence()
+
+ override val isActual: Boolean = false
+
+ override val isExpect: Boolean = false
+
+ override val isCompanionObject: Boolean = false
+
+ override val location: Location = NonExistLocation
+
+ override val parent: KSNode? = null
+
+ override val modifiers: Set<Modifier> = emptySet()
+
+ override val origin: Origin = Origin.SYNTHETIC
+
+ override val packageName: KSName = KSNameImpl.getCached("")
+
+ override val parentDeclaration: KSDeclaration? = null
+
+ override val primaryConstructor: KSFunctionDeclaration? = null
+
+ override val qualifiedName: KSName? = null
+
+ override val simpleName: KSName = KSNameImpl.getCached("<Error>")
+
+ override val superTypes: Sequence<KSTypeReference> = emptySequence()
+
+ override val typeParameters: List<KSTypeParameter> = emptyList()
+
+ override fun getSealedSubclasses(): Sequence<KSClassDeclaration> = emptySequence()
+
+ override fun asStarProjectedType(): KSType {
+ return ResolverImpl.instance!!.builtIns.nothingType
+ }
+
+ override fun asType(typeArguments: List<KSTypeArgument>): KSType {
+ return ResolverImpl.instance!!.builtIns.nothingType
+ }
+
+ override fun findActuals(): Sequence<KSDeclaration> {
+ return emptySequence()
+ }
+
+ override fun findExpects(): Sequence<KSDeclaration> {
+ return emptySequence()
+ }
+
+ override fun getAllFunctions(): Sequence<KSFunctionDeclaration> {
+ return emptySequence()
+ }
+
+ override fun getAllProperties(): Sequence<KSPropertyDeclaration> {
+ return emptySequence()
+ }
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitClassDeclaration(this, data)
+ }
+
+ override fun toString(): String {
+ return "Error type synthetic declaration"
+ }
+
+ override val docString = null
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertyAccessorSyntheticImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertyAccessorSyntheticImpl.kt
new file mode 100644
index 00000000..f6f0ad9f
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertyAccessorSyntheticImpl.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.symbol.impl.synthetic
+
+import com.google.devtools.ksp.processing.impl.findAnnotationFromUseSiteTarget
+import com.google.devtools.ksp.symbol.*
+
+abstract class KSPropertyAccessorSyntheticImpl(ksPropertyDeclaration: KSPropertyDeclaration) : KSPropertyAccessor {
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ this.findAnnotationFromUseSiteTarget()
+ }
+
+ override val location: Location by lazy {
+ ksPropertyDeclaration.location
+ }
+
+ override val modifiers: Set<Modifier> = emptySet()
+
+ override val origin: Origin = Origin.SYNTHETIC
+
+ override val receiver: KSPropertyDeclaration = ksPropertyDeclaration
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyAccessor(this, data)
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertyGetterSyntheticImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertyGetterSyntheticImpl.kt
new file mode 100644
index 00000000..70455bb3
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertyGetterSyntheticImpl.kt
@@ -0,0 +1,59 @@
+/*
+ * 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.symbol.impl.synthetic
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSPropertyDeclaration
+import com.google.devtools.ksp.symbol.KSPropertyGetter
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.impl.binary.KSTypeReferenceDescriptorImpl
+import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
+
+class KSPropertyGetterSyntheticImpl(val ksPropertyDeclaration: KSPropertyDeclaration) :
+ KSPropertyAccessorSyntheticImpl(ksPropertyDeclaration), KSPropertyGetter {
+ companion object : KSObjectCache<KSPropertyDeclaration, KSPropertyGetterSyntheticImpl>() {
+ fun getCached(ksPropertyDeclaration: KSPropertyDeclaration) =
+ KSPropertyGetterSyntheticImpl.cache.getOrPut(ksPropertyDeclaration) {
+ KSPropertyGetterSyntheticImpl(ksPropertyDeclaration)
+ }
+ }
+
+ private val descriptor: PropertyAccessorDescriptor by lazy {
+ ResolverImpl.instance!!.resolvePropertyDeclaration(ksPropertyDeclaration)!!.getter!!
+ }
+
+ override val returnType: KSTypeReference? by lazy {
+ if (descriptor.returnType != null) {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.returnType!!, origin, this)
+ } else {
+ null
+ }
+ }
+ override val parent: KSNode? = ksPropertyDeclaration
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertyGetter(this, data)
+ }
+
+ override fun toString(): String {
+ return "$receiver.getter()"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertySetterSyntheticImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertySetterSyntheticImpl.kt
new file mode 100644
index 00000000..c8120e55
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSPropertySetterSyntheticImpl.kt
@@ -0,0 +1,57 @@
+/*
+ * 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.symbol.impl.synthetic
+
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSPropertyDeclaration
+import com.google.devtools.ksp.symbol.KSPropertySetter
+import com.google.devtools.ksp.symbol.KSValueParameter
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.impl.binary.KSValueParameterDescriptorImpl
+import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
+
+class KSPropertySetterSyntheticImpl(val ksPropertyDeclaration: KSPropertyDeclaration) :
+ KSPropertyAccessorSyntheticImpl(ksPropertyDeclaration), KSPropertySetter {
+ companion object : KSObjectCache<KSPropertyDeclaration, KSPropertySetterSyntheticImpl>() {
+ fun getCached(ksPropertyDeclaration: KSPropertyDeclaration) =
+ KSPropertySetterSyntheticImpl.cache.getOrPut(ksPropertyDeclaration) {
+ KSPropertySetterSyntheticImpl(ksPropertyDeclaration)
+ }
+ }
+
+ private val descriptor: PropertyAccessorDescriptor by lazy {
+ ResolverImpl.instance!!.resolvePropertyDeclaration(ksPropertyDeclaration)!!.setter!!
+ }
+
+ override val parameter: KSValueParameter by lazy {
+ descriptor.valueParameters.singleOrNull()?.let { KSValueParameterDescriptorImpl.getCached(it, this) }
+ ?: throw IllegalStateException("Failed to resolve property type")
+ }
+
+ override val parent: KSNode? = ksPropertyDeclaration
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitPropertySetter(this, data)
+ }
+
+ override fun toString(): String {
+ return "$receiver.getter()"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSTypeReferenceSyntheticImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSTypeReferenceSyntheticImpl.kt
new file mode 100644
index 00000000..aa2631e4
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSTypeReferenceSyntheticImpl.kt
@@ -0,0 +1,43 @@
+package com.google.devtools.ksp.symbol.impl.synthetic
+
+import com.google.devtools.ksp.IdKey
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSReferenceElement
+import com.google.devtools.ksp.symbol.KSType
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.Modifier
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+
+class KSTypeReferenceSyntheticImpl(val ksType: KSType, override val parent: KSNode?) : KSTypeReference {
+ companion object : KSObjectCache<Pair<IdKey<KSType>, KSNode?>, KSTypeReferenceSyntheticImpl>() {
+ fun getCached(ksType: KSType, parent: KSNode?) = KSTypeReferenceSyntheticImpl.cache
+ .getOrPut(Pair(IdKey(ksType), parent)) { KSTypeReferenceSyntheticImpl(ksType, parent) }
+ }
+
+ override val annotations: Sequence<KSAnnotation> = emptySequence()
+
+ override val element: KSReferenceElement? = null
+
+ override val location: Location = NonExistLocation
+
+ override val modifiers: Set<Modifier> = emptySet()
+
+ override val origin: Origin = Origin.SYNTHETIC
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitTypeReference(this, data)
+ }
+
+ override fun resolve(): KSType {
+ return ksType
+ }
+
+ override fun toString(): String {
+ return ksType.toString()
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSValueParameterSyntheticImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSValueParameterSyntheticImpl.kt
new file mode 100644
index 00000000..6e5692b2
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/synthetic/KSValueParameterSyntheticImpl.kt
@@ -0,0 +1,76 @@
+package com.google.devtools.ksp.symbol.impl.synthetic
+
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KSObjectCache
+import com.google.devtools.ksp.processing.impl.KSNameImpl
+import com.google.devtools.ksp.processing.impl.findAnnotationFromUseSiteTarget
+import com.google.devtools.ksp.symbol.KSAnnotated
+import com.google.devtools.ksp.symbol.KSAnnotation
+import com.google.devtools.ksp.symbol.KSName
+import com.google.devtools.ksp.symbol.KSNode
+import com.google.devtools.ksp.symbol.KSTypeReference
+import com.google.devtools.ksp.symbol.KSValueParameter
+import com.google.devtools.ksp.symbol.KSVisitor
+import com.google.devtools.ksp.symbol.Location
+import com.google.devtools.ksp.symbol.NonExistLocation
+import com.google.devtools.ksp.symbol.Origin
+import com.google.devtools.ksp.symbol.impl.binary.KSAnnotationDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.binary.KSTypeReferenceDescriptorImpl
+import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
+import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
+import org.jetbrains.kotlin.resolve.calls.components.isVararg
+
+class KSValueParameterSyntheticImpl(val owner: KSAnnotated?, resolve: () -> ValueParameterDescriptor?) :
+ KSValueParameter {
+
+ companion object :
+ KSObjectCache<Pair<KSAnnotated?, () -> ValueParameterDescriptor?>, KSValueParameterSyntheticImpl>() {
+ fun getCached(owner: KSAnnotated? = null, resolve: () -> ValueParameterDescriptor?) =
+ KSValueParameterSyntheticImpl.cache.getOrPut(Pair(owner, resolve)) {
+ KSValueParameterSyntheticImpl(owner, resolve)
+ }
+ }
+
+ private val descriptor by lazy {
+ resolve() ?: throw IllegalStateException("Failed to resolve for synthetic value parameter, $ExceptionMessage")
+ }
+
+ override val name: KSName? by lazy {
+ KSNameImpl.getCached(descriptor.name.asString())
+ }
+
+ override val type: KSTypeReference by lazy {
+ KSTypeReferenceDescriptorImpl.getCached(descriptor.type, origin, this)
+ }
+
+ override val isVararg: Boolean = descriptor.isVararg
+
+ override val isNoInline: Boolean = descriptor.isNoinline
+
+ override val isCrossInline: Boolean = descriptor.isCrossinline
+
+ override val isVal: Boolean = !descriptor.isVar
+
+ override val isVar: Boolean = descriptor.isVar
+
+ override val hasDefault: Boolean = descriptor.hasDefaultValue()
+
+ override val annotations: Sequence<KSAnnotation> by lazy {
+ descriptor.annotations.asSequence()
+ .map { KSAnnotationDescriptorImpl.getCached(it, this) }.plus(this.findAnnotationFromUseSiteTarget())
+ }
+
+ override val origin: Origin = Origin.SYNTHETIC
+
+ override val location: Location = NonExistLocation
+
+ override val parent: KSNode? = owner
+
+ override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R {
+ return visitor.visitValueParameter(this, data)
+ }
+
+ override fun toString(): String {
+ return name?.asString() ?: "_"
+ }
+}
diff --git a/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt
new file mode 100644
index 00000000..4e19baf1
--- /dev/null
+++ b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/utils.kt
@@ -0,0 +1,559 @@
+/*
+ * 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.symbol.impl
+
+import com.google.devtools.ksp.BinaryClassInfoCache
+import com.google.devtools.ksp.ExceptionMessage
+import com.google.devtools.ksp.KspExperimental
+import com.google.devtools.ksp.processing.impl.ResolverImpl
+import com.google.devtools.ksp.processing.impl.workaroundForNested
+import com.google.devtools.ksp.symbol.*
+import com.google.devtools.ksp.symbol.Variance
+import com.google.devtools.ksp.symbol.impl.binary.KSClassDeclarationDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.binary.KSDeclarationDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.binary.KSFunctionDeclarationDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.binary.KSPropertyDeclarationDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.binary.KSTypeArgumentDescriptorImpl
+import com.google.devtools.ksp.symbol.impl.java.*
+import com.google.devtools.ksp.symbol.impl.kotlin.*
+import com.google.devtools.ksp.symbol.impl.synthetic.KSPropertyGetterSyntheticImpl
+import com.google.devtools.ksp.symbol.impl.synthetic.KSPropertySetterSyntheticImpl
+import com.google.devtools.ksp.symbol.impl.synthetic.KSValueParameterSyntheticImpl
+import com.intellij.psi.*
+import com.intellij.psi.impl.light.LightMethod
+import com.intellij.psi.impl.source.PsiClassImpl
+import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMapper
+import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.load.java.descriptors.JavaClassConstructorDescriptor
+import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
+import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver
+import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
+import org.jetbrains.kotlin.load.java.structure.impl.JavaConstructorImpl
+import org.jetbrains.kotlin.load.java.structure.impl.JavaMethodImpl
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaField
+import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaMethodBase
+import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
+import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
+import org.jetbrains.kotlin.load.kotlin.getContainingKotlinJvmBinaryClass
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.psi.*
+import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
+import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
+import org.jetbrains.kotlin.resolve.descriptorUtil.getOwnerForEffectiveDispatchReceiverParameter
+import org.jetbrains.kotlin.resolve.source.getPsi
+import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
+import org.jetbrains.kotlin.types.*
+import java.util.*
+import kotlin.Comparator
+import kotlin.collections.ArrayDeque
+
+fun PsiElement.findParentAnnotated(): KSAnnotated? {
+ var parent = when (this) {
+ // Unfortunately, LightMethod doesn't implement parent.
+ is LightMethod -> this.containingClass
+ else -> this.parent
+ }
+
+ while (parent != null && parent !is KtDeclaration && parent !is KtFile && parent !is PsiClass &&
+ parent !is PsiMethod && parent !is PsiJavaFile && parent !is KtTypeAlias
+ ) {
+ parent = parent.parent
+ }
+
+ return when (parent) {
+ is KtClassOrObject -> KSClassDeclarationImpl.getCached(parent)
+ is KtFile -> KSFileImpl.getCached(parent)
+ is KtFunction -> KSFunctionDeclarationImpl.getCached(parent)
+ is PsiClass -> KSClassDeclarationJavaImpl.getCached(parent)
+ is PsiJavaFile -> KSFileJavaImpl.getCached(parent)
+ is PsiMethod -> KSFunctionDeclarationJavaImpl.getCached(parent)
+ is KtProperty -> KSPropertyDeclarationImpl.getCached(parent)
+ is KtPropertyAccessor -> if (parent.isGetter) {
+ KSPropertyGetterImpl.getCached(parent)
+ } else {
+ KSPropertySetterImpl.getCached(parent)
+ }
+ is KtTypeAlias -> KSTypeAliasImpl.getCached(parent)
+ else -> null
+ }
+}
+
+fun PsiElement.findParentDeclaration(): KSDeclaration? {
+ return this.findParentAnnotated() as? KSDeclaration
+}
+
+fun PsiElement.toLocation(): Location {
+ val file = this.containingFile
+ val document = ResolverImpl.instance!!.psiDocumentManager.getDocument(file) ?: return NonExistLocation
+ return FileLocation(file.virtualFile.path, document.getLineNumber(this.textOffset) + 1)
+}
+
+// TODO: handle local functions/classes correctly
+fun Sequence<KtElement>.getKSDeclarations(): Sequence<KSDeclaration> =
+ this.mapNotNull {
+ when (it) {
+ is KtFunction -> KSFunctionDeclarationImpl.getCached(it)
+ is KtProperty -> KSPropertyDeclarationImpl.getCached(it)
+ is KtClassOrObject -> KSClassDeclarationImpl.getCached(it)
+ is KtTypeAlias -> KSTypeAliasImpl.getCached(it)
+ else -> null
+ }
+ }
+
+fun List<PsiElement>.getKSJavaDeclarations() =
+ this.mapNotNull {
+ when (it) {
+ is PsiClass -> KSClassDeclarationJavaImpl.getCached(it)
+ is PsiMethod -> KSFunctionDeclarationJavaImpl.getCached(it)
+ is PsiField -> KSPropertyDeclarationJavaImpl.getCached(it)
+ else -> null
+ }
+ }
+
+fun org.jetbrains.kotlin.types.Variance.toKSVariance(): Variance {
+ return when (this) {
+ org.jetbrains.kotlin.types.Variance.IN_VARIANCE -> Variance.CONTRAVARIANT
+ org.jetbrains.kotlin.types.Variance.OUT_VARIANCE -> Variance.COVARIANT
+ org.jetbrains.kotlin.types.Variance.INVARIANT -> Variance.INVARIANT
+ else -> throw IllegalStateException("Unexpected variance value $this, $ExceptionMessage")
+ }
+}
+
+private fun KSTypeReference.toKotlinType() = (resolve() as? KSTypeImpl)?.kotlinType
+
+// returns null if error
+internal fun KotlinType.replaceTypeArguments(newArguments: List<KSTypeArgument>): KotlinType? {
+ if (newArguments.isNotEmpty() && this.arguments.size != newArguments.size)
+ return null
+ return replace(
+ newArguments.mapIndexed { index, ksTypeArgument ->
+ val variance = when (ksTypeArgument.variance) {
+ Variance.INVARIANT -> org.jetbrains.kotlin.types.Variance.INVARIANT
+ Variance.COVARIANT -> org.jetbrains.kotlin.types.Variance.OUT_VARIANCE
+ Variance.CONTRAVARIANT -> org.jetbrains.kotlin.types.Variance.IN_VARIANCE
+ Variance.STAR -> return@mapIndexed StarProjectionImpl(constructor.parameters[index])
+ }
+
+ val type = when (ksTypeArgument) {
+ is KSTypeArgumentKtImpl, is KSTypeArgumentJavaImpl, is KSTypeArgumentLiteImpl -> ksTypeArgument.type!!
+ is KSTypeArgumentDescriptorImpl -> return@mapIndexed ksTypeArgument.descriptor
+ else -> throw IllegalStateException(
+ "Unexpected psi for type argument: ${ksTypeArgument.javaClass}, $ExceptionMessage"
+ )
+ }.toKotlinType() ?: return null
+
+ TypeProjectionImpl(variance, type)
+ }
+ )
+}
+
+internal fun FunctionDescriptor.toKSDeclaration(): KSDeclaration {
+ if (this.kind != CallableMemberDescriptor.Kind.DECLARATION)
+ return KSFunctionDeclarationDescriptorImpl.getCached(this)
+ val psi = this.findPsi() ?: return KSFunctionDeclarationDescriptorImpl.getCached(this)
+ // Java default constructor has a kind DECLARATION of while still being synthetic.
+ if (psi is PsiClassImpl && this is JavaClassConstructorDescriptor) {
+ return KSFunctionDeclarationDescriptorImpl.getCached(this)
+ }
+ return when (psi) {
+ is KtFunction -> KSFunctionDeclarationImpl.getCached(psi)
+ is PsiMethod -> KSFunctionDeclarationJavaImpl.getCached(psi)
+ is KtProperty -> KSPropertyDeclarationImpl.getCached(psi)
+ else -> throw IllegalStateException("unexpected psi: ${psi.javaClass}")
+ }
+}
+
+internal fun PropertyDescriptor.toKSPropertyDeclaration(): KSPropertyDeclaration {
+ if (this.kind != CallableMemberDescriptor.Kind.DECLARATION)
+ return KSPropertyDeclarationDescriptorImpl.getCached(this)
+ val psi = this.findPsi() ?: return KSPropertyDeclarationDescriptorImpl.getCached(this)
+ return when (psi) {
+ is KtProperty -> KSPropertyDeclarationImpl.getCached(psi)
+ is KtParameter -> KSPropertyDeclarationParameterImpl.getCached(psi)
+ is PsiField -> KSPropertyDeclarationJavaImpl.getCached(psi)
+ is PsiMethod -> {
+ // happens when a java class implements a kotlin interface that declares properties.
+ KSPropertyDeclarationDescriptorImpl.getCached(this)
+ }
+ else -> throw IllegalStateException("unexpected psi: ${psi.javaClass}")
+ }
+}
+
+/**
+ * @see KSFunctionDeclaration.findOverridee / [KSPropertyDeclaration.findOverridee] for docs.
+ */
+internal inline fun <reified T : CallableMemberDescriptor> T.findClosestOverridee(): T? {
+ // When there is an intermediate class between the overridden and our function, we might receive
+ // a FAKE_OVERRIDE function which is not desired as we are trying to find the actual
+ // declared method.
+
+ // we also want to return the closes function declaration. That is either the closest
+ // class / interface method OR in case of equal distance (e.g. diamon dinheritance), pick the
+ // one declared first in the code.
+
+ (getOwnerForEffectiveDispatchReceiverParameter() as? ClassDescriptor)?.defaultType?.let {
+ ResolverImpl.instance!!.incrementalContext.recordLookupWithSupertypes(it)
+ }
+
+ val queue = ArrayDeque<T>()
+ queue.add(this)
+
+ while (queue.isNotEmpty()) {
+ val current = queue.removeFirst()
+ ResolverImpl.instance!!.incrementalContext.recordLookupForCallableMemberDescriptor(current.original)
+ val overriddenDescriptors: Collection<T> = current.original.overriddenDescriptors.filterIsInstance<T>()
+ overriddenDescriptors.firstOrNull {
+ it.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE
+ }?.let {
+ ResolverImpl.instance!!.incrementalContext.recordLookupForCallableMemberDescriptor(it.original)
+ return it.original as T?
+ }
+ // if all methods are fake, add them to the queue
+ queue.addAll(overriddenDescriptors)
+ }
+ return null
+}
+
+internal fun ModuleClassResolver.resolveContainingClass(psiMethod: PsiMethod): ClassDescriptor? {
+ return if (psiMethod.isConstructor) {
+ resolveClass(JavaConstructorImpl(psiMethod).containingClass.apply { workaroundForNested() })
+ } else {
+ resolveClass(JavaMethodImpl(psiMethod).containingClass.apply { workaroundForNested() })
+ }
+}
+
+internal fun getInstanceForCurrentRound(node: KSNode): KSNode? {
+ return when (node.origin) {
+ Origin.KOTLIN_LIB, Origin.JAVA_LIB -> null
+ else -> when (node) {
+ is KSClassDeclarationImpl -> KSClassDeclarationImpl.getCached(node.ktClassOrObject)
+ is KSFileImpl -> KSFileImpl.getCached(node.file)
+ is KSFunctionDeclarationImpl -> KSFunctionDeclarationImpl.getCached(node.ktFunction)
+ is KSPropertyDeclarationImpl -> KSPropertyDeclarationImpl.getCached(node.ktProperty)
+ is KSPropertyGetterImpl -> KSPropertyGetterImpl.getCached(node.ktPropertyAccessor)
+ is KSPropertySetterImpl -> KSPropertySetterImpl.getCached(node.ktPropertyAccessor)
+ is KSTypeAliasImpl -> KSTypeAliasImpl.getCached(node.ktTypeAlias)
+ is KSTypeArgumentLiteImpl -> KSTypeArgumentLiteImpl.getCached(node.type, node.variance)
+ is KSTypeArgumentKtImpl -> KSTypeArgumentKtImpl.getCached(node.ktTypeArgument)
+ is KSTypeParameterImpl -> KSTypeParameterImpl.getCached(node.ktTypeParameter)
+ is KSTypeReferenceImpl -> KSTypeReferenceImpl.getCached(node.ktTypeReference)
+ is KSValueParameterImpl -> KSValueParameterImpl.getCached(node.ktParameter)
+ is KSClassDeclarationJavaEnumEntryImpl -> KSClassDeclarationJavaEnumEntryImpl.getCached(node.psi)
+ is KSClassDeclarationJavaImpl -> KSClassDeclarationJavaImpl.getCached(node.psi)
+ is KSFileJavaImpl -> KSFileJavaImpl.getCached(node.psi)
+ is KSFunctionDeclarationJavaImpl -> KSFunctionDeclarationJavaImpl.getCached(node.psi)
+ is KSPropertyDeclarationJavaImpl -> KSPropertyDeclarationJavaImpl.getCached(node.psi)
+ is KSTypeArgumentJavaImpl -> KSTypeArgumentJavaImpl.getCached(node.psi, node.parent)
+ is KSTypeParameterJavaImpl -> KSTypeParameterJavaImpl.getCached(node.psi)
+ is KSTypeReferenceJavaImpl ->
+ KSTypeReferenceJavaImpl.getCached(node.psi, (node.parent as? KSAnnotated)?.getInstanceForCurrentRound())
+ is KSValueParameterJavaImpl -> KSValueParameterJavaImpl.getCached(node.psi)
+ is KSPropertyGetterSyntheticImpl -> KSPropertyGetterSyntheticImpl.getCached(node.ksPropertyDeclaration)
+ is KSPropertySetterSyntheticImpl -> KSPropertySetterSyntheticImpl.getCached(node.ksPropertyDeclaration)
+ is KSValueParameterSyntheticImpl ->
+ KSPropertySetterImpl.getCached(node.owner as KtPropertyAccessor).parameter
+ is KSAnnotationJavaImpl -> KSAnnotationJavaImpl.getCached(node.psi)
+ is KSAnnotationImpl -> KSAnnotationImpl.getCached(node.ktAnnotationEntry)
+ is KSClassifierReferenceJavaImpl -> KSClassifierReferenceJavaImpl.getCached(node.psi, node.parent)
+ is KSValueArgumentJavaImpl ->
+ KSValueArgumentJavaImpl.getCached(node.name, node.value, getInstanceForCurrentRound(node.parent!!))
+ else -> null
+ }
+ }
+}
+
+internal fun KSAnnotated.getInstanceForCurrentRound(): KSAnnotated? = getInstanceForCurrentRound(this) as? KSAnnotated
+
+/**
+ * Helper class to read the order of fields/methods in a .class file compiled from Kotlin.
+ *
+ * When a compiled Kotlin class is read from descriptors, the order of fields / methods do not match
+ * the order in the original source file (or the .class file).
+ * This helper class reads the order from the binary class (using the visitor API) and allows
+ * [KSClassDeclarationDescriptorImpl] to sort its declarations based on the .class file.
+ *
+ * Note that the ordering is relevant only for fields and methods. For any other declaration, the
+ * order that was returned from the descriptor API is kept.
+ *
+ * see: https://github.com/google/ksp/issues/250
+ */
+@KspExperimental
+internal class DeclarationOrdering(
+ binaryClass: KotlinJvmBinaryClass
+) : KotlinJvmBinaryClass.MemberVisitor {
+ // Map of fieldName -> Order
+ private val fieldOrdering = mutableMapOf<String, Int>()
+ // Map of method name to (jvm desc -> Order) map
+ // multiple methods might have the same name, hence we need to use signature matching for
+ // methods. That being said, we only do it when we find multiple methods with the same name
+ // otherwise, there is no reason to compute the jvm signature.
+ private val methodOrdering = mutableMapOf<String, MutableMap<String, Int>>()
+ // This map is built while we are sorting to ensure for the same declaration, we return the same
+ // order, in case it is not found in fields / methods.
+ private val declOrdering = IdentityHashMap<KSDeclaration, Int>()
+ // Helper class to generate ids that can be used for comparison.
+ private val orderProvider = OrderProvider()
+
+ init {
+ binaryClass.visitMembers(this, null)
+ orderProvider.seal()
+ }
+
+ val comparator = Comparator<KSDeclarationDescriptorImpl> { first, second ->
+ getOrder(first).compareTo(getOrder(second))
+ }
+
+ private fun getOrder(decl: KSDeclarationDescriptorImpl): Int {
+ return declOrdering.getOrPut(decl) {
+ when (decl) {
+ is KSPropertyDeclarationDescriptorImpl -> {
+ fieldOrdering[decl.simpleName.asString()]?.let {
+ return@getOrPut it
+ }
+ // might be a property without backing field. Use method ordering instead
+ decl.getter?.let { getter ->
+ return@getOrPut findMethodOrder(
+ ResolverImpl.instance!!.getJvmName(getter).toString()
+ ) {
+ ResolverImpl.instance!!.mapToJvmSignature(getter)
+ }
+ }
+ decl.setter?.let { setter ->
+ return@getOrPut findMethodOrder(
+ ResolverImpl.instance!!.getJvmName(setter).toString()
+ ) {
+ ResolverImpl.instance!!.mapToJvmSignature(setter)
+ }
+ }
+ orderProvider.next(decl)
+ }
+ is KSFunctionDeclarationDescriptorImpl -> {
+ findMethodOrder(
+ ResolverImpl.instance!!.getJvmName(decl).toString()
+ ) {
+ ResolverImpl.instance!!.mapToJvmSignature(decl).toString()
+ }
+ }
+ else -> orderProvider.nextIgnoreSealed()
+ }
+ }
+ }
+
+ private inline fun findMethodOrder(
+ jvmName: String,
+ crossinline getJvmDesc: () -> String
+ ): Int {
+ val methods = methodOrdering[jvmName]
+ // if there is 1 method w/ that name, just return.
+ // otherwise, we need signature matching
+ return when {
+ methods == null -> {
+ orderProvider.next(jvmName)
+ }
+ methods.size == 1 -> {
+ // only 1 method with this name, return it, no reason to resolve jvm
+ // signature
+ methods.values.first()
+ }
+ else -> {
+ // need to match using the jvm signature
+ val jvmDescriptor = getJvmDesc()
+ methods.getOrPut(jvmDescriptor) {
+ orderProvider.next(jvmName)
+ }
+ }
+ }
+ }
+
+ override fun visitField(
+ name: Name,
+ desc: String,
+ initializer: Any?
+ ): KotlinJvmBinaryClass.AnnotationVisitor? {
+ fieldOrdering.getOrPut(name.asString()) {
+ orderProvider.next(name)
+ }
+ return null
+ }
+
+ override fun visitMethod(
+ name: Name,
+ desc: String
+ ): KotlinJvmBinaryClass.MethodAnnotationVisitor? {
+ methodOrdering.getOrPut(name.asString()) {
+ mutableMapOf()
+ }.put(desc, orderProvider.next(name))
+ return null
+ }
+
+ /**
+ * Helper class to generate order values for items.
+ * Each time we see a new declaration, we give it an increasing order.
+ *
+ * This provider can also run in STRICT MODE to ensure that if we don't find an expected value
+ * during sorting, we can crash instead of picking the next ID. For now, it is only used for
+ * testing.
+ */
+ private class OrderProvider {
+ private var nextId = 0
+ private var sealed = false
+
+ /**
+ * Seals the provider, preventing it from generating new IDs if [STRICT_MODE] is enabled.
+ */
+ fun seal() {
+ sealed = true
+ }
+
+ /**
+ * Returns the next available order value.
+ *
+ * @param ref Used for logging if the data is sealed and we shouldn't provide a new order.
+ */
+ fun next(ref: Any): Int {
+ check(!sealed || !STRICT_MODE) {
+ "couldn't find item $ref"
+ }
+ return nextId ++
+ }
+
+ /**
+ * Returns the next ID without checking whether the model is sealed or not. This is useful
+ * for declarations where we don't care about the order (e.g. inner class declarations).
+ */
+ fun nextIgnoreSealed(): Int {
+ return nextId ++
+ }
+ }
+ companion object {
+ /**
+ * Used in tests to prevent fallback behavior of creating a new ID when we cannot find the
+ * order.
+ */
+ var STRICT_MODE = false
+ }
+}
+
+/**
+ * Same as KSDeclarationContainer.declarations, but sorted by declaration order in the source.
+ *
+ * Note that this is SLOW. AVOID IF POSSIBLE.
+ */
+@KspExperimental
+internal val KSDeclarationContainer.declarationsInSourceOrder: Sequence<KSDeclaration>
+ get() {
+ // Only Kotlin libs can be out of order.
+ if (this !is KSClassDeclarationDescriptorImpl || origin != Origin.KOTLIN_LIB)
+ return declarations
+
+ val declarationOrdering = (
+ (descriptor as? DeserializedClassDescriptor)?.source as? KotlinJvmBinarySourceElement
+ )?.binaryClass?.let {
+ DeclarationOrdering(it)
+ } ?: return declarations
+
+ return (declarations as? Sequence<KSDeclarationDescriptorImpl>)?.sortedWith(declarationOrdering.comparator)
+ ?: declarations
+ }
+
+internal val KSPropertyDeclaration.jvmAccessFlag: Int
+ get() = when (origin) {
+ Origin.KOTLIN_LIB -> {
+ val descriptor = (this as KSPropertyDeclarationDescriptorImpl).descriptor
+ val kotlinBinaryJavaClass = descriptor.getContainingKotlinJvmBinaryClass()
+ // 0 if no backing field
+ kotlinBinaryJavaClass?.let {
+ BinaryClassInfoCache.getCached(it).fieldAccFlags.get(this.simpleName.asString()) ?: 0
+ } ?: 0
+ }
+ Origin.JAVA_LIB -> {
+ val descriptor = (this as KSPropertyDeclarationDescriptorImpl).descriptor
+ ((descriptor.source as? JavaSourceElement)?.javaElement as? BinaryJavaField)?.access ?: 0
+ }
+ else -> throw IllegalStateException("this function expects only KOTLIN_LIB or JAVA_LIB")
+ }
+
+internal val KSFunctionDeclaration.jvmAccessFlag: Int
+ get() = when (origin) {
+ Origin.KOTLIN_LIB -> {
+ val jvmDesc = ResolverImpl.instance!!.mapToJvmSignatureInternal(this)
+ val descriptor = (this as KSFunctionDeclarationDescriptorImpl).descriptor
+ // Companion.<init> doesn't have containing KotlinJvmBinaryClass.
+ val kotlinBinaryJavaClass = descriptor.getContainingKotlinJvmBinaryClass()
+ kotlinBinaryJavaClass?.let {
+ BinaryClassInfoCache.getCached(it).methodAccFlags.get(this.simpleName.asString() + jvmDesc) ?: 0
+ } ?: 0
+ }
+ Origin.JAVA_LIB -> {
+ val descriptor = (this as KSFunctionDeclarationDescriptorImpl).descriptor
+ // Some functions, like `equals` in builtin types, doesn't have source.
+ ((descriptor.source as? JavaSourceElement)?.javaElement as? BinaryJavaMethodBase)?.access ?: 0
+ }
+ else -> throw IllegalStateException("this function expects only KOTLIN_LIB or JAVA_LIB")
+ }
+
+// Compiler subtype checking does not convert Java types to Kotlin types, while getting super types
+// from a java type does the conversion, therefore resulting in subtype checking for Java types to fail.
+// Check if candidate super type is a Java type, convert to Kotlin type for subtype checking.
+// Also, if the type is a generic deserialized type, that actually represents a function type,
+// a conversion is also required to yield a type with a correctly recognised descriptor.
+internal fun KotlinType.convertKotlinType(): KotlinType {
+ val declarationDescriptor = this.constructor.declarationDescriptor
+ val base = if (declarationDescriptor?.shouldMapToKotlinForAssignabilityCheck() == true) {
+ JavaToKotlinClassMapper
+ .mapJavaToKotlin(declarationDescriptor.fqNameSafe, ResolverImpl.instance!!.module.builtIns)
+ ?.defaultType
+ ?.replace(this.arguments)
+ ?: this
+ } else this
+ val newarguments =
+ base.arguments.map { if (it !is StarProjectionImpl) it.replaceType(it.type.convertKotlinType()) else it }
+ val upperBound = if (base.unwrap() is FlexibleType) {
+ (base.unwrap() as FlexibleType).upperBound.arguments
+ .map { if (it !is StarProjectionImpl) it.replaceType(it.type.convertKotlinType()) else it }
+ } else newarguments
+ return base.replace(
+ newarguments,
+ annotations,
+ upperBound
+ )
+}
+
+private fun ClassifierDescriptor.shouldMapToKotlinForAssignabilityCheck(): Boolean {
+ return when (this) {
+ is JavaClassDescriptor -> true // All java types need to be mapped to kotlin
+ is DeserializedDescriptor -> {
+ // If this is a generic deserialized type descriptor, which actually is a kotlin function type.
+ // This may be the case if the client explicitly mapped a kotlin function type to the JVM one.
+ // Such types need to be remapped to be represented by a correct function class descriptor.
+ fqNameSafe.parent().asString() == "kotlin.jvm.functions"
+ }
+ else -> false
+ }
+}
+
+fun DeclarationDescriptor.findPsi(): PsiElement? {
+ // For synthetic members.
+ if ((this is CallableMemberDescriptor) && this.kind != CallableMemberDescriptor.Kind.DECLARATION) return null
+ val psi = (this as? DeclarationDescriptorWithSource)?.source?.getPsi() ?: return null
+ if (psi is KtElement) return psi
+
+ // Find Java PSIs loaded by KSP
+ val containingFile = ResolverImpl.instance!!.findPsiJavaFile(psi.containingFile.virtualFile.path) ?: return null
+ val leaf = containingFile.findElementAt(psi.textOffset) ?: return null
+ return leaf.parentsWithSelf.firstOrNull { psi.manager.areElementsEquivalent(it, psi) }
+}