diff options
author | Jiaxiang Chen <jiaxiang@google.com> | 2023-01-19 11:12:13 -0800 |
---|---|---|
committer | KSP Auto Pick <kotlin-symbol-processing@google.com> | 2023-01-19 22:47:08 +0000 |
commit | 4b299afe9b7c323c3a72030a977c50658cad9f8a (patch) | |
tree | fdc104a29fd350f9de5fb9f2df55efcaca6bbbd2 | |
parent | 03b0374ee3ccfde8891a42c1fafc919020c376b3 (diff) | |
download | ksp-4b299afe9b7c323c3a72030a977c50658cad9f8a.tar.gz |
Support Definitely non null type language feature.
* Add api for definitely non null type element.
* Implement definitely non null type element for FE1.0.
fixes #1127
(cherry picked from commit c048c6b03374e86379fed40d47be6af5303cb668)
12 files changed, 104 insertions, 13 deletions
diff --git a/api/api.base b/api/api.base index 60c2a8db..9884b771 100644 --- a/api/api.base +++ b/api/api.base @@ -325,6 +325,12 @@ package com.google.devtools.ksp.symbol { property @NonNull public abstract kotlin.sequences.Sequence<com.google.devtools.ksp.symbol.KSDeclaration> declarations; } + public interface KSDefNonNullReference extends com.google.devtools.ksp.symbol.KSReferenceElement { + method public default <D, R> R accept(@NonNull com.google.devtools.ksp.symbol.KSVisitor<D,R> visitor, @Nullable D data); + method @NonNull public com.google.devtools.ksp.symbol.KSClassifierReference getEnclosedType(); + property @NonNull public abstract com.google.devtools.ksp.symbol.KSClassifierReference enclosedType; + } + public interface KSDynamicReference extends com.google.devtools.ksp.symbol.KSReferenceElement { } @@ -531,6 +537,7 @@ package com.google.devtools.ksp.symbol { method public R visitClassifierReference(@NonNull com.google.devtools.ksp.symbol.KSClassifierReference reference, @Nullable D data); method public R visitDeclaration(@NonNull com.google.devtools.ksp.symbol.KSDeclaration declaration, @Nullable D data); method public R visitDeclarationContainer(@NonNull com.google.devtools.ksp.symbol.KSDeclarationContainer declarationContainer, @Nullable D data); + method public R visitDefNonNullReference(@NonNull com.google.devtools.ksp.symbol.KSDefNonNullReference reference, @Nullable D data); method public R visitDynamicReference(@NonNull com.google.devtools.ksp.symbol.KSDynamicReference reference, @Nullable D data); method public R visitFile(@NonNull com.google.devtools.ksp.symbol.KSFile file, @Nullable D data); method public R visitFunctionDeclaration(@NonNull com.google.devtools.ksp.symbol.KSFunctionDeclaration function, @Nullable D data); @@ -559,6 +566,7 @@ package com.google.devtools.ksp.symbol { method public void visitClassifierReference(@NonNull com.google.devtools.ksp.symbol.KSClassifierReference reference, @NonNull kotlin.Unit data); method public void visitDeclaration(@NonNull com.google.devtools.ksp.symbol.KSDeclaration declaration, @NonNull kotlin.Unit data); method public void visitDeclarationContainer(@NonNull com.google.devtools.ksp.symbol.KSDeclarationContainer declarationContainer, @NonNull kotlin.Unit data); + method public void visitDefNonNullReference(@NonNull com.google.devtools.ksp.symbol.KSDefNonNullReference reference, @NonNull kotlin.Unit data); method public void visitDynamicReference(@NonNull com.google.devtools.ksp.symbol.KSDynamicReference reference, @NonNull kotlin.Unit data); method public void visitFile(@NonNull com.google.devtools.ksp.symbol.KSFile file, @NonNull kotlin.Unit data); method public void visitFunctionDeclaration(@NonNull com.google.devtools.ksp.symbol.KSFunctionDeclaration function, @NonNull kotlin.Unit data); @@ -676,6 +684,7 @@ package com.google.devtools.ksp.visitor { method public R visitClassifierReference(@NonNull com.google.devtools.ksp.symbol.KSClassifierReference reference, @Nullable D data); method public R visitDeclaration(@NonNull com.google.devtools.ksp.symbol.KSDeclaration declaration, @Nullable D data); method public R visitDeclarationContainer(@NonNull com.google.devtools.ksp.symbol.KSDeclarationContainer declarationContainer, @Nullable D data); + method public R visitDefNonNullReference(@NonNull com.google.devtools.ksp.symbol.KSDefNonNullReference reference, @Nullable D data); method public R visitDynamicReference(@NonNull com.google.devtools.ksp.symbol.KSDynamicReference reference, @Nullable D data); method public R visitFile(@NonNull com.google.devtools.ksp.symbol.KSFile file, @Nullable D data); method public R visitFunctionDeclaration(@NonNull com.google.devtools.ksp.symbol.KSFunctionDeclaration function, @Nullable D data); diff --git a/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSDefNonNullReference.kt b/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSDefNonNullReference.kt new file mode 100644 index 00000000..6230fe6a --- /dev/null +++ b/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSDefNonNullReference.kt @@ -0,0 +1,13 @@ +package com.google.devtools.ksp.symbol + +interface KSDefNonNullReference : KSReferenceElement { + /** + * Enclosed reference element of the Definitely non null type. + * For a reference of `T & Any`, this returns `T`. + */ + val enclosedType: KSClassifierReference + + override fun <D, R> accept(visitor: KSVisitor<D, R>, data: D): R { + return visitor.visitDefNonNullReference(this, data) + } +} diff --git a/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitor.kt b/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitor.kt index 31c6b699..6ec4ca1f 100644 --- a/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitor.kt +++ b/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitor.kt @@ -67,4 +67,6 @@ interface KSVisitor<D, R> { fun visitValueArgument(valueArgument: KSValueArgument, data: D): R fun visitClassifierReference(reference: KSClassifierReference, data: D): R + + fun visitDefNonNullReference(reference: KSDefNonNullReference, data: D): R } diff --git a/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitorVoid.kt b/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitorVoid.kt index 3e8b6fca..1e729d95 100644 --- a/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitorVoid.kt +++ b/api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitorVoid.kt @@ -91,4 +91,7 @@ open class KSVisitorVoid : KSVisitor<Unit, Unit> { override fun visitValueArgument(valueArgument: KSValueArgument, data: Unit) { } + + override fun visitDefNonNullReference(reference: KSDefNonNullReference, data: Unit) { + } } diff --git a/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSDefaultVisitor.kt b/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSDefaultVisitor.kt index 2e9af220..19ea484f 100644 --- a/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSDefaultVisitor.kt +++ b/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSDefaultVisitor.kt @@ -107,6 +107,11 @@ abstract class KSDefaultVisitor<D, R> : KSEmptyVisitor<D, R>() { return super.visitClassifierReference(reference, data) } + override fun visitDefNonNullReference(reference: KSDefNonNullReference, data: D): R { + this.visitReferenceElement(reference, data) + return super.visitDefNonNullReference(reference, data) + } + override fun visitTypeArgument(typeArgument: KSTypeArgument, data: D): R { this.visitAnnotated(typeArgument, data) return super.visitTypeArgument(typeArgument, data) diff --git a/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSEmptyVisitor.kt b/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSEmptyVisitor.kt index 0bef8c5a..4704f81e 100644 --- a/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSEmptyVisitor.kt +++ b/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSEmptyVisitor.kt @@ -88,6 +88,10 @@ abstract class KSEmptyVisitor<D, R> : KSVisitor<D, R> { return defaultHandler(reference, data) } + override fun visitDefNonNullReference(reference: KSDefNonNullReference, data: D): R { + return defaultHandler(reference, data) + } + override fun visitReferenceElement(element: KSReferenceElement, data: D): R { return defaultHandler(element, data) } diff --git a/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSTopDownVisitor.kt b/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSTopDownVisitor.kt index 22acce5e..23c9736c 100644 --- a/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSTopDownVisitor.kt +++ b/api/src/main/kotlin/com/google/devtools/ksp/visitor/KSTopDownVisitor.kt @@ -126,6 +126,11 @@ abstract class KSTopDownVisitor<D, R> : KSDefaultVisitor<D, R>() { return super.visitClassifierReference(reference, data) } + override fun visitDefNonNullReference(reference: KSDefNonNullReference, data: D): R { + reference.enclosedType.accept(data) + return super.visitDefNonNullReference(reference, data) + } + override fun visitValueParameter(valueParameter: KSValueParameter, data: D): R { valueParameter.type?.accept(data) return super.visitValueParameter(valueParameter, data) 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/KSTypeReferenceImpl.kt b/compiler-plugin/src/main/kotlin/com/google/devtools/ksp/symbol/impl/kotlin/KSTypeReferenceImpl.kt index b129612c..9f751700 100644 --- 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 @@ -32,19 +32,7 @@ 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.KtAnnotationEntry -import org.jetbrains.kotlin.psi.KtClassOrObject -import org.jetbrains.kotlin.psi.KtDynamicType -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtFunctionType -import org.jetbrains.kotlin.psi.KtNullableType -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtTypeAlias -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.KtTypeProjection -import org.jetbrains.kotlin.psi.KtTypeReference -import org.jetbrains.kotlin.psi.KtUserType +import org.jetbrains.kotlin.psi.* class KSTypeReferenceImpl private constructor(val ktTypeReference: KtTypeReference) : KSTypeReference { companion object : KSObjectCache<KtTypeReference, KSTypeReferenceImpl>() { @@ -124,6 +112,7 @@ class KSTypeReferenceImpl private constructor(val ktTypeReference: KtTypeReferen 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") } } diff --git a/integration-tests/src/test/resources/playground/test-processor/src/main/kotlin/TestProcessor.kt b/integration-tests/src/test/resources/playground/test-processor/src/main/kotlin/TestProcessor.kt index 9b922d68..4b5a3cb5 100644 --- a/integration-tests/src/test/resources/playground/test-processor/src/main/kotlin/TestProcessor.kt +++ b/integration-tests/src/test/resources/playground/test-processor/src/main/kotlin/TestProcessor.kt @@ -68,6 +68,11 @@ class TestProcessor : SymbolProcessor { override fun visitDynamicReference(reference: KSDynamicReference, data: String) { TODO("Not yet implemented") } + + override fun visitDefNonNullReference(reference: KSDefNonNullReference, data: String) { + TODO("Not yet implemented") + } + val visited = HashSet<Any>() private fun checkVisited(symbol: Any): Boolean { diff --git a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/ReferenceElementProcessor.kt b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/ReferenceElementProcessor.kt index 46a4ea47..c0843f36 100644 --- a/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/ReferenceElementProcessor.kt +++ b/test-utils/src/main/kotlin/com/google/devtools/ksp/processor/ReferenceElementProcessor.kt @@ -60,6 +60,16 @@ open class ReferenceElementProcessor : AbstractTestProcessor() { ) } + val defNonNullReferences = + references.filter { it.element is KSDefNonNullReference && it.origin == Origin.KOTLIN } + .sortedBy { it.toString() } + + defNonNullReferences.forEach { + results.add( + "KSDefNonNullReferenceImpl: Enclosed type of ${(it.element as KSDefNonNullReference).enclosedType}" + ) + } + val javaReferences = references.filter { it.element is KSClassifierReference && it.origin == Origin.JAVA } .sortedBy(::refName) for (i in javaReferences) { diff --git a/test-utils/testData/api/referenceElement.kt b/test-utils/testData/api/referenceElement.kt index 4f018fb1..513ad429 100644 --- a/test-utils/testData/api/referenceElement.kt +++ b/test-utils/testData/api/referenceElement.kt @@ -26,6 +26,7 @@ // KSClassifierReferenceDescriptorImpl: Qualifier of String is null // KSClassifierReferenceDescriptorImpl: Qualifier of Y is X // KSClassifierReferenceDescriptorImpl: Qualifier of Z<Int> is X<String> +// KSDefNonNullReferenceImpl: Enclosed type of T // KSClassifierReferenceJavaImpl: Qualifier of H is J<String> // KSClassifierReferenceJavaImpl: Qualifier of I is J // KSClassifierReferenceJavaImpl: Qualifier of Object is null @@ -52,6 +53,10 @@ class A<T1> { inner class C<T2> } +class DefNonNull<T> { + val u: T & Any +} + val x: A.B = A.B() val y: A<String>.C<Int> = A<String>().C<Int>() |