Skip to content

Commit

Permalink
Support Definitely non null type language feature.
Browse files Browse the repository at this point in the history
* Add api for definitely non null type element.
* Implement definitely non null type element for FE1.0.

fixes google#1127
  • Loading branch information
neetopia committed Jan 19, 2023
1 parent 3bbd53b commit 23e3ce4
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 13 deletions.
9 changes: 9 additions & 0 deletions api/api.base
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,7 @@ open class KSVisitorVoid : KSVisitor<Unit, Unit> {

override fun visitValueArgument(valueArgument: KSValueArgument, data: Unit) {
}

override fun visitDefNonNullReference(reference: KSDefNonNullReference, data: Unit) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
}
Original file line number Diff line number Diff line change
Expand Up @@ -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>() {
Expand Down Expand Up @@ -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")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 5 additions & 0 deletions test-utils/testData/api/referenceElement.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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>()

Expand Down

0 comments on commit 23e3ce4

Please sign in to comment.