aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiaxiang Chen <jiaxiang@google.com>2023-01-19 11:12:13 -0800
committerKSP Auto Pick <kotlin-symbol-processing@google.com>2023-01-19 22:47:08 +0000
commit4b299afe9b7c323c3a72030a977c50658cad9f8a (patch)
treefdc104a29fd350f9de5fb9f2df55efcaca6bbbd2
parent03b0374ee3ccfde8891a42c1fafc919020c376b3 (diff)
downloadksp-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)
-rw-r--r--api/api.base9
-rw-r--r--api/src/main/kotlin/com/google/devtools/ksp/symbol/KSDefNonNullReference.kt13
-rw-r--r--api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitor.kt2
-rw-r--r--api/src/main/kotlin/com/google/devtools/ksp/symbol/KSVisitorVoid.kt3
-rw-r--r--api/src/main/kotlin/com/google/devtools/ksp/visitor/KSDefaultVisitor.kt5
-rw-r--r--api/src/main/kotlin/com/google/devtools/ksp/visitor/KSEmptyVisitor.kt4
-rw-r--r--api/src/main/kotlin/com/google/devtools/ksp/visitor/KSTopDownVisitor.kt5
-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/KSTypeReferenceImpl.kt15
-rw-r--r--integration-tests/src/test/resources/playground/test-processor/src/main/kotlin/TestProcessor.kt5
-rw-r--r--test-utils/src/main/kotlin/com/google/devtools/ksp/processor/ReferenceElementProcessor.kt10
-rw-r--r--test-utils/testData/api/referenceElement.kt5
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>()